'Programming' category

« Older entries

Accomplish your new year's resolution of being more badass

I know what you're going through — I've done it all before.

The market is teeming with products that purport to help you meet your badassery quota.

First you do the shakes. Then, you go with the bars that say they're infused with the good stuff, but just seem to leave a slightly corrugated taste in your mouth. Finally, you're droppin' hard-earned dinero on a facility that you don't need or a professional badassery trainer whose appointments you desperately wish you could cancel.

But I'm here to tell you don't need to shell out cash-money to become more badass, my friends. Not anymore, thanks to the beauty of open source, the ES6 plans wiki page, and our delightful SpiderMonkey technical staff who are standing by to receive your calls for mentorship.

Allow me to explain.

Badass begets badass

You may have seen Badass JavaScript: self described as, "A showcase of awesome JavaScript code that pushes the boundaries of what's possible on the web." Check out their badass year in review if you haven't. (Some of the stuff that the interwebs has done with JavaScript even has @NeckbeardHacker envious.)

It probably won't surprise you, but do you know what those folks love? JavaScript evolution. There's nothing quite so refreshing as a fresh-squeezed JS language feature that removes that irritating itching-burning sensation. Sets that do what you mean! String repetition that you can use without copy/pasting from your last project! Inverse hyperbolic sine that you can use for... your... math! (Again, all of this is in the ES6 plans.)

I, for example, have wanted String.prototype.startsWith very badly, to the point that I've started washing people's window panes against their will as they exit highway 101. Around here, odds are that a programmer sees my sign and implements the thing just to stop me from bothering them again. (A little tactic that I call SpiderGuerilla warfare.)

Me, holding my SpiderGuerilla sign.

So what are you waiting for?

I know, you're probably already quite beefcake, but here's my three step plan:

  1. Watch the SpiderMonkey hacking intro.

  2. Pick out a bug from the ES6 plans.

  3. Come talk to great people on irc.mozilla.org in channel #jsapi (for example, cdleary, jorendorff, luke, or whoever else is in there) or comment in the bug — tell them that you're on a quest to become even more badass, describe a bug that you're interested in taking, and give a quick note on what you've done with the engine so far — for example, walking through the video in step 1! We'll find you a mentor who will get you started on the right track.

Don't miss out on this exclusive offer — SpiderMonkey contribution is not sold in stores.

In fact, if you act now, we'll throw in an IonMonkey shirt (or another Firefox shirt of equivalent awesomeness) and publish a blurb about your feature in Mozilla hacks. Of course, you can also have yourself added to about:credits, providing that's what you are into.

IonMonkey shirt.

This one-of-a-kind offer is too ridonk to pass up. Just listen to this testimonial from one of our badass contributors:

I started contributing to SpiderMonkey and now I can write a JIT compiler from scratch in a matter of days. BEEFCAKE!

@evilpies [Liberally paraphrased]

See you in the tubes!

Accomplish your new year's resolution of being more badass

I know what you're going through — I've done it all before.

The market is teeming with products that purport to help you meet your badassery quota.

First you do the shakes. Then, you go with the bars that say they're infused with the good stuff, but just seem to leave a slightly corrugated taste in your mouth. Finally, you're droppin' hard-earned dinero on a facility that you don't need or a professional badassery trainer whose appointments you desperately wish you could cancel.

But I'm here to tell you don't need to shell out cash-money to become more badass, my friends. Not anymore, thanks to the beauty of open source, the ES6 plans wiki page, and our delightful SpiderMonkey technical staff who are standing by to receive your calls for mentorship.

Allow me to explain.

Badass begets badass

You may have seen Badass JavaScript: self described as, "A showcase of awesome JavaScript code that pushes the boundaries of what's possible on the web." Check out their badass year in review if you haven't. (Some of the stuff that the interwebs has done with JavaScript even has @NeckbeardHacker envious.)

It probably won't surprise you, but do you know what those folks love? JavaScript evolution. There's nothing quite so refreshing as a fresh-squeezed JS language feature that removes that irritating itching-burning sensation. Sets that do what you mean! String repetition that you can use without copy/pasting from your last project! Inverse hyperbolic sine that you can use for... your... math! (Again, all of this is in the ES6 plans.)

I, for example, have wanted String.prototype.startsWith very badly, to the point that I've started washing people's window panes against their will as they exit highway 101. Around here, odds are that a programmer sees my sign and implements the thing just to stop me from bothering them again. (A little tactic that I call SpiderGuerilla warfare.)

