Comparing JSValue representations in JavaScriptCore. A short overview.

The central data structure in JavaScriptCore is JSValue. It represents the value of a JavaScript variable. Since there are no type restrictions in JavaScript, a JSValue can contain anything from a simple bool constant to an object. Most operations work on these JSValues, so their effective handling is essential for a fast JavaScript engine. In JavaScriptCore there are 3 types of JSValue representations: JSValue32 and JSValue32_64 for 32 bit machines, and JSValue64 for 64 bit machines. Albeit maintaining all of these representations is a heavy burden, the feeling to have a fast JS engine is rewarding.

Let's start with the key differences between these representations. JSValue32 uses 32 bit pointers to store the JS values. Its value points to a JSCell, which provides virtual functions to detect the exact type of any JS value. However, some simple types are encoded as invalid pointers. On a 32 bit machine, the pointers are aligned to 4 bytes, therefore the last two bits are always zero. Primitive types can be stored in this 32 bit space by setting any of these bits to 1. Therefore it is possible to distinguish pointers from primitive types. 31 bit integers are encoded as (value << 1) | 0x1 and other primitive types (true, false boolen constants, undefined and null) are encoded by setting bit 1 and clearing bit 0.

Both JSValue32_64 and JSValue64 use 64 bit doubles to store JS values. It has enough space to contain any valid real number since the numbers should be represented as doubles according to the ECMA specification. Everything else is encoded as NaN-s. More specifically, JSCell pointers, 32 bit integers and fixed immediates mentioned above (true, null, etc.) are encoded as NaN-s. Since integer operations are much faster than double operations, 32 bit integers are worth to be encoded as int32 values. JSValue64 is an excellent design for 64 bit systems, since JSValues fit into one machine register. However, JSValue32_64 is not necessary faster on 32 bit systems compared to JSValue32. The gain here is the reduced number of memory allocitons, since we don't need to allocate memory for JSNumberCells which contain a double in case of JSValue32. The price is the increased number of memory accesses, since copying a JSValue takes two operation instead of one. JSValue32_64 is faster, if we use many non-integer numbers (like 3D math), and slower in all other cases.

I can give some pointers in the source code for those who want to dig deeper. JSValue handling is found in JavaScriptCore/runtime except some JIT related things. In the begining of JSImmediate.h, there is a comparsion about JSValue32 and JSValue64. Moreover, JSImmediate.h contains functions for operating on immediates except for JSValue32_64. The generic JSValue handling functions are found in JSValue.h. Furthermore, the JSValue32_64 handling methods are found here as well. Search for #if USE(JSVALUExxx) defines, where xxx can be 32, 64 or 32_64 to see the differences. JSCell, which acts as the base class of all non-primitive JSValues, can be found in JSCell.cpp and .h

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • No HTML tags allowed
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Fill in the blank