diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSObject.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSObject.h | 122 |
1 files changed, 68 insertions, 54 deletions
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 7345bb700..0a4f1c745 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -75,7 +75,7 @@ namespace JSC { friend class JIT; friend class JSCell; friend class MarkedBlock; - JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot); + JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject*, PropertyName, PropertySlot&); enum PutMode { PutModePut, @@ -95,39 +95,39 @@ namespace JSC { Structure* inheritorID(JSGlobalData&); - JSValue get(ExecState*, const Identifier& propertyName) const; + JSValue get(ExecState*, PropertyName) const; JSValue get(ExecState*, unsigned propertyName) const; - bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + bool getPropertySlot(ExecState*, PropertyName, PropertySlot&); bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); + JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, PropertyName, PropertyDescriptor&); - static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); bool allowsAccessFrom(ExecState*); - JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); // putDirect is effectively an unchecked vesion of 'defineOwnProperty': // - the prototype chain is not consulted // - accessors are not called. // - attributes will be respected (after the call the property will exist with the given attributes) - JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); - void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0); - void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); - void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0); - void putDirectAccessor(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes); + 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 putDirectAccessor(JSGlobalData&, PropertyName, JSValue, unsigned attributes); bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const; - JS_EXPORT_PRIVATE bool hasProperty(ExecState*, const Identifier& propertyName) const; + JS_EXPORT_PRIVATE bool hasProperty(ExecState*, PropertyName) const; JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const; - bool hasOwnProperty(ExecState*, const Identifier& propertyName) const; + bool hasOwnProperty(ExecState*, PropertyName) const; - JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName); JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); @@ -148,22 +148,22 @@ namespace JSC { JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*); JSObject* unwrappedObject(); - bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; + bool getPropertySpecificValue(ExecState*, PropertyName, JSCell*& specificFunction) const; // This get function only looks at the property map. - JSValue getDirect(JSGlobalData& globalData, const Identifier& propertyName) const + JSValue getDirect(JSGlobalData& globalData, PropertyName propertyName) const { size_t offset = structure()->get(globalData, propertyName); return offset != WTF::notFound ? getDirectOffset(offset) : JSValue(); } - WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName) + WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName) { size_t offset = structure()->get(globalData, propertyName); return offset != WTF::notFound ? locationForOffset(offset) : 0; } - WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes) + WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName, unsigned& attributes) { JSCell* specificFunction; size_t offset = structure()->get(globalData, propertyName, attributes, specificFunction); @@ -177,7 +177,7 @@ namespace JSC { void transitionTo(JSGlobalData&, Structure*); - void removeDirect(JSGlobalData&, const Identifier& propertyName); + void removeDirect(JSGlobalData&, PropertyName); bool hasCustomProperties() { return structure()->didTransition(); } bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); } @@ -186,14 +186,14 @@ namespace JSC { // - 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&, const Identifier& propertyName, JSValue, PutPropertySlot&); + bool putOwnDataProperty(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&); // Fast access to known property offsets. JSValue getDirectOffset(size_t offset) const { return propertyStorage()[offset].get(); } void putDirectOffset(JSGlobalData& globalData, size_t offset, JSValue value) { propertyStorage()[offset].set(globalData, this, value); } void putUndefinedAtDirectOffset(size_t offset) { propertyStorage()[offset].setUndefined(); } - JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); + JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow); bool isGlobalObject() const; bool isVariableObject() const; @@ -212,8 +212,9 @@ namespace JSC { bool staticFunctionsReified() { return structure()->staticFunctionsReified(); } void reifyStaticFunctionsForDelete(ExecState* exec); - JS_EXPORT_PRIVATE void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); + JS_EXPORT_PRIVATE PropertyStorage growPropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); } + void setPropertyStorage(JSGlobalData&, PropertyStorage, Structure*); void* addressOfPropertyStorage() { @@ -294,12 +295,12 @@ namespace JSC { } template<PutMode> - bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*); + bool putDirectInternal(JSGlobalData&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*); - bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + bool inlineGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&); JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location); - const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; + const HashEntry* findPropertyHashEntry(ExecState*, PropertyName) const; Structure* createInheritorID(JSGlobalData&); StorageBarrier m_propertyStorage; @@ -452,6 +453,14 @@ inline bool JSObject::isGlobalThis() const return structure()->typeInfo().type() == GlobalThisType; } +inline void JSObject::setPropertyStorage(JSGlobalData& globalData, PropertyStorage storage, Structure* structure) +{ + ASSERT(storage); + ASSERT(structure); + setStructure(globalData, structure); + m_propertyStorage.set(globalData, this, storage); +} + inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure) { return JSFinalObject::create(exec, structure); @@ -539,7 +548,7 @@ inline JSObject* JSValue::toThisObject(ExecState* exec) const return isCell() ? asCell()->methodTable()->toThisObject(asCell(), exec) : toThisObjectSlowCase(exec); } -ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) { if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) { if (structure()->hasGetterSetterProperties() && location->isGetterSetter()) @@ -555,12 +564,12 @@ ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Ide // It may seem crazy to inline a function this large, especially a virtual function, // but it makes a big difference to property lookup that derived classes can inline their // base class call to this. -ALWAYS_INLINE bool JSObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +ALWAYS_INLINE bool JSObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { return jsCast<JSObject*>(cell)->inlineGetOwnPropertySlot(exec, propertyName, slot); } -ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) { if (!structure()->typeInfo().overridesGetOwnPropertySlot()) return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot); @@ -585,7 +594,7 @@ ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const UString& // 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, const Identifier& propertyName, PropertySlot& slot) +ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) { JSObject* object = this; while (true) { @@ -611,7 +620,7 @@ ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyN } } -inline JSValue JSObject::get(ExecState* exec, const Identifier& propertyName) const +inline JSValue JSObject::get(ExecState* exec, PropertyName propertyName) const { PropertySlot slot(this); if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot)) @@ -630,7 +639,7 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const } template<JSObject::PutMode mode> -inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction) +inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction) { ASSERT(value); ASSERT(value.isGetterSetter() == !!(attributes & Accessor)); @@ -663,10 +672,11 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi if ((mode == PutModePut) && !isExtensible()) return false; - size_t currentCapacity = structure()->propertyStorageCapacity(); + PropertyStorage newStorage = propertyStorage(); + if (structure()->shouldGrowPropertyStorage()) + newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize()); offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction); - if (currentCapacity != structure()->propertyStorageCapacity()) - allocatePropertyStorage(globalData, currentCapacity, structure()->propertyStorageCapacity()); + setPropertyStorage(globalData, newStorage, structure()); ASSERT(offset < structure()->propertyStorageCapacity()); putDirectOffset(globalData, offset, value); @@ -678,12 +688,13 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi size_t offset; size_t currentCapacity = structure()->propertyStorageCapacity(); - if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) { + if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) { + PropertyStorage newStorage = propertyStorage(); if (currentCapacity != structure->propertyStorageCapacity()) - allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity()); + newStorage = growPropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity()); ASSERT(offset < structure->propertyStorageCapacity()); - setStructure(globalData, structure); + setPropertyStorage(globalData, newStorage, structure); putDirectOffset(globalData, offset, value); // This is a new property; transitions with specific values are not currently cachable, // so leave the slot in an uncachable state. @@ -727,13 +738,14 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi if ((mode == PutModePut) && !isExtensible()) return false; - Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset); + PropertyStorage newStorage = propertyStorage(); + if (structure()->shouldGrowPropertyStorage()) + newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize()); - if (currentCapacity != structure->propertyStorageCapacity()) - allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity()); + Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset); ASSERT(offset < structure->propertyStorageCapacity()); - setStructure(globalData, structure); + setPropertyStorage(globalData, newStorage, structure); putDirectOffset(globalData, offset, value); // This is a new property; transitions with specific values are not currently cachable, // so leave the slot in an uncachable state. @@ -742,7 +754,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } -inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -751,34 +763,36 @@ inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, const Identif return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)); } -inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) +inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes) { ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); PutPropertySlot slot; putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value)); } -inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(!value.isGetterSetter()); putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getJSFunction(value)); } -inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) +inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes) { ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); - size_t currentCapacity = structure()->propertyStorageCapacity(); + PropertyStorage newStorage = propertyStorage(); + if (structure()->shouldGrowPropertyStorage()) + newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize()); size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value)); - if (currentCapacity != structure()->propertyStorageCapacity()) - allocatePropertyStorage(globalData, currentCapacity, structure()->propertyStorageCapacity()); + setPropertyStorage(globalData, newStorage, structure()); putDirectOffset(globalData, offset, value); } inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure) { + PropertyStorage newStorage = propertyStorage(); if (structure()->propertyStorageCapacity() != newStructure->propertyStorageCapacity()) - allocatePropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity()); - setStructure(globalData, newStructure); + newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity()); + setPropertyStorage(globalData, newStorage, newStructure); } inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const @@ -786,13 +800,13 @@ inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType pre return methodTable()->defaultValue(this, exec, preferredType); } -inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName) const +inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName) const { PropertySlot slot(asValue()); return get(exec, propertyName, slot); } -inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const +inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const { if (UNLIKELY(!isCell())) { JSObject* prototype = synthesizePrototype(exec); @@ -836,7 +850,7 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot } } -inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline void JSValue::put(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { if (UNLIKELY(!isCell())) { putToPrimitive(exec, propertyName, value, slot); |