Me, holding my SpiderGuerilla sign.

So what are you waiting for?

I know, you're probably already quite beefcake, but here's my three step plan:

  1. Watch the SpiderMonkey hacking intro.

  2. Pick out a bug from the ES6 plans.

  3. Come talk to great people on irc.mozilla.org in channel #jsapi (for example, cdleary, jorendorff, luke, or whoever else is in there) or comment in the bug — tell them that you're on a quest to become even more badass, describe a bug that you're interested in taking, and give a quick note on what you've done with the engine so far — for example, walking through the video in step 1! We'll find you a mentor who will get you started on the right track.

Don't miss out on this exclusive offer — SpiderMonkey contribution is not sold in stores.

In fact, if you act now, we'll throw in an IonMonkey shirt (or another Firefox shirt of equivalent awesomeness) and publish a blurb about your feature in Mozilla hacks. Of course, you can also have yourself added to about:credits, providing that's what you are into.

IonMonkey shirt.

This one-of-a-kind offer is too ridonk to pass up. Just listen to this testimonial from one of our badass contributors:

I started contributing to SpiderMonkey and now I can write a JIT compiler from scratch in a matter of days. BEEFCAKE!

@evilpies [Liberally paraphrased]

See you in the tubes!

C++, generic wrappers, and CRTP, oh MI!

Reading some of the original traits papers, I got to the part where they mention the conceptual difficulties inherent in multiple inheritance (MI), one of which is "factoring out generic wrappers". [*]

There's a footnote clarifying that, in practice, languages with MI actually do have other ways of accomplishing the factoring, and in reading that I remembered that the first time I actually understood CRTP (Curiously Recurring Template Pattern) was because I needed some generic wrappers.

Some folks were asking about CRTP on our IRC channel this past week, so I figured I'd share a quick walk-though.

Sometimes you want to be able to shove a method implementation onto a class, given that it has a few buiding blocks for you to work with. Let's say that there's some generic and formulaic way of making a delicious cake.

class CakeMaker
{
  public:
    Cake makeCake() {
        Ingredients ingredients = fetchIngredients();
        if (ingredients.spoiled())
            return Cake::Fail;

        BatterAndWhatnot batter = mixAndStuff(ingredients);
        Cake result = bake(batter);
        if (cake.burned())
            return Cake::Fail;

        return cake;
    }
};

This is supposed to be a reusable component for shoving a makeCake method onto another class that already has the necessary methods, fetchIngredients, mixAndStuff, and bake.

Great. So now let's say that we have two different cake makers, CakeFactory and PersonalChef — we want to just implement the necessary methods for CakeMaker in those and somehow shove the makeCake method onto their class definition as well. Maybe we can inherit from CakeMaker or something?

But here's the rub: CakeMaker can't exist. It is an invalid class definition that will not compile, because it refers to methods that it does not have.

cdleary@stretch:~$ g++ -c crtp.cpp
crtp.cpp: In member function ‘Cake CakeMaker::makeCake()’:
crtp.cpp:17:56: error: ‘fetchIngredients’ was not declared in this scope
crtp.cpp:21:62: error: ‘mixAndStuff’ was not declared in this scope
crtp.cpp:22:38: error: ‘bake’ was not declared in this scope

Luckily, C++ templates have this nice lazy instantiation property, where the code goes mostly unchecked by the compiler until you actually try to use it. So, if we just change our definition to:

template <typename T>
class CakeMaker
{
    // ...
};

GCC will accept it if we ask it to shut up a little bit (with -fpermissive), because we're thinking.

So now we take a look at our close friend, PersonalChef:

class PersonalChef
{
    Ingredients fetchIngredients();
    BatterAndWhatnot mixAndStuff(Ingredients);
    Cake bake(BatterAndWhatnot);
};

We want to shove the CakeMaker method onto his/her class definition. We could inherit from the CakeMaker and just pass it an arbitrary type T, like so:

class PersonalChef : public CakeMaker<int>
{
    // ...
};

But we need a way to wire up the methods that CakeMaker needs to the methods that PersonalChef actually has. And this is where we take the final step — via a stroke of intuition, let's pass in the type that actually has the methods on it, and use that type to refer to the method implementations within CakeMaker:

