Sunday, May 15, 2011

Porting to JS 1.8.5 with GPSEE 0.3: Part II, Fat JSValues

JavaScript 1.8.5 changed the underlying representation of jsval, the fundamental data type which represents every possible value a JavaScript variable can hold.

In previous versions of SpiderMonkey, jsval was respresented in JSAPI as a tagged 32-bit integer; the bottom three bits were reserved for type tagging information (two tagging bits re-used when it stored an integer), all pointers were 8-byte aligned, and floating numbers (and integers larger than 31 bits) were stored in the jsval as pointers to jsdouble.  The type checking and manipulation macros, i.e. JSVAL_IS_DOUBLE, INT_TO_JSVAL, etc, abstracted the relevent bit-shifting masking operations required to extract the relevant tagging information, but left visible to the API consumer the fact that doubles were  stored on the heap rather than in the jsval itself, like the < 31-bit integers.  (Recall that JavaScript does not actually have the concept of integers and floats, rather just "numbers" -- but we differentiate in JSAPI because C integers are so much faster to work with, and more commonly used in JavaScript programs).

In SpiderMonkey 1.8.5, we have "fatvals" - again, we have a C type named jsval which encodes all possible JavaScript values, but now it is represented by a 64-bit quanity, which is a C struct in debug builds.  This means that we can no longer use expressions like INT_TO_JSVAL(123) in a C switch statement, and we can no longer directly compare jsvals with the C == operator.

The new jsval representation also now directly encodes doubles, rather than pointers to doubles on the heap. This alone yields a significant performance boost, but it causes code breakage for those using the JSDOUBLE_ macros, rather than more flexible ways of converting numbers like JS_ConvertArguments() or JS_NewNumberValue().

GPSEE 0.3 provides macros to allow you to maintain the pre-1.8.5 pointer-to-double storage semantic for doubles.  These macros allow old code to be converted quickly, while maintaining backwards compatibility with older versions of JSAPI -- GPSEE 0.3 built against older-JSAPI preserves the new macros, manipulating the older datatypes appropriately.  The affected macros are DOUBLEPTR_TO_JSVAL and JSVAL_TO_DOUBLEPTR; they behave the same as DOUBLE_TO_JSVAL and JSVAL_TO_DOUBLE from previous versions of JSAPI.

We have also provided a replacement implementation of JS_NewDoubleValue() which was removed from JSAPI.

No comments:

Post a Comment