IndexType

IndexType

In JavaScriptCore, the JavaScript engine employed in WebKit, the way in which elements are stored in an object is represented as an IndexingType value, an 8-bit integer representing a combination of flags.

The definition can be found in IndexingType.h. Throughout the code, the engine will often inspect (or emit code which inspects) the indexing type of an object and decide which one of several specialized fast paths to use based on that.

One important indexing type is ArrayWithUndecided, which indicates that all elements are undefined and no actual values have to be stored. In this case, the engine can leave the elements uninitialized for increased performance.

A list of index type:

// Flags for testing the presence of capabilities.
static const IndexingType IsArray                  = 0x01;

// The shape of the indexed property storage.
static const IndexingType NoIndexingShape                 = 0x00;
static const IndexingType UndecidedShape                  = 0x02; // Only useful for arrays.
static const IndexingType Int32Shape                      = 0x04;
static const IndexingType DoubleShape                     = 0x06;
static const IndexingType ContiguousShape                 = 0x08;
static const IndexingType ArrayStorageShape               = 0x0A;
static const IndexingType SlowPutArrayStorageShape        = 0x0C;

static const IndexingType IndexingShapeMask               = 0x0E;
static const IndexingType IndexingShapeShift              = 1;
static const IndexingType NumberOfIndexingShapes          = 7;
static const IndexingType IndexingTypeMask                = IndexingShapeMask | IsArray;

// Whether or not the butterfly is copy on write. If it is copy on write then the butterfly is actually a JSImmutableButterfly. This should only ever be set if there are no named properties.
static const IndexingType CopyOnWrite                      = 0x10;
static const IndexingType IndexingShapeAndWritabilityMask  = CopyOnWrite | IndexingShapeMask;
static const IndexingType IndexingModeMask                 = CopyOnWrite | IndexingTypeMask;
static const IndexingType NumberOfCopyOnWriteIndexingModes = 3; // We only have copy on write for int32, double, and contiguous shapes.
static const IndexingType NumberOfArrayIndexingModes       = NumberOfIndexingShapes + NumberOfCopyOnWriteIndexingModes;

// Additional flags for tracking the history of the type. These are usually
// masked off unless you ask for them directly.
static const IndexingType MayHaveIndexedAccessors         = 0x20;

// The IndexingType field of JSCells is stolen for locks and remembering if the object has been a
// prototype.
static const IndexingType IndexingTypeLockIsHeld          = 0x40;
static const IndexingType IndexingTypeLockHasParked       = 0x80;
// List of acceptable array types.
static const IndexingType NonArray                        = 0x0;
static const IndexingType NonArrayWithInt32               = Int32Shape;
static const IndexingType NonArrayWithDouble              = DoubleShape;
static const IndexingType NonArrayWithContiguous          = ContiguousShape;
static const IndexingType NonArrayWithArrayStorage        = ArrayStorageShape;
static const IndexingType NonArrayWithSlowPutArrayStorage = SlowPutArrayStorageShape;
static const IndexingType ArrayClass                      = IsArray; // I'd want to call this "Array" but this would lead to disastrous namespace pollution.
static const IndexingType ArrayWithUndecided              = IsArray | UndecidedShape;
static const IndexingType ArrayWithInt32                  = IsArray | Int32Shape;
static const IndexingType ArrayWithDouble                 = IsArray | DoubleShape;
static const IndexingType ArrayWithContiguous             = IsArray | ContiguousShape;
static const IndexingType ArrayWithArrayStorage           = IsArray | ArrayStorageShape;
static const IndexingType ArrayWithSlowPutArrayStorage    = IsArray | SlowPutArrayStorageShape;
static const IndexingType CopyOnWriteArrayWithInt32       = IsArray | Int32Shape | CopyOnWrite;
static const IndexingType CopyOnWriteArrayWithDouble      = IsArray | DoubleShape | CopyOnWrite;
static const IndexingType CopyOnWriteArrayWithContiguous  = IsArray | ContiguousShape | CopyOnWrite;

Some code segments:

// ArrayWithUndecided
a1 = []

// CopyOnWriteArrayWithInt32
a2 = [1,2,3,4]
// ArrayWithInt32
a2.push(1)

// CopyOnWriteArrayWithDouble
a3 = [1.1, 2.2, 3.3, 4.4]
// ArrayWithDouble
a3.push(1.1)

// ArrayWithContiguous
a4 = [[1,2,3], [2,3,4]]

// ArrayWithArrayStorage
a5 = [1,2]
a5[100] = 3
a5[1000] = 4
a5[10000] = 5

// ArrayWithSlowPutArrayStorage
a6 = [1337, 13.37]
Array.prototype.__defineSetter__("0", function() {})

// NonArray
b1 = {"a":1, "b":2}