diff options
author | Ben Murdoch <benm@google.com> | 2011-05-24 11:24:40 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-02 09:53:15 +0100 |
commit | 81bc750723a18f21cd17d1b173cd2a4dda9cea6e (patch) | |
tree | 7a9e5ed86ff429fd347a25153107221543909b19 /Source/JavaScriptCore/runtime/JSObject.h | |
parent | 94088a6d336c1dd80a1e734af51e96abcbb689a7 (diff) | |
download | external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.zip external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.gz external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.bz2 |
Merge WebKit at r80534: Intial merge by Git
Change-Id: Ia7a83357124c9e1cdb1debf55d9661ec0bd09a61
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSObject.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSObject.h | 172 |
1 files changed, 118 insertions, 54 deletions
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index b79249c..2b4db43 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -80,8 +80,6 @@ namespace JSC { friend void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot); public: - explicit JSObject(NonNullPassRefPtr<Structure>); - virtual void markChildren(MarkStack&); ALWAYS_INLINE void markChildrenDirect(MarkStack& markStack); @@ -212,19 +210,19 @@ namespace JSC { virtual bool isStrictModeFunction() const { return false; } virtual bool isErrorInstance() const { return false; } + void seal(); + void freeze(); + void preventExtensions(); + bool isSealed() { return m_structure->isSealed(); } + bool isFrozen() { return m_structure->isFrozen(); } + bool isExtensible() { return m_structure->isExtensible(); } + virtual ComplType exceptionType() const { return Throw; } void allocatePropertyStorage(size_t oldSize, size_t newSize); - void allocatePropertyStorageInline(size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } - static const unsigned inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3; - static const unsigned nonInlineBaseStorageCapacity = 16; - - static PassRefPtr<Structure> createStructure(JSValue prototype) - { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); - } + static const unsigned baseExternalStorageCapacity = 16; void flattenDictionaryObject(JSGlobalData& globalData) { @@ -246,15 +244,28 @@ namespace JSC { ASSERT(index < m_structure->anonymousSlotCount()); return locationForOffset(index)->get(); } + + static size_t offsetOfInlineStorage(); + static JS_EXPORTDATA const ClassInfo s_info; + protected: + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + } + static const unsigned StructureFlags = 0; - + void putThisToAnonymousValue(unsigned index) { locationForOffset(index)->setWithoutWriteBarrier(this); } - + + // To instantiate objects you likely want JSFinalObject, below. + // To create derived types you likely want JSNonFinalObject, below. + JSObject(NonNullPassRefPtr<Structure>, PropertyStorage inlineStorage); + private: // Nobody should ever ask any of these questions on something already known to be a JSObject. using JSCell::isAPIValueWrapper; @@ -265,8 +276,8 @@ namespace JSC { void isObject(); void isString(); - ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } - PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } + ConstPropertyStorage propertyStorage() const { return m_propertyStorage; } + PropertyStorage propertyStorage() { return m_propertyStorage; } const WriteBarrierBase<Unknown>* locationForOffset(size_t offset) const { @@ -287,14 +298,90 @@ namespace JSC { const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; Structure* createInheritorID(); - union { - PropertyStorage m_externalStorage; - WriteBarrierBase<Unknown> m_inlineStorage[inlineStorageCapacity]; - }; - + PropertyStorage m_propertyStorage; RefPtr<Structure> m_inheritorID; }; - + + +#if USE(JSVALUE32_64) +#define JSNonFinalObject_inlineStorageCapacity 4 +#define JSFinalObject_inlineStorageCapacity 6 +#else +#define JSNonFinalObject_inlineStorageCapacity 2 +#define JSFinalObject_inlineStorageCapacity 4 +#endif + +COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineStorageCapacity), final_storage_is_at_least_as_large_as_non_final); + + // 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. + class JSNonFinalObject : public JSObject { + friend class JSObject; + + public: + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + } + + protected: + explicit JSNonFinalObject(NonNullPassRefPtr<Structure> structure) + : JSObject(structure, m_inlineStorage) + { + ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double))); + ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity); + } + + private: + WriteBarrierBase<Unknown> m_inlineStorage[JSNonFinalObject_inlineStorageCapacity]; + }; + + // JSFinalObject is a type of JSObject that contains sufficent internal + // storage to fully make use of the colloctor cell containing it. + class JSFinalObject : public JSObject { + friend class JSObject; + + public: + static JSFinalObject* create(ExecState* exec, NonNullPassRefPtr<Structure> structure) + { + return new (exec) JSFinalObject(structure); + } + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + } + + private: + explicit JSFinalObject(NonNullPassRefPtr<Structure> structure) + : JSObject(structure, m_inlineStorage) + { + ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double) == 0); + ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity); + } + + static const unsigned StructureFlags = JSObject::StructureFlags | IsJSFinalObject; + + WriteBarrierBase<Unknown> m_inlineStorage[JSFinalObject_inlineStorageCapacity]; + }; + +inline size_t JSObject::offsetOfInlineStorage() +{ + ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage)); + return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage); +} + +inline JSObject* constructEmptyObject(ExecState* exec, NonNullPassRefPtr<Structure> structure) +{ + return JSFinalObject::create(exec, structure); +} + +inline PassRefPtr<Structure> createEmptyObjectStructure(JSValue prototype) +{ + return JSFinalObject::createStructure(prototype); +} + inline JSObject* asObject(JSCell* cell) { ASSERT(cell->isObject()); @@ -306,20 +393,21 @@ inline JSObject* asObject(JSValue value) return asObject(value.asCell()); } -inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure) +inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure, PropertyStorage inlineStorage) : JSCell(structure.releaseRef()) // ~JSObject balances this ref() + , m_propertyStorage(inlineStorage) { - ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity); + ASSERT(inherits(&s_info)); + ASSERT(m_structure->propertyStorageCapacity() < baseExternalStorageCapacity); ASSERT(m_structure->isEmpty()); ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); - ASSERT(OBJECT_OFFSETOF(JSObject, m_inlineStorage) % sizeof(double) == 0); } inline JSObject::~JSObject() { ASSERT(m_structure); if (!isUsingInlineStorage()) - delete [] m_externalStorage; + delete [] m_propertyStorage; m_structure->deref(); } @@ -363,7 +451,7 @@ inline Structure* JSObject::inheritorID() inline bool Structure::isUsingInlineStorage() const { - return (propertyStorageCapacity() == JSObject::inlineStorageCapacity); + return propertyStorageCapacity() < JSObject::baseExternalStorageCapacity; } inline bool JSCell::inherits(const ClassInfo* info) const @@ -490,6 +578,9 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } + if (!isExtensible()) + return false; + size_t currentCapacity = m_structure->propertyStorageCapacity(); offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction); if (currentCapacity != m_structure->propertyStorageCapacity()) @@ -551,15 +642,8 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } - // If we have a specific function, we may have got to this point if there is - // already a transition with the correct property name and attributes, but - // specialized to a different function. In this case we just want to give up - // and despecialize the transition. - // In this case we clear the value of specificFunction which will result - // in us adding a non-specific transition, and any subsequent lookup in - // Structure::addPropertyTransitionToExistingStructure will just use that. - if (specificFunction && m_structure->hasTransition(propertyName, attributes)) - specificFunction = 0; + if (!isExtensible()) + return false; RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset); @@ -727,26 +811,6 @@ inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) asCell()->put(exec, propertyName, value); } -ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_t newSize) -{ - ASSERT(newSize > oldSize); - - // It's important that this function not rely on m_structure, since - // we might be in the middle of a transition. - bool wasInline = (oldSize == JSObject::inlineStorageCapacity); - - PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage); - PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize]; - - for (unsigned i = 0; i < oldSize; ++i) - newPropertyStorage[i] = oldPropertyStorage[i]; - - if (!wasInline) - delete [] oldPropertyStorage; - - m_externalStorage = newPropertyStorage; -} - ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) { JSCell::markChildren(markStack); |