summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSObject.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSObject.h')
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h122
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);