template <class Wrapped>
class CakeMaker
{
  public:
    Cake makeCake() {
        Wrapped *self = static_cast<Wrapped *>(this);
        Ingredients ingredients = self->fetchIngredients();
        if (ingredients.spoiled())
            return Cake::Fail;

        BatterAndWhatnot batter = self->mixAndStuff(ingredients);
        Cake result = self->bake(batter);
        if (result.burned())
            return Cake::Fail;

        return result;
    }
};

class PersonalChef : public CakeMaker<PersonalChef>
{
    Ingredients fetchIngredients();
    BatterAndWhatnot mixAndStuff(Ingredients);
    Cake bake(BatterAndWhatnot);

    friend class CakeMaker;
};

int main()
{
    PersonalChef chef;
    chef.makeCake();
    return 0;
}

Bam! Now it compiles normally. The CakeMaker is given PersonalChef as the template type argument, and the CakeMaker converts its this pointer for use as the PersonalChef type (which is valid in this case, since PersonalChef is a CakeMaker), which does implement the required methods!

This can also be used to enforce minimum interface requirements at compile time (as in the cross-platform macro assembler) without the use of virtual functions, which have a tendency to thwart inlining optimization.

Fun fact: it looks like we have about 90 virtual function declarations in the 190k lines of engine-related C/C++ code that cloc tells me are in the js/src directory.

Footnotes

[*]

Fun concept from the papers: the conceptual issue with MI is that classes are overloaded in their purpose: they are intended to serve both as units of code (implementation) reuse and for instantiation of actual objects.

C++, generic wrappers, and CRTP, oh MI!

Reading some of the original traits papers, I got to the part where they mention the conceptual difficulties inherent in multiple inheritance (MI), one of which is "factoring out generic wrappers". [*]

There's a footnote clarifying that, in practice, languages with MI actually do have other ways of accomplishing the factoring, and in reading that I remembered that the first time I actually understood CRTP (Curiously Recurring Template Pattern) was because I needed some generic wrappers.

Some folks were asking about CRTP on our IRC channel this past week, so I figured I'd share a quick walk-though.

Sometimes you want to be able to shove a method implementation onto a class, given that it has a few buiding blocks for you to work with. Let's say that there's some generic and formulaic way of making a delicious cake.

class CakeMaker
{
  public:
    Cake makeCake() {
        Ingredients ingredients = fetchIngredients();
        if (ingredients.spoiled())
            return Cake::Fail;

        BatterAndWhatnot batter = mixAndStuff(ingredients);
        Cake result = bake(batter);
        if (cake.burned())
            return Cake::Fail;

        return cake;
    }
};

This is supposed to be a reusable component for shoving a makeCake method onto another class that already has the necessary methods, fetchIngredients, mixAndStuff, and bake.

Great. So now let's say that we have two different cake makers, CakeFactory and PersonalChef — we want to just implement the necessary methods for CakeMaker in those and somehow shove the makeCake method onto their class definition as well. Maybe we can inherit from CakeMaker or something?

But here's the rub: CakeMaker can't exist. It is an invalid class definition that will not compile, because it refers to methods that it does not have.

cdleary@stretch:~$ g++ -c crtp.cpp
crtp.cpp: In member function ‘Cake CakeMaker::makeCake()’:
crtp.cpp:17:56: error: ‘fetchIngredients’ was not declared in this scope
crtp.cpp:21:62: error: ‘mixAndStuff’ was not declared in this scope
crtp.cpp:22:38: error: ‘bake’ was not declared in this scope

Luckily, C++ templates have this nice lazy instantiation property, where the code goes mostly unchecked by the compiler until you actually try to use it. So, if we just change our definition to:

template <typename T>
class CakeMaker
{
    // ...
};

GCC will accept it if we ask it to shut up a little bit (with -fpermissive), because we're thinking.

So now we take a look at our close friend, PersonalChef:

class PersonalChef
{
    Ingredients fetchIngredients();
    BatterAndWhatnot mixAndStuff(Ingredients);
    Cake bake(BatterAndWhatnot);
};

We want to shove the CakeMaker method onto his/her class definition. We could inherit from the CakeMaker and just pass it an arbitrary type T, like so:

class PersonalChef : public CakeMaker<int>
{
    // ...
};

But we need a way to wire up the methods that CakeMaker needs to the methods that PersonalChef actually has. And this is where we take the final step — via a stroke of intuition, let's pass in the type that actually has the methods on it, and use that type to refer to the method implementations within CakeMaker:

