diff options
Diffstat (limited to 'JavaScriptCore/runtime/JSArray.h')
| -rw-r--r-- | JavaScriptCore/runtime/JSArray.h | 81 |
1 files changed, 66 insertions, 15 deletions
diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h index ad6ee88..9e155d8 100644 --- a/JavaScriptCore/runtime/JSArray.h +++ b/JavaScriptCore/runtime/JSArray.h @@ -23,26 +23,50 @@ #include "JSObject.h" +#define CHECK_ARRAY_CONSISTENCY 0 + namespace JSC { typedef HashMap<unsigned, JSValue> SparseArrayValueMap; + // This struct holds the actual data values of an array. A JSArray object points to it's contained ArrayStorage + // struct by pointing to m_vector. To access the contained ArrayStorage struct, use the getStorage() and + // setStorage() methods. It is important to note that there may be space before the ArrayStorage that + // is used to quick unshift / shift operation. The actual allocated pointer is available by using: + // getStorage() - m_indexBias * sizeof(JSValue) struct ArrayStorage { - unsigned m_length; + unsigned m_length; // The "length" property on the array unsigned m_numValuesInVector; SparseArrayValueMap* m_sparseValueMap; - void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily. + void* subclassData; // A JSArray subclass can use this to fill the vector lazily. + void* m_allocBase; // Pointer to base address returned by malloc(). Keeping this pointer does eliminate false positives from the leak detector. size_t reportedMapCapacity; +#if CHECK_ARRAY_CONSISTENCY + bool m_inCompactInitialization; +#endif JSValue m_vector[1]; }; + // The CreateCompact creation mode is used for fast construction of arrays + // whose size and contents are known at time of creation. + // + // There are two obligations when using this mode: + // + // - uncheckedSetIndex() must be used when initializing the array. + // - setLength() must be called after initialization. + + enum ArrayCreationMode { CreateCompact, CreateInitialized }; + class JSArray : public JSObject { friend class JIT; friend class Walker; public: + enum VPtrStealingHackType { VPtrStealingHack }; + JSArray(VPtrStealingHackType); + explicit JSArray(NonNullPassRefPtr<Structure>); - JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength); + JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength, ArrayCreationMode); JSArray(NonNullPassRefPtr<Structure>, const ArgList& initialValues); virtual ~JSArray(); @@ -52,7 +76,7 @@ namespace JSC { virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem. static JS_EXPORTDATA const ClassInfo info; - + unsigned length() const { return m_storage->m_length; } void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray. @@ -63,6 +87,9 @@ namespace JSC { void push(ExecState*, JSValue); JSValue pop(); + void shiftCount(ExecState*, int count); + void unshiftCount(ExecState*, int count); + bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; } JSValue getIndex(unsigned i) { @@ -74,14 +101,26 @@ namespace JSC { void setIndex(unsigned i, JSValue v) { ASSERT(canSetIndex(i)); + JSValue& x = m_storage->m_vector[i]; if (!x) { - ++m_storage->m_numValuesInVector; - if (i >= m_storage->m_length) - m_storage->m_length = i + 1; + ArrayStorage *storage = m_storage; + ++storage->m_numValuesInVector; + if (i >= storage->m_length) + storage->m_length = i + 1; } x = v; } + + void uncheckedSetIndex(unsigned i, JSValue v) + { + ASSERT(canSetIndex(i)); + ArrayStorage *storage = m_storage; +#if CHECK_ARRAY_CONSISTENCY + ASSERT(storage->m_inCompactInitialization); +#endif + storage->m_vector[i] = v; + } void fillArgList(ExecState*, MarkedArgumentBuffer&); void copyToRegisters(ExecState*, Register*, uint32_t); @@ -101,24 +140,27 @@ namespace JSC { virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual void markChildren(MarkStack&); - void* lazyCreationData(); - void setLazyCreationData(void*); - + void* subclassData() const; + void setSubclassData(void*); + private: virtual const ClassInfo* classInfo() const { return &info; } bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&); void putSlowCase(ExecState*, unsigned propertyName, JSValue); + unsigned getNewVectorLength(unsigned desiredLength); bool increaseVectorLength(unsigned newLength); + bool increaseVectorPrefixLength(unsigned newLength); unsigned compactForSorting(); enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck }; void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck); - unsigned m_vectorLength; - ArrayStorage* m_storage; + unsigned m_vectorLength; // The valid length of m_vector + int m_indexBias; // The number of JSValue sized blocks before ArrayStorage. + ArrayStorage *m_storage; }; JSArray* asArray(JSValue); @@ -194,7 +236,7 @@ namespace JSC { current.m_values++; JSCell* cell; - if (!value || !value.isCell() || Heap::isCellMarked(cell = value.asCell())) { + if (!value || !value.isCell() || Heap::checkMarkCell(cell = value.asCell())) { if (current.m_values == end) { m_markSets.removeLast(); continue; @@ -202,7 +244,6 @@ namespace JSC { goto findNextUnmarkedNullValue; } - Heap::markCell(cell); if (cell->structure()->typeInfo().type() < CompoundType) { if (current.m_values == end) { m_markSets.removeLast(); @@ -220,7 +261,17 @@ namespace JSC { markChildren(m_values.removeLast()); } } - + + // Rule from ECMA 15.2 about what an array index is. + // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. + inline unsigned Identifier::toArrayIndex(bool& ok) const + { + unsigned i = toUInt32(ok); + if (ok && i >= 0xFFFFFFFFU) + ok = false; + return i; + } + } // namespace JSC #endif // JSArray_h |
