diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSObject.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSObject.h | 610 |
1 files changed, 251 insertions, 359 deletions
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 428e51f3c..c62dc2aec 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -37,7 +37,7 @@ #include "PutPropertySlot.h" #include "Structure.h" -#include "JSGlobalData.h" +#include "VM.h" #include "JSString.h" #include "SlotVisitorInlines.h" #include "SparseArrayValueMap.h" @@ -121,16 +121,8 @@ public: JS_EXPORT_PRIVATE static String className(const JSObject*); JSValue prototype() const; - void setPrototype(JSGlobalData&, JSValue prototype); - bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype); - - Structure* inheritorID(JSGlobalData&); - void notifyUsedAsPrototype(JSGlobalData&); - - bool mayBeUsedAsPrototype(JSGlobalData& globalData) - { - return isValidOffset(structure()->get(globalData, globalData.m_inheritorIDKey)); - } + void setPrototype(VM&, JSValue prototype); + bool setPrototypeWithCycleCheck(VM&, JSValue prototype); bool mayInterceptIndexedAccesses() { @@ -170,7 +162,7 @@ public: void putByIndexInline(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) { if (canSetIndexQuickly(propertyName)) { - setIndexQuickly(exec->globalData(), propertyName, value); + setIndexQuickly(exec->vm(), propertyName, value); return; } methodTable()->putByIndex(this, exec, propertyName, value, shouldThrow); @@ -184,7 +176,7 @@ public: bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes, PutDirectIndexMode mode) { if (!attributes && canSetIndexQuicklyForPutDirect(propertyName)) { - setIndexQuickly(exec->globalData(), propertyName, value); + setIndexQuickly(exec->vm(), propertyName, value); return true; } return putDirectIndexBeyondVectorLength(exec, propertyName, value, attributes, mode); @@ -217,7 +209,7 @@ public: case ALL_ARRAY_STORAGE_INDEXING_TYPES: return i < m_butterfly->arrayStorage()->vectorLength() && m_butterfly->arrayStorage()->m_vector[i]; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return false; } } @@ -233,7 +225,7 @@ public: case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage()->m_vector[i].get(); default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return JSValue(); } } @@ -262,7 +254,7 @@ public: return m_butterfly->arrayStorage()->m_vector[i].get(); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); break; } return JSValue(); @@ -302,7 +294,7 @@ public: return i < m_butterfly->arrayStorage()->vectorLength() && !!m_butterfly->arrayStorage()->m_vector[i]; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return false; } } @@ -319,25 +311,25 @@ public: case ALL_ARRAY_STORAGE_INDEXING_TYPES: return i < m_butterfly->vectorLength(); default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return false; } } - void setIndexQuickly(JSGlobalData& globalData, unsigned i, JSValue v) + void setIndexQuickly(VM& vm, unsigned i, JSValue v) { switch (structure()->indexingType()) { case ALL_INT32_INDEXING_TYPES: { ASSERT(i < m_butterfly->vectorLength()); if (!v.isInt32()) { - convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(globalData, i, v); + convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(vm, i, v); return; } // Fall through to contiguous case. } case ALL_CONTIGUOUS_INDEXING_TYPES: { ASSERT(i < m_butterfly->vectorLength()); - m_butterfly->contiguous()[i].set(globalData, this, v); + m_butterfly->contiguous()[i].set(vm, this, v); if (i >= m_butterfly->publicLength()) m_butterfly->setPublicLength(i + 1); break; @@ -345,12 +337,12 @@ public: case ALL_DOUBLE_INDEXING_TYPES: { ASSERT(i < m_butterfly->vectorLength()); if (!v.isNumber()) { - convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v); + convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v); return; } double value = v.asNumber(); if (value != value) { - convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v); + convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v); return; } m_butterfly->contiguousDouble()[i] = value; @@ -362,7 +354,7 @@ public: ArrayStorage* storage = m_butterfly->arrayStorage(); WriteBarrier<Unknown>& x = storage->m_vector[i]; JSValue old = x.get(); - x.set(globalData, this, v); + x.set(vm, this, v); if (!old) { ++storage->m_numValuesInVector; if (i >= storage->length()) @@ -371,22 +363,22 @@ public: break; } default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } - void initializeIndex(JSGlobalData& globalData, unsigned i, JSValue v) + void initializeIndex(VM& vm, unsigned i, JSValue v) { switch (structure()->indexingType()) { case ALL_UNDECIDED_INDEXING_TYPES: { - setIndexQuicklyToUndecided(globalData, i, v); + setIndexQuicklyToUndecided(vm, i, v); break; } case ALL_INT32_INDEXING_TYPES: { ASSERT(i < m_butterfly->publicLength()); ASSERT(i < m_butterfly->vectorLength()); if (!v.isInt32()) { - convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(globalData, i, v); + convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(vm, i, v); break; } // Fall through. @@ -394,19 +386,19 @@ public: case ALL_CONTIGUOUS_INDEXING_TYPES: { ASSERT(i < m_butterfly->publicLength()); ASSERT(i < m_butterfly->vectorLength()); - m_butterfly->contiguous()[i].set(globalData, this, v); + m_butterfly->contiguous()[i].set(vm, this, v); break; } case ALL_DOUBLE_INDEXING_TYPES: { ASSERT(i < m_butterfly->publicLength()); ASSERT(i < m_butterfly->vectorLength()); if (!v.isNumber()) { - convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v); + convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v); return; } double value = v.asNumber(); if (value != value) { - convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v); + convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v); return; } m_butterfly->contiguousDouble()[i] = value; @@ -416,11 +408,11 @@ public: ArrayStorage* storage = m_butterfly->arrayStorage(); ASSERT(i < storage->length()); ASSERT(i < storage->m_numValuesInVector); - storage->m_vector[i].set(globalData, this, v); + storage->m_vector[i].set(vm, this, v); break; } default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -436,7 +428,7 @@ public: case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage()->m_sparseMap; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return false; } } @@ -453,12 +445,12 @@ public: case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage()->inSparseMode(); default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return false; } } - void enterDictionaryIndexingMode(JSGlobalData&); + void enterDictionaryIndexingMode(VM&); // putDirect is effectively an unchecked vesion of 'defineOwnProperty': // - the prototype chain is not consulted @@ -466,9 +458,9 @@ public: // - attributes will be respected (after the call the property will exist with the given attributes) // - the property name is assumed to not be an index. JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes); - void putDirect(JSGlobalData&, PropertyName, JSValue, unsigned attributes = 0); - void putDirect(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&); - void putDirectWithoutTransition(JSGlobalData&, PropertyName, JSValue, unsigned attributes = 0); + void putDirect(VM&, PropertyName, JSValue, unsigned attributes = 0); + void putDirect(VM&, PropertyName, JSValue, PutPropertySlot&); + void putDirectWithoutTransition(VM&, PropertyName, JSValue, unsigned attributes = 0); void putDirectAccessor(ExecState*, PropertyName, JSValue, unsigned attributes); bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const; @@ -501,25 +493,18 @@ public: bool getPropertySpecificValue(ExecState*, PropertyName, JSCell*& specificFunction) const; // This get function only looks at the property map. - JSValue getDirect(JSGlobalData& globalData, PropertyName propertyName) const + JSValue getDirect(VM& vm, PropertyName propertyName) const { - PropertyOffset offset = structure()->get(globalData, propertyName); - checkOffset(offset, structure()->typeInfo().type()); - return offset != invalidOffset ? getDirectOffset(offset) : JSValue(); + PropertyOffset offset = structure()->get(vm, propertyName); + checkOffset(offset, structure()->inlineCapacity()); + return offset != invalidOffset ? getDirect(offset) : JSValue(); } - WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName) + PropertyOffset getDirectOffset(VM& vm, PropertyName propertyName) { - PropertyOffset offset = structure()->get(globalData, propertyName); - checkOffset(offset, structure()->typeInfo().type()); - return isValidOffset(offset) ? locationForOffset(offset) : 0; - } - - WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName, unsigned& attributes) - { - JSCell* specificFunction; - PropertyOffset offset = structure()->get(globalData, propertyName, attributes, specificFunction); - return isValidOffset(offset) ? locationForOffset(offset) : 0; + PropertyOffset offset = structure()->get(vm, propertyName); + checkOffset(offset, structure()->inlineCapacity()); + return offset; } bool hasInlineStorage() const { return structure()->hasInlineStorage(); } @@ -562,21 +547,9 @@ public: return &outOfLineStorage()[offsetInOutOfLineStorage(offset)]; } - PropertyOffset offsetForLocation(WriteBarrierBase<Unknown>* location) const - { - PropertyOffset result; - size_t offsetInInlineStorage = location - inlineStorageUnsafe(); - if (offsetInInlineStorage < static_cast<size_t>(firstOutOfLineOffset)) - result = offsetInInlineStorage; - else - result = outOfLineStorage() - location + (firstOutOfLineOffset - 1); - validateOffset(result, structure()->typeInfo().type()); - return result; - } + void transitionTo(VM&, Structure*); - void transitionTo(JSGlobalData&, Structure*); - - bool removeDirect(JSGlobalData&, PropertyName); // Return true if anything is removed. + bool removeDirect(VM&, PropertyName); // Return true if anything is removed. bool hasCustomProperties() { return structure()->didTransition(); } bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); } @@ -585,26 +558,29 @@ public: // - provides no special handling for __proto__ // - does not walk the prototype chain (to check for accessors or non-writable properties). // This is used by JSActivation. - bool putOwnDataProperty(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&); + bool putOwnDataProperty(VM&, PropertyName, JSValue, PutPropertySlot&); // Fast access to known property offsets. - JSValue getDirectOffset(PropertyOffset offset) const { return locationForOffset(offset)->get(); } - void putDirectOffset(JSGlobalData& globalData, PropertyOffset offset, JSValue value) { locationForOffset(offset)->set(globalData, this, value); } - void putUndefinedAtDirectOffset(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); } + JSValue getDirect(PropertyOffset offset) const { return locationForOffset(offset)->get(); } + void putDirect(VM& vm, PropertyOffset offset, JSValue value) { locationForOffset(offset)->set(vm, this, value); } + void putDirectUndefined(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); } + + void putDirectNativeFunction(ExecState*, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes); JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow); bool isGlobalObject() const; bool isVariableObject() const; + bool isStaticScopeObject() const; bool isNameScopeObject() const; bool isActivationObject() const; bool isErrorInstance() const; - void seal(JSGlobalData&); - void freeze(JSGlobalData&); - JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&); - bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); } - bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); } + void seal(VM&); + void freeze(VM&); + JS_EXPORT_PRIVATE void preventExtensions(VM&); + bool isSealed(VM& vm) { return structure()->isSealed(vm); } + bool isFrozen(VM& vm) { return structure()->isFrozen(vm); } bool isExtensible() { return structure()->isExtensible(); } bool indexingShouldBeSparse() { @@ -615,16 +591,16 @@ public: bool staticFunctionsReified() { return structure()->staticFunctionsReified(); } void reifyStaticFunctionsForDelete(ExecState* exec); - JS_EXPORT_PRIVATE Butterfly* growOutOfLineStorage(JSGlobalData&, size_t oldSize, size_t newSize); - void setButterfly(JSGlobalData&, Butterfly*, Structure*); + JS_EXPORT_PRIVATE Butterfly* growOutOfLineStorage(VM&, size_t oldSize, size_t newSize); + void setButterfly(VM&, Butterfly*, Structure*); void setButterflyWithoutChangingStructure(Butterfly*); // You probably don't want to call this. - void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, unsigned oldCapacity, Structure*); - void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, Structure*); + void setStructureAndReallocateStorageIfNecessary(VM&, unsigned oldCapacity, Structure*); + void setStructureAndReallocateStorageIfNecessary(VM&, Structure*); - void flattenDictionaryObject(JSGlobalData& globalData) + void flattenDictionaryObject(VM& vm) { - structure()->flattenDictionaryStructure(globalData, this); + structure()->flattenDictionaryStructure(vm, this); } JSGlobalObject* globalObject() const @@ -634,7 +610,7 @@ public: return structure()->globalObject(); } - void switchToSlowPutArrayStorage(JSGlobalData&); + void switchToSlowPutArrayStorage(VM&); // The receiver is the prototype in this case. The following: // @@ -649,46 +625,57 @@ public: // indexing should be sparse, we're having a bad time, or because // we already have a more general form of storage (double, // contiguous, array storage). - WriteBarrier<Unknown>* ensureInt32(JSGlobalData& globalData) + ContiguousJSValues ensureInt32(VM& vm) { if (LIKELY(hasInt32(structure()->indexingType()))) return m_butterfly->contiguousInt32(); - return ensureInt32Slow(globalData); + return ensureInt32Slow(vm); } // Returns 0 if double storage cannot be created - either because // indexing should be sparse, we're having a bad time, or because // we already have a more general form of storage (contiguous, // or array storage). - double* ensureDouble(JSGlobalData& globalData) + ContiguousDoubles ensureDouble(VM& vm) { if (LIKELY(hasDouble(structure()->indexingType()))) return m_butterfly->contiguousDouble(); - return ensureDoubleSlow(globalData); + return ensureDoubleSlow(vm); } // Returns 0 if contiguous storage cannot be created - either because // indexing should be sparse or because we're having a bad time. - WriteBarrier<Unknown>* ensureContiguous(JSGlobalData& globalData) + ContiguousJSValues ensureContiguous(VM& vm) { if (LIKELY(hasContiguous(structure()->indexingType()))) return m_butterfly->contiguous(); - return ensureContiguousSlow(globalData); + return ensureContiguousSlow(vm); + } + + // Same as ensureContiguous(), except that if the indexed storage is in + // double mode, then it does a rage conversion to contiguous: it + // attempts to convert each double to an int32. + ContiguousJSValues rageEnsureContiguous(VM& vm) + { + if (LIKELY(hasContiguous(structure()->indexingType()))) + return m_butterfly->contiguous(); + + return rageEnsureContiguousSlow(vm); } // Ensure that the object is in a mode where it has array storage. Use // this if you're about to perform actions that would have required the // object to be converted to have array storage, if it didn't have it // already. - ArrayStorage* ensureArrayStorage(JSGlobalData& globalData) + ArrayStorage* ensureArrayStorage(VM& vm) { if (LIKELY(hasArrayStorage(structure()->indexingType()))) return m_butterfly->arrayStorage(); - return ensureArrayStorageSlow(globalData); + return ensureArrayStorageSlow(vm); } static size_t offsetOfInlineStorage(); @@ -706,9 +693,9 @@ public: static JS_EXPORTDATA const ClassInfo s_info; protected: - void finishCreation(JSGlobalData& globalData) + void finishCreation(VM& vm) { - Base::finishCreation(globalData); + Base::finishCreation(vm); ASSERT(inherits(&s_info)); ASSERT(!structure()->outOfLineCapacity()); ASSERT(structure()->isEmpty()); @@ -717,16 +704,14 @@ protected: ASSERT(classInfo()); } - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } // To instantiate objects you likely want JSFinalObject, below. // To create derived types you likely want JSNonFinalObject, below. - JSObject(JSGlobalData&, Structure*, Butterfly* = 0); - - void resetInheritorID(JSGlobalData&); + JSObject(VM&, Structure*, Butterfly* = 0); void visitButterfly(SlotVisitor&, Butterfly*, size_t storageSize); void copyButterfly(CopyVisitor&, Butterfly*, size_t storageSize); @@ -752,41 +737,42 @@ protected: } } - Butterfly* createInitialUndecided(JSGlobalData&, unsigned length); - WriteBarrier<Unknown>* createInitialInt32(JSGlobalData&, unsigned length); - double* createInitialDouble(JSGlobalData&, unsigned length); - WriteBarrier<Unknown>* createInitialContiguous(JSGlobalData&, unsigned length); + Butterfly* createInitialUndecided(VM&, unsigned length); + ContiguousJSValues createInitialInt32(VM&, unsigned length); + ContiguousDoubles createInitialDouble(VM&, unsigned length); + ContiguousJSValues createInitialContiguous(VM&, unsigned length); - void convertUndecidedForValue(JSGlobalData&, JSValue); - void convertInt32ForValue(JSGlobalData&, JSValue); + void convertUndecidedForValue(VM&, JSValue); + void convertInt32ForValue(VM&, JSValue); - ArrayStorage* createArrayStorage(JSGlobalData&, unsigned length, unsigned vectorLength); - ArrayStorage* createInitialArrayStorage(JSGlobalData&); + ArrayStorage* createArrayStorage(VM&, unsigned length, unsigned vectorLength); + ArrayStorage* createInitialArrayStorage(VM&); - WriteBarrier<Unknown>* convertUndecidedToInt32(JSGlobalData&); - double* convertUndecidedToDouble(JSGlobalData&); - WriteBarrier<Unknown>* convertUndecidedToContiguous(JSGlobalData&); - ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength); - ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&, NonPropertyTransition); - ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&); + ContiguousJSValues convertUndecidedToInt32(VM&); + ContiguousDoubles convertUndecidedToDouble(VM&); + ContiguousJSValues convertUndecidedToContiguous(VM&); + ArrayStorage* convertUndecidedToArrayStorage(VM&, NonPropertyTransition, unsigned neededLength); + ArrayStorage* convertUndecidedToArrayStorage(VM&, NonPropertyTransition); + ArrayStorage* convertUndecidedToArrayStorage(VM&); - double* convertInt32ToDouble(JSGlobalData&); - WriteBarrier<Unknown>* convertInt32ToContiguous(JSGlobalData&); - ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength); - ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&, NonPropertyTransition); - ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&); - - WriteBarrier<Unknown>* convertDoubleToContiguous(JSGlobalData&); - ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength); - ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&, NonPropertyTransition); - ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&); + ContiguousDoubles convertInt32ToDouble(VM&); + ContiguousJSValues convertInt32ToContiguous(VM&); + ArrayStorage* convertInt32ToArrayStorage(VM&, NonPropertyTransition, unsigned neededLength); + ArrayStorage* convertInt32ToArrayStorage(VM&, NonPropertyTransition); + ArrayStorage* convertInt32ToArrayStorage(VM&); + + ContiguousJSValues convertDoubleToContiguous(VM&); + ContiguousJSValues rageConvertDoubleToContiguous(VM&); + ArrayStorage* convertDoubleToArrayStorage(VM&, NonPropertyTransition, unsigned neededLength); + ArrayStorage* convertDoubleToArrayStorage(VM&, NonPropertyTransition); + ArrayStorage* convertDoubleToArrayStorage(VM&); - ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength); - ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition); - ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&); + ArrayStorage* convertContiguousToArrayStorage(VM&, NonPropertyTransition, unsigned neededLength); + ArrayStorage* convertContiguousToArrayStorage(VM&, NonPropertyTransition); + ArrayStorage* convertContiguousToArrayStorage(VM&); - ArrayStorage* ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData&); + ArrayStorage* ensureArrayStorageExistsAndEnterDictionaryIndexingMode(VM&); bool defineOwnNonIndexProperty(ExecState*, PropertyName, PropertyDescriptor&, bool throwException); @@ -794,24 +780,24 @@ protected: void putByIndexBeyondVectorLengthWithoutAttributes(ExecState*, unsigned propertyName, JSValue); void putByIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, bool shouldThrow, ArrayStorage*); - bool increaseVectorLength(JSGlobalData&, unsigned newLength); + bool increaseVectorLength(VM&, unsigned newLength); void deallocateSparseIndexMap(); bool defineOwnIndexedProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException); - SparseArrayValueMap* allocateSparseIndexMap(JSGlobalData&); + SparseArrayValueMap* allocateSparseIndexMap(VM&); - void notifyPresenceOfIndexedAccessors(JSGlobalData&); + void notifyPresenceOfIndexedAccessors(VM&); bool attemptToInterceptPutByIndexOnHole(ExecState*, unsigned index, JSValue, bool shouldThrow); // Call this if you want setIndexQuickly to succeed and you're sure that // the array is contiguous. - void ensureLength(JSGlobalData& globalData, unsigned length) + void ensureLength(VM& vm, unsigned length) { ASSERT(length < MAX_ARRAY_INDEX); ASSERT(hasContiguous(structure()->indexingType()) || hasInt32(structure()->indexingType()) || hasDouble(structure()->indexingType()) || hasUndecided(structure()->indexingType())); if (m_butterfly->vectorLength() < length) - ensureLengthSlow(globalData, length); + ensureLengthSlow(vm, length); if (m_butterfly->publicLength() < length) m_butterfly->setPublicLength(length); @@ -827,7 +813,7 @@ protected: // as if it contained JSValues. But it won't always contain JSValues. // Make sure you cast this to the appropriate type before using. template<IndexingType indexingType> - WriteBarrier<Unknown>* indexingData() + ContiguousJSValues indexingData() { switch (indexingType) { case ALL_INT32_INDEXING_TYPES: @@ -836,15 +822,15 @@ protected: return m_butterfly->contiguous(); case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return m_butterfly->arrayStorage()->m_vector; - + return m_butterfly->arrayStorage()->vector(); + default: CRASH(); - return 0; + return ContiguousJSValues(); } } - WriteBarrier<Unknown>* currentIndexingData() + ContiguousJSValues currentIndexingData() { switch (structure()->indexingType()) { case ALL_INT32_INDEXING_TYPES: @@ -852,11 +838,11 @@ protected: return m_butterfly->contiguous(); case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return m_butterfly->arrayStorage()->m_vector; + return m_butterfly->arrayStorage()->vector(); default: CRASH(); - return 0; + return ContiguousJSValues(); } } @@ -931,18 +917,17 @@ private: void isObject(); void isString(); - Butterfly* createInitialIndexedStorage(JSGlobalData&, unsigned length, size_t elementSize); + Butterfly* createInitialIndexedStorage(VM&, unsigned length, size_t elementSize); - ArrayStorage* enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(JSGlobalData&, ArrayStorage*); + ArrayStorage* enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(VM&, ArrayStorage*); template<PutMode> - bool putDirectInternal(JSGlobalData&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*); + bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*); bool inlineGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&); JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, PropertyOffset); const HashEntry* findPropertyHashEntry(ExecState*, PropertyName) const; - Structure* createInheritorID(JSGlobalData&); void putIndexedDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old); @@ -955,24 +940,29 @@ private: JS_EXPORT_PRIVATE bool getOwnPropertySlotSlow(ExecState*, PropertyName, PropertySlot&); - ArrayStorage* constructConvertedArrayStorageWithoutCopyingElements(JSGlobalData&, unsigned neededLength); - - JS_EXPORT_PRIVATE void setIndexQuicklyToUndecided(JSGlobalData&, unsigned index, JSValue); - JS_EXPORT_PRIVATE void convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(JSGlobalData&, unsigned index, JSValue); - JS_EXPORT_PRIVATE void convertDoubleToContiguousWhilePerformingSetIndex(JSGlobalData&, unsigned index, JSValue); + ArrayStorage* constructConvertedArrayStorageWithoutCopyingElements(VM&, unsigned neededLength); - void ensureLengthSlow(JSGlobalData&, unsigned length); + JS_EXPORT_PRIVATE void setIndexQuicklyToUndecided(VM&, unsigned index, JSValue); + JS_EXPORT_PRIVATE void convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(VM&, unsigned index, JSValue); + JS_EXPORT_PRIVATE void convertDoubleToContiguousWhilePerformingSetIndex(VM&, unsigned index, JSValue); - WriteBarrier<Unknown>* ensureInt32Slow(JSGlobalData&); - double* ensureDoubleSlow(JSGlobalData&); - WriteBarrier<Unknown>* ensureContiguousSlow(JSGlobalData&); - ArrayStorage* ensureArrayStorageSlow(JSGlobalData&); + void ensureLengthSlow(VM&, unsigned length); + ContiguousJSValues ensureInt32Slow(VM&); + ContiguousDoubles ensureDoubleSlow(VM&); + ContiguousJSValues ensureContiguousSlow(VM&); + ContiguousJSValues rageEnsureContiguousSlow(VM&); + ArrayStorage* ensureArrayStorageSlow(VM&); + + enum DoubleToContiguousMode { EncodeValueAsDouble, RageConvertDoubleToValue }; + template<DoubleToContiguousMode mode> + ContiguousJSValues genericConvertDoubleToContiguous(VM&); + ContiguousJSValues ensureContiguousSlow(VM&, DoubleToContiguousMode); + protected: Butterfly* m_butterfly; }; - // JSNonFinalObject is a type of JSObject that has some internal storage, // but also preserves some space in the collector cell for additional // data members in derived types. @@ -982,20 +972,20 @@ class JSNonFinalObject : public JSObject { public: typedef JSObject Base; - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } protected: - explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly = 0) - : JSObject(globalData, structure, butterfly) + explicit JSNonFinalObject(VM& vm, Structure* structure, Butterfly* butterfly = 0) + : JSObject(vm, structure, butterfly) { } - void finishCreation(JSGlobalData& globalData) + void finishCreation(VM& vm) { - Base::finishCreation(globalData); + Base::finishCreation(vm); ASSERT(!this->structure()->totalStorageCapacity()); ASSERT(classInfo()); } @@ -1011,10 +1001,22 @@ class JSFinalObject : public JSObject { public: typedef JSObject Base; + static const unsigned defaultSize = 64; + static inline unsigned defaultInlineCapacity() + { + return (defaultSize - allocationSize(0)) / sizeof(WriteBarrier<Unknown>); + } + + static const unsigned maxSize = 512; + static inline unsigned maxInlineCapacity() + { + return (maxSize - allocationSize(0)) / sizeof(WriteBarrier<Unknown>); + } + static JSFinalObject* create(ExecState*, Structure*); - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, unsigned inlineCapacity) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(FinalObjectType, StructureFlags), &s_info, NonArray, INLINE_STORAGE_CAPACITY); + return Structure::create(vm, globalObject, prototype, TypeInfo(FinalObjectType, StructureFlags), &s_info, NonArray, inlineCapacity); } JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); @@ -1024,9 +1026,9 @@ public: protected: void visitChildrenCommon(SlotVisitor&); - void finishCreation(JSGlobalData& globalData) + void finishCreation(VM& vm) { - Base::finishCreation(globalData); + Base::finishCreation(vm); ASSERT(structure()->totalStorageCapacity() == structure()->inlineCapacity()); ASSERT(classInfo()); } @@ -1034,8 +1036,8 @@ protected: private: friend class LLIntOffsetsExtractor; - explicit JSFinalObject(JSGlobalData& globalData, Structure* structure) - : JSObject(globalData, structure) + explicit JSFinalObject(VM& vm, Structure* structure) + : JSObject(vm, structure) { } @@ -1050,8 +1052,8 @@ inline JSFinalObject* JSFinalObject::create(ExecState* exec, Structure* structur *exec->heap(), allocationSize(structure->inlineCapacity()) ) - ) JSFinalObject(exec->globalData(), structure); - finalObject->finishCreation(exec->globalData()); + ) JSFinalObject(exec->vm(), structure); + finalObject->finishCreation(exec->vm()); return finalObject; } @@ -1080,6 +1082,14 @@ inline bool JSObject::isVariableObject() const return structure()->typeInfo().type() >= VariableObjectType; } + +inline bool JSObject::isStaticScopeObject() const +{ + JSType type = structure()->typeInfo().type(); + return type == NameScopeObjectType || type == ActivationObjectType; +} + + inline bool JSObject::isNameScopeObject() const { return structure()->typeInfo().type() == NameScopeObjectType; @@ -1095,11 +1105,11 @@ inline bool JSObject::isErrorInstance() const return structure()->typeInfo().type() == ErrorInstanceType; } -inline void JSObject::setButterfly(JSGlobalData& globalData, Butterfly* butterfly, Structure* structure) +inline void JSObject::setButterfly(VM& vm, Butterfly* butterfly, Structure* structure) { ASSERT(structure); ASSERT(!butterfly == (!structure->outOfLineCapacity() && !hasIndexingHeader(structure->indexingType()))); - setStructure(globalData, structure); + setStructure(vm, structure); m_butterfly = butterfly; } @@ -1108,11 +1118,6 @@ inline void JSObject::setButterflyWithoutChangingStructure(Butterfly* butterfly) m_butterfly = butterfly; } -inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure) -{ - return JSFinalObject::create(exec, structure); -} - inline CallType getCallData(JSValue value, CallData& callData) { CallType result = value.isCell() ? value.asCell()->methodTable()->getCallData(value.asCell(), callData) : CallTypeNone; @@ -1127,11 +1132,6 @@ inline ConstructType getConstructData(JSValue value, ConstructData& constructDat return result; } -inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) -{ - return JSFinalObject::createStructure(globalData, globalObject, prototype); -} - inline JSObject* asObject(JSCell* cell) { ASSERT(cell->isObject()); @@ -1143,8 +1143,8 @@ inline JSObject* asObject(JSValue value) return asObject(value.asCell()); } -inline JSObject::JSObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly) - : JSCell(globalData, structure) +inline JSObject::JSObject(VM& vm, Structure* structure, Butterfly* butterfly) + : JSCell(vm, structure) , m_butterfly(butterfly) { } @@ -1154,32 +1154,11 @@ inline JSValue JSObject::prototype() const return structure()->storedPrototype(); } -inline const MethodTable* JSCell::methodTable() const -{ - return &classInfo()->methodTable; -} - -inline bool JSCell::inherits(const ClassInfo* info) const -{ - return classInfo()->isSubClassOf(info); -} - -// this method is here to be after the inline declaration of JSCell::inherits -inline bool JSValue::inherits(const ClassInfo* classInfo) const -{ - return isCell() && asCell()->inherits(classInfo); -} - -inline JSObject* JSValue::toThisObject(ExecState* exec) const -{ - return isCell() ? asCell()->methodTable()->toThisObject(asCell(), exec) : toThisObjectSlowCase(exec); -} - ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) { - PropertyOffset offset = structure()->get(exec->globalData(), propertyName); + PropertyOffset offset = structure()->get(exec->vm(), propertyName); if (LIKELY(isValidOffset(offset))) { - JSValue value = getDirectOffset(offset); + JSValue value = getDirect(offset); if (structure()->hasGetterSetterProperties() && value.isGetterSetter()) fillGetterPropertySlot(slot, offset); else @@ -1198,29 +1177,6 @@ ALWAYS_INLINE bool JSObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, P return jsCast<JSObject*>(cell)->inlineGetOwnPropertySlot(exec, propertyName, slot); } -ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - if (!structure()->typeInfo().overridesGetOwnPropertySlot()) - return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot); - return methodTable()->getOwnPropertySlot(this, exec, propertyName, slot); -} - -// Fast call to get a property where we may not yet have converted the string to an -// identifier. The first time we perform a property access with a given string, try -// performing the property map lookup without forming an identifier. We detect this -// case by checking whether the hash has yet been set for this string. -ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const String& name) -{ - if (!structure()->typeInfo().overridesGetOwnPropertySlot() && !structure()->hasGetterSetterProperties()) { - PropertyOffset offset = name.impl()->hasHash() - ? structure()->get(exec->globalData(), Identifier(exec, name)) - : structure()->get(exec->globalData(), name); - if (offset != invalidOffset) - return asObject(this)->locationForOffset(offset)->get(); - } - return JSValue(); -} - // It may seem crazy to inline a function this large but it makes a big difference // since this is function very hot in variable lookup ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) @@ -1268,7 +1224,7 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const } template<JSObject::PutMode mode> -inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction) +inline bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction) { ASSERT(value); ASSERT(value.isGetterSetter() == !!(attributes & Accessor)); @@ -1278,16 +1234,16 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p if (structure()->isDictionary()) { unsigned currentAttributes; JSCell* currentSpecificFunction; - PropertyOffset offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction); + PropertyOffset offset = structure()->get(vm, propertyName, currentAttributes, currentSpecificFunction); if (offset != invalidOffset) { // If there is currently a specific function, and there now either isn't, // or the new value is different, then despecify. if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) - structure()->despecifyDictionaryFunction(globalData, propertyName); + structure()->despecifyDictionaryFunction(vm, propertyName); if ((mode == PutModePut) && currentAttributes & ReadOnly) return false; - putDirectOffset(globalData, offset, value); + putDirect(vm, offset, value); // At this point, the objects structure only has a specific value set if previously there // had been one set, and if the new value being specified is the same (otherwise we would // have despecified, above). So, if currentSpecificFunction is not set, or if the new @@ -1304,13 +1260,13 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p Butterfly* newButterfly = m_butterfly; if (structure()->putWillGrowOutOfLineStorage()) - newButterfly = growOutOfLineStorage(globalData, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity()); - offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction); - setButterfly(globalData, newButterfly, structure()); + newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity()); + offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes, specificFunction); + setButterfly(vm, newButterfly, structure()); validateOffset(offset); ASSERT(structure()->isValidOffset(offset)); - putDirectOffset(globalData, offset, value); + putDirect(vm, offset, value); // See comment on setNewProperty call below. if (!specificFunction) slot.setNewProperty(this, offset); @@ -1324,12 +1280,12 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) { Butterfly* newButterfly = m_butterfly; if (currentCapacity != structure->outOfLineCapacity()) - newButterfly = growOutOfLineStorage(globalData, currentCapacity, structure->outOfLineCapacity()); + newButterfly = growOutOfLineStorage(vm, currentCapacity, structure->outOfLineCapacity()); validateOffset(offset); ASSERT(structure->isValidOffset(offset)); - setButterfly(globalData, newButterfly, structure); - putDirectOffset(globalData, offset, value); + setButterfly(vm, newButterfly, structure); + putDirect(vm, offset, value); // This is a new property; transitions with specific values are not currently cachable, // so leave the slot in an uncachable state. if (!specificFunction) @@ -1339,7 +1295,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p unsigned currentAttributes; JSCell* currentSpecificFunction; - offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction); + offset = structure()->get(vm, propertyName, currentAttributes, currentSpecificFunction); if (offset != invalidOffset) { if ((mode == PutModePut) && currentAttributes & ReadOnly) return false; @@ -1356,29 +1312,29 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p if (currentSpecificFunction) { // case (1) Do the put, then return leaving the slot uncachable. if (specificFunction == currentSpecificFunction) { - putDirectOffset(globalData, offset, value); + putDirect(vm, offset, value); return true; } // case (2) Despecify, fall through to (3). - setStructure(globalData, Structure::despecifyFunctionTransition(globalData, structure(), propertyName)); + setStructure(vm, Structure::despecifyFunctionTransition(vm, structure(), propertyName)); } // case (3) set the slot, do the put, return. slot.setExistingProperty(this, offset); - putDirectOffset(globalData, offset, value); + putDirect(vm, offset, value); return true; } if ((mode == PutModePut) && !isExtensible()) return false; - Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset); + Structure* structure = Structure::addPropertyTransition(vm, this->structure(), propertyName, attributes, specificFunction, offset); validateOffset(offset); ASSERT(structure->isValidOffset(offset)); - setStructureAndReallocateStorageIfNecessary(globalData, structure); + setStructureAndReallocateStorageIfNecessary(vm, structure); - putDirectOffset(globalData, offset, value); + putDirect(vm, offset, value); // This is a new property; transitions with specific values are not currently cachable, // so leave the slot in an uncachable state. if (!specificFunction) @@ -1388,57 +1344,57 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p return true; } -inline void JSObject::setStructureAndReallocateStorageIfNecessary(JSGlobalData& globalData, unsigned oldCapacity, Structure* newStructure) +inline void JSObject::setStructureAndReallocateStorageIfNecessary(VM& vm, unsigned oldCapacity, Structure* newStructure) { ASSERT(oldCapacity <= newStructure->outOfLineCapacity()); if (oldCapacity == newStructure->outOfLineCapacity()) { - setStructure(globalData, newStructure); + setStructure(vm, newStructure); return; } Butterfly* newButterfly = growOutOfLineStorage( - globalData, oldCapacity, newStructure->outOfLineCapacity()); - setButterfly(globalData, newButterfly, newStructure); + vm, oldCapacity, newStructure->outOfLineCapacity()); + setButterfly(vm, newButterfly, newStructure); } -inline void JSObject::setStructureAndReallocateStorageIfNecessary(JSGlobalData& globalData, Structure* newStructure) +inline void JSObject::setStructureAndReallocateStorageIfNecessary(VM& vm, Structure* newStructure) { setStructureAndReallocateStorageIfNecessary( - globalData, structure()->outOfLineCapacity(), newStructure); + vm, structure()->outOfLineCapacity(), newStructure); } -inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +inline bool JSObject::putOwnDataProperty(VM& vm, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); ASSERT(!structure()->hasGetterSetterProperties()); - return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value)); + return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot, getCallableObject(value)); } -inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes) +inline void JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes) { ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); PutPropertySlot slot; - putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getCallableObject(value)); + putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot, getCallableObject(value)); } -inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +inline void JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(!value.isGetterSetter()); - putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getCallableObject(value)); + putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, 0, slot, getCallableObject(value)); } -inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes) +inline void JSObject::putDirectWithoutTransition(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes) { ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); Butterfly* newButterfly = m_butterfly; if (structure()->putWillGrowOutOfLineStorage()) - newButterfly = growOutOfLineStorage(globalData, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity()); - PropertyOffset offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getCallableObject(value)); - setButterfly(globalData, newButterfly, structure()); - putDirectOffset(globalData, offset, value); + newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity()); + PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes, getCallableObject(value)); + setButterfly(vm, newButterfly, structure()); + putDirect(vm, offset, value); } inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const @@ -1446,74 +1402,6 @@ inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType pre return methodTable()->defaultValue(this, exec, preferredType); } -inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName) const -{ - PropertySlot slot(asValue()); - return get(exec, propertyName, slot); -} - -inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const -{ - if (UNLIKELY(!isCell())) { - JSObject* prototype = synthesizePrototype(exec); - if (!prototype->getPropertySlot(exec, propertyName, slot)) - return jsUndefined(); - return slot.getValue(exec, propertyName); - } - JSCell* cell = asCell(); - while (true) { - if (cell->fastGetOwnPropertySlot(exec, propertyName, slot)) - return slot.getValue(exec, propertyName); - JSValue prototype = asObject(cell)->prototype(); - if (!prototype.isObject()) - return jsUndefined(); - cell = asObject(prototype); - } -} - -inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const -{ - PropertySlot slot(asValue()); - return get(exec, propertyName, slot); -} - -inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const -{ - if (UNLIKELY(!isCell())) { - JSObject* prototype = synthesizePrototype(exec); - if (!prototype->getPropertySlot(exec, propertyName, slot)) - return jsUndefined(); - return slot.getValue(exec, propertyName); - } - JSCell* cell = const_cast<JSCell*>(asCell()); - while (true) { - if (cell->methodTable()->getOwnPropertySlotByIndex(cell, exec, propertyName, slot)) - return slot.getValue(exec, propertyName); - JSValue prototype = asObject(cell)->prototype(); - if (!prototype.isObject()) - return jsUndefined(); - cell = prototype.asCell(); - } -} - -inline void JSValue::put(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) -{ - if (UNLIKELY(!isCell())) { - putToPrimitive(exec, propertyName, value, slot); - return; - } - asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot); -} - -inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) -{ - if (UNLIKELY(!isCell())) { - putToPrimitiveByIndex(exec, propertyName, value, shouldThrow); - return; - } - asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow); -} - ALWAYS_INLINE JSObject* Register::function() const { if (!jsValue()) @@ -1533,7 +1421,7 @@ inline size_t offsetInButterfly(PropertyOffset offset) return offsetInOutOfLineStorage(offset) + Butterfly::indexOfPropertyStorage(); } -// This is a helper for patching code where you want to emit a load or store and +// Helpers for patching code where you want to emit a load or store and // the base is: // For inline offsets: a pointer to the out-of-line storage pointer. // For out-of-line offsets: the base of the out-of-line storage. @@ -1544,6 +1432,17 @@ inline size_t offsetRelativeToPatchedStorage(PropertyOffset offset) return JSObject::offsetOfInlineStorage() - JSObject::butterflyOffset() + sizeof(EncodedJSValue) * offsetInInlineStorage(offset); } +// Returns the maximum offset (away from zero) a load instruction will encode. +inline size_t maxOffsetRelativeToPatchedStorage(PropertyOffset offset) +{ + ptrdiff_t addressOffset = static_cast<ptrdiff_t>(offsetRelativeToPatchedStorage(offset)); +#if USE(JSVALUE32_64) + if (addressOffset >= 0) + return static_cast<size_t>(addressOffset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag); +#endif + return static_cast<size_t>(addressOffset); +} + inline int indexRelativeToBase(PropertyOffset offset) { if (isOutOfLineOffset(offset)) @@ -1561,37 +1460,30 @@ inline int offsetRelativeToBase(PropertyOffset offset) COMPILE_ASSERT(!(sizeof(JSObject) % sizeof(WriteBarrierBase<Unknown>)), JSObject_inline_storage_has_correct_alignment); -class JSDestructibleObject : public JSNonFinalObject { -public: - typedef JSNonFinalObject Base; - - static const bool needsDestruction = true; - - const ClassInfo* classInfo() const { return m_classInfo; } - -protected: - JSDestructibleObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly = 0) - : JSNonFinalObject(globalData, structure, butterfly) - , m_classInfo(structure->classInfo()) - { - ASSERT(m_classInfo); - } - -private: - const ClassInfo* m_classInfo; -}; +ALWAYS_INLINE Identifier makeIdentifier(ExecState* exec, const char* name) +{ + return Identifier(exec, name); +} -inline const ClassInfo* JSCell::classInfo() const +ALWAYS_INLINE Identifier makeIdentifier(ExecState*, const Identifier& name) { - if (MarkedBlock::blockFor(this)->destructorType() == MarkedBlock::Normal) - return static_cast<const JSDestructibleObject*>(this)->classInfo(); -#if ENABLE(GC_VALIDATION) - return m_structure.unvalidatedGet()->classInfo(); -#else - return m_structure->classInfo(); -#endif + return name; } +// Helper for defining native functions, if you're not using a static hash table. +// Use this macro from within finishCreation() methods in prototypes. This assumes +// you've defined variables called exec, globalObject, and vm, and they +// have the expected meanings. +#define JSC_NATIVE_INTRINSIC_FUNCTION(jsName, cppName, attributes, length, intrinsic) \ + putDirectNativeFunction(\ + exec, globalObject, makeIdentifier(exec, (jsName)), (length), cppName, \ + (intrinsic), (attributes)) + +// As above, but this assumes that the function you're defining doesn't have an +// intrinsic. +#define JSC_NATIVE_FUNCTION(jsName, cppName, attributes, length) \ + JSC_NATIVE_INTRINSIC_FUNCTION(jsName, cppName, (attributes), (length), NoIntrinsic) + } // namespace JSC #endif // JSObject_h |