template <class Wrapped>
class CakeMaker
{
  public:
    Cake makeCake() {
        Wrapped *self = static_cast<Wrapped *>(this);
        Ingredients ingredients = self->fetchIngredients();
        if (ingredients.spoiled())
            return Cake::Fail;

        BatterAndWhatnot batter = self->mixAndStuff(ingredients);
        Cake result = self->bake(batter);
        if (result.burned())
            return Cake::Fail;

        return result;
    }
};

class PersonalChef : public CakeMaker<PersonalChef>
{
    Ingredients fetchIngredients();
    BatterAndWhatnot mixAndStuff(Ingredients);
    Cake bake(BatterAndWhatnot);

    friend class CakeMaker;
};

int main()
{
    PersonalChef chef;
    chef.makeCake();
    return 0;
}

Bam! Now it compiles normally. The CakeMaker is given PersonalChef as the template type argument, and the CakeMaker converts its this pointer for use as the PersonalChef type (which is valid in this case, since PersonalChef is a CakeMaker), which does implement the required methods!

This can also be used to enforce minimum interface requirements at compile time (as in the cross-platform macro assembler) without the use of virtual functions, which have a tendency to thwart inlining optimization.

Fun fact: it looks like we have about 90 virtual function declarations in the 190k lines of engine-related C/C++ code that cloc tells me are in the js/src directory.

Footnotes

[*]

Fun concept from the papers: the conceptual issue with MI is that classes are overloaded in their purpose: they are intended to serve both as units of code (implementation) reuse and for instantiation of actual objects.

Lively assertions

Recently, "another" discussion about fatal assertions has cropped up in the Mozilla community. Luckily for me, I've missed all of the other discussions, so this is the one where I get to throw in my two bits.

Effectively, I only work on the JS engine, and the JS engine only has fatal assertions. This approach works for the JS team, and I can take an insider's guess as to why.

What's a fatal assertion?

In Mozilla, we have two relevant build modes: debug and no-debug.

A fatal assertion means that, when I write JS_ASSERT(someCondition), if someCondition doesn't hold, we call abort in debug build mode. As a result, the code which follows the assertion may legitimately assume that someCondition holds. You will never see something like this in the JS engine:

{
    JS_ASSERT(0 <= offset && offset < size);
    if (0 <= offset && offset < size) // Bad! Already enforced!
        offset_ = offset;
}

The interesting thing is that, in no-debug mode, we will not call abort. We eliminate the assertion condition test entirely. This means that, in production, the code which follows the assertion assumes that someCondition holds, and there's nothing checking that to be the case. [*]

Exploding early and often

If a JS-engine hacker assumes someCondition during development, and it turns out that someCondition isn't the case, we'd like to know about it, and we'd like to know about it LOUDLY.

Our valiant security team runs fuzz testing against the JS engine continuously, and hitting any one of these fatal assertions causes an abort. When you know that there is input that causes an abort in debug mode, you have a few potential resolutions:

  • Most severely, you realize a critical assumption has been violated that will lead to a potentially exploitable crash. This must be fixed immediately.

  • Moderately severely, you realize that this assertion should hold as a form of sanity check, but no code is directly affected in the sense of a vulnerability. This permits you to comment out the assertion, put a FIXME: bug XXXXXX comment next to it, and file an investigation bug that's assigned to the appropriate person, which can be prioritized appropriately.

  • Least severely, by reasoning about the parts of the program that are dependent on that assertion, you realize that the assertion was over-zealous, and should be loosened to a less strict check. You loosen the assertion and request confirmation via review.

But I think the real key to this whole process is simple: if things are exploding, a member of the bomb squad will show up and come to some resolution. Fatal assertions force action in a way that logs will not. You must (at least cursorily) investigate any one of these assertions as though it were in the most severe category, and some form of resolution must be timely in order to unblock fuzzers and other developers.

Everything that the hacker feels can and should be asserted is being asserted in a way that's impossible to ignore. Invariants present in the code base are reflected by the fatal assertions and, once they've proven themselves by running the regression/fuzzer/web gamut, can be depended upon — they certainly come to reinforce and strengthen each other over time.

Footnotes

[*]

We do have mechanisms that hackers can use for further checking, however. If crash reports indicate that some assertions may be suspect in production environments, we have a JS_OPT_ASSERT for doing diagnostics in our pre-release distribution channels. Since the most reliable information in a crash report tends to be the line number that you crashed on, fatal non-debug assertions are a very useful capability.