Unreviewed, rolling out r121605.
authorzandobersek@gmail.com <zandobersek@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Jun 2012 12:09:15 +0000 (12:09 +0000)
committerzandobersek@gmail.com <zandobersek@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Jun 2012 12:09:15 +0000 (12:09 +0000)
http://trac.webkit.org/changeset/121605
https://bugs.webkit.org/show_bug.cgi?id=90336

Changes caused flaky crashes in sputnik/Unicode tests on Apple
WK1 and GTK Linux builders

* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
* jit/JIT.cpp:
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITInlineMethods.h:
(JSC::JIT::emitAllocateBasicJSObject):
(JSC::JIT::emitAllocateJSFinalObject):
(JSC):
(JSC::JIT::emitAllocateJSFunction):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_new_func):
(JSC::JIT::emitSlow_op_new_func):
(JSC):
(JSC::JIT::emit_op_new_func_exp):
(JSC::JIT::emitSlow_op_new_func_exp):
* runtime/JSFunction.cpp:
(JSC::JSFunction::finishCreation):
* runtime/JSObject.h:
(JSC::JSObject::isUsingInlineStorage):
(JSObject):
(JSC::JSObject::finishCreation):
(JSC):
(JSNonFinalObject):
(JSC::JSNonFinalObject::JSNonFinalObject):
(JSC::JSNonFinalObject::finishCreation):
(JSFinalObject):
(JSC::JSFinalObject::finishCreation):
(JSC::JSObject::offsetOfInlineStorage):
(JSC::JSObject::setPropertyStorage):
(JSC::Structure::isUsingInlineStorage):
(JSC::JSObject::putDirectInternal):
(JSC::JSObject::putDirectWithoutTransition):
(JSC::JSObject::transitionTo):
* runtime/Structure.cpp:
(JSC::Structure::Structure):
(JSC):
(JSC::Structure::growPropertyStorageCapacity):
(JSC::Structure::suggestedNewPropertyStorageSize):
* runtime/Structure.h:
(JSC::Structure::shouldGrowPropertyStorage):
(JSC::Structure::propertyStorageSize):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121627 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITInlineMethods.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h

index a6e2102..2787b12 100644 (file)
@@ -1,3 +1,55 @@
+2012-06-30  Zan Dobersek  <zandobersek@gmail.com>
+
+        Unreviewed, rolling out r121605.
+        http://trac.webkit.org/changeset/121605
+        https://bugs.webkit.org/show_bug.cgi?id=90336
+
+        Changes caused flaky crashes in sputnik/Unicode tests on Apple
+        WK1 and GTK Linux builders
+
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::privateExecute):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITInlineMethods.h:
+        (JSC::JIT::emitAllocateBasicJSObject):
+        (JSC::JIT::emitAllocateJSFinalObject):
+        (JSC):
+        (JSC::JIT::emitAllocateJSFunction):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_new_func):
+        (JSC::JIT::emitSlow_op_new_func):
+        (JSC):
+        (JSC::JIT::emit_op_new_func_exp):
+        (JSC::JIT::emitSlow_op_new_func_exp):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::finishCreation):
+        * runtime/JSObject.h:
+        (JSC::JSObject::isUsingInlineStorage):
+        (JSObject):
+        (JSC::JSObject::finishCreation):
+        (JSC):
+        (JSNonFinalObject):
+        (JSC::JSNonFinalObject::JSNonFinalObject):
+        (JSC::JSNonFinalObject::finishCreation):
+        (JSFinalObject):
+        (JSC::JSFinalObject::finishCreation):
+        (JSC::JSObject::offsetOfInlineStorage):
+        (JSC::JSObject::setPropertyStorage):
+        (JSC::Structure::isUsingInlineStorage):
+        (JSC::JSObject::putDirectInternal):
+        (JSC::JSObject::putDirectWithoutTransition):
+        (JSC::JSObject::transitionTo):
+        * runtime/Structure.cpp:
+        (JSC::Structure::Structure):
+        (JSC):
+        (JSC::Structure::growPropertyStorageCapacity):
+        (JSC::Structure::suggestedNewPropertyStorageSize):
+        * runtime/Structure.h:
+        (JSC::Structure::shouldGrowPropertyStorage):
+        (JSC::Structure::propertyStorageSize):
+
 2012-06-29  Mark Hahnenberg  <mhahnenberg@apple.com>
 
         Remove warning about protected values when the Heap is being destroyed
index 4fdd79a..b8610e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009, 2010, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -3602,7 +3602,7 @@ skip_id_custom_self:
                         proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
                     }
                 }
-                baseObject->setStructureAndReallocateStorageIfNecessary(*globalData, newStructure);
+                baseObject->transitionTo(*globalData, newStructure);
 
                 int value = vPC[3].u.operand;
                 unsigned offset = vPC[7].u.operand;
index d6a5b9d..78b6ad3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -472,6 +472,8 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_neq)
         DEFINE_SLOWCASE_OP(op_new_array)
         DEFINE_SLOWCASE_OP(op_new_object)
+        DEFINE_SLOWCASE_OP(op_new_func)
+        DEFINE_SLOWCASE_OP(op_new_func_exp)
         DEFINE_SLOWCASE_OP(op_not)
         DEFINE_SLOWCASE_OP(op_nstricteq)
         DEFINE_SLOWCASE_OP(op_post_dec)
index 67aa185..6d4c578 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -423,6 +423,7 @@ namespace JSC {
         template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr);
         void emitAllocateBasicStorage(size_t, RegisterID result, RegisterID storagePtr);
         template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
+        void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr);
         void emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr);
         
 #if ENABLE(VALUE_PROFILER)
@@ -749,6 +750,8 @@ namespace JSC {
         void emitSlow_op_to_jsnumber(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_new_func(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_new_func_exp(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_new_array(Instruction*, Vector<SlowCaseEntry>::iterator&);
         
         void emitRightShift(Instruction*, bool isUnsigned);
index fdb9564..40985ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -429,11 +429,8 @@ template <typename ClassType, bool destructor, typename StructureType> inline vo
     storePtr(TrustedImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
 
     // initialize the object's property storage pointer
-    if (ClassType::hasInlineStorage()) {
-        addPtr(TrustedImm32(sizeof(JSObject)), result, storagePtr);
-        storePtr(storagePtr, Address(result, ClassType::offsetOfPropertyStorage()));
-    } else
-        storePtr(TrustedImmPtr(0), Address(result, ClassType::offsetOfPropertyStorage()));
+    addPtr(TrustedImm32(sizeof(JSObject)), result, storagePtr);
+    storePtr(storagePtr, Address(result, ClassType::offsetOfPropertyStorage()));
 }
 
 template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
@@ -441,6 +438,28 @@ template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, Re
     emitAllocateBasicJSObject<JSFinalObject, false, T>(structure, result, scratch);
 }
 
+inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, RegisterID scopeChain, RegisterID result, RegisterID storagePtr)
+{
+    emitAllocateBasicJSObject<JSFunction, true>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), result, storagePtr);
+
+    // store the function's scope chain
+    storePtr(scopeChain, Address(result, JSFunction::offsetOfScopeChain()));
+
+    // store the function's executable member
+    storePtr(TrustedImmPtr(executable), Address(result, JSFunction::offsetOfExecutable()));
+
+    // clear the function's inheritorID
+    storePtr(TrustedImmPtr(0), Address(result, JSFunction::offsetOfCachedInheritorID()));
+
+    // store the function's name
+    ASSERT(executable->nameValue());
+    int functionNameOffset = sizeof(JSValue) * m_codeBlock->globalObject()->functionNameOffset();
+    storePtr(TrustedImmPtr(executable->nameValue()), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+#if USE(JSVALUE32_64)
+    store32(TrustedImm32(JSValue::CellTag), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+#endif
+}
+
 inline void JIT::emitAllocateBasicStorage(size_t size, RegisterID result, RegisterID storagePtr)
 {
     CopiedAllocator* allocator = &m_globalData->heap.storageAllocator();
index d96cfd9..2e448dd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
  * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1618,9 +1618,11 @@ void JIT::emit_op_new_func(Instruction* currentInstruction)
 #endif
     }
 
-    JITStubCall stubCall(this, cti_op_new_func);
-    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
-    stubCall.call(dst);
+    FunctionExecutable* executable = m_codeBlock->functionDecl(currentInstruction[2].u.operand);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+    emitAllocateJSFunction(executable, regT2, regT0, regT1);
+
+    emitStoreCell(dst, regT0);
 
     if (currentInstruction[3].u.operand) {
 #if USE(JSVALUE32_64)        
@@ -1632,13 +1634,44 @@ void JIT::emit_op_new_func(Instruction* currentInstruction)
     }
 }
 
+void JIT::emitSlow_op_new_func(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter);
+    JITStubCall stubCall(this, cti_op_new_func);
+    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
+    stubCall.call(currentInstruction[1].u.operand);
+}
+
 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
+    FunctionExecutable* executable = m_codeBlock->functionExpr(currentInstruction[2].u.operand);
+
+    // We only inline the allocation of a anonymous function expressions
+    // If we want to be able to allocate a named function expression, we would
+    // need to be able to do inline allocation of a JSStaticScopeObject.
+    if (executable->name().isNull()) {
+        emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+        emitAllocateJSFunction(executable, regT2, regT0, regT1);
+        emitStoreCell(currentInstruction[1].u.operand, regT0);
+        return;
+    }
+
     JITStubCall stubCall(this, cti_op_new_func_exp);
     stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
+void JIT::emitSlow_op_new_func_exp(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    FunctionExecutable* executable = m_codeBlock->functionExpr(currentInstruction[2].u.operand);
+    if (!executable->name().isNull())
+        return;
+    linkSlowCase(iter);
+    JITStubCall stubCall(this, cti_op_new_func_exp);
+    stubCall.addArgument(TrustedImmPtr(executable));
+    stubCall.call(currentInstruction[1].u.operand);
+}
+
 void JIT::emit_op_new_array(Instruction* currentInstruction)
 {
     int length = currentInstruction[3].u.operand;
index 0a65dee..f2d9c81 100644 (file)
@@ -103,16 +103,13 @@ void JSFunction::finishCreation(ExecState* exec, NativeExecutable* executable, i
 
 void JSFunction::finishCreation(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode)
 {
-    JSGlobalData& globalData = exec->globalData();
-    Base::finishCreation(globalData);
+    Base::finishCreation(exec->globalData());
     ASSERT(inherits(&s_info));
 
     // Switching the structure here is only safe if we currently have the function structure!
     ASSERT(structure() == scopeChainNode->globalObject->functionStructure());
-    setStructureAndReallocateStorageIfNecessary(
-        globalData,
-        scopeChainNode->globalObject->namedFunctionStructure());
-    putDirectOffset(globalData, scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
+    setStructure(exec->globalData(), scopeChainNode->globalObject->namedFunctionStructure());
+    putDirectOffset(exec->globalData(), scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
 }
 
 Structure* JSFunction::cacheInheritorID(ExecState* exec)
index 9417fe9..fdb708d 100644 (file)
@@ -79,14 +79,6 @@ namespace JSC {
         Accessor     = 1 << 5,  // property is a getter/setter
     };
 
-#if USE(JSVALUE32_64)
-#define JSFinalObject_inlineStorageCapacity 6
-#else
-#define JSFinalObject_inlineStorageCapacity 4
-#endif
-
-COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= 0), final_storage_non_negative);
-
     class JSObject : public JSCell {
         friend class BatchedTransitionOptimizer;
         friend class JIT;
@@ -229,25 +221,16 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= 0), final_storage_non_neg
         void reifyStaticFunctionsForDelete(ExecState* exec);
 
         JS_EXPORT_PRIVATE PropertyStorage growPropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize);
-        bool isUsingInlineStorage() const
-        {
-            bool result =
-                !m_propertyStorage.get()
-                || static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1);
-            ASSERT(result == structure()->isUsingInlineStorage());
-            return result;
-        }
+        bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); }
         void setPropertyStorage(JSGlobalData&, PropertyStorage, Structure*);
-        
-        bool reallocateStorageIfNecessary(JSGlobalData&, unsigned oldCapacity, Structure*);
-        void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, unsigned oldCapacity, Structure*);
-        void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, Structure*);
 
         void* addressOfPropertyStorage()
         {
             return &m_propertyStorage;
         }
 
+        static const unsigned baseExternalStorageCapacity = 16;
+
         void flattenDictionaryObject(JSGlobalData& globalData)
         {
             structure()->flattenDictionaryStructure(globalData, this);
@@ -267,13 +250,14 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= 0), final_storage_non_neg
         static JS_EXPORTDATA const ClassInfo s_info;
 
     protected:
-        void finishCreation(JSGlobalData& globalData)
+        void finishCreation(JSGlobalData& globalData, PropertyStorage inlineStorage)
         {
             Base::finishCreation(globalData);
             ASSERT(inherits(&s_info));
-            ASSERT(structure()->isUsingInlineStorage());
+            ASSERT(structure()->propertyStorageCapacity() < baseExternalStorageCapacity);
             ASSERT(structure()->isEmpty());
             ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
+            ASSERT_UNUSED(inlineStorage, static_cast<void*>(inlineStorage) == static_cast<void*>(this + 1));
             ASSERT(structure()->isObject());
             ASSERT(classInfo());
         }
@@ -332,6 +316,16 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= 0), final_storage_non_neg
     };
 
 
+#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.
@@ -346,23 +340,22 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= 0), final_storage_non_neg
             return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
-        static bool hasInlineStorage()
-        {
-            return false;
-        }
-
     protected:
         explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
-            : JSObject(globalData, structure, 0)
+            : JSObject(globalData, structure, m_inlineStorage)
         {
         }
 
         void finishCreation(JSGlobalData& globalData)
         {
-            Base::finishCreation(globalData);
-            ASSERT(!this->structure()->propertyStorageCapacity());
+            Base::finishCreation(globalData, m_inlineStorage);
+            ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
+            ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
             ASSERT(classInfo());
         }
+
+    private:
+        WriteBarrier<Unknown> m_inlineStorage[JSNonFinalObject_inlineStorageCapacity];
     };
 
     class JSFinalObject;
@@ -383,14 +376,10 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= 0), final_storage_non_neg
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
-        static bool hasInlineStorage()
-        {
-            return true;
-        }
     protected:
         void finishCreation(JSGlobalData& globalData)
         {
-            Base::finishCreation(globalData);
+            Base::finishCreation(globalData, m_inlineStorage);
             ASSERT(!(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double)));
             ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity);
             ASSERT(classInfo());
@@ -428,6 +417,7 @@ inline bool isJSFinalObject(JSValue value)
 
 inline size_t JSObject::offsetOfInlineStorage()
 {
+    ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage));
     return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage);
 }
 
@@ -475,8 +465,6 @@ inline void JSObject::setPropertyStorage(JSGlobalData& globalData, PropertyStora
 {
     ASSERT(storage);
     ASSERT(structure);
-    ASSERT(!structure->isUsingInlineStorage()
-           || (classInfo() == &JSFinalObject::s_info && static_cast<void*>(storage) == static_cast<void*>(this + 1)));
     setStructure(globalData, structure);
     m_propertyStorage.set(globalData, this, storage);
 }
@@ -542,17 +530,9 @@ inline Structure* JSObject::inheritorID(JSGlobalData& globalData)
     return createInheritorID(globalData);
 }
 
-inline size_t Structure::inlineStorageCapacity() const
-{
-    if (classInfo() == &JSFinalObject::s_info)
-        return JSFinalObject_inlineStorageCapacity;
-    return 0;
-}
-
 inline bool Structure::isUsingInlineStorage() const
 {
-    ASSERT(propertyStorageCapacity() >= inlineStorageCapacity());
-    return propertyStorageCapacity() == inlineStorageCapacity();
+    return propertyStorageCapacity() < JSObject::baseExternalStorageCapacity;
 }
 
 inline bool JSCell::inherits(const ClassInfo* info) const
@@ -701,7 +681,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
             return false;
 
         PropertyStorage newStorage = propertyStorage();
-        if (structure()->putWillGrowPropertyStorage())
+        if (structure()->shouldGrowPropertyStorage())
             newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
         offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
         setPropertyStorage(globalData, newStorage, structure());
@@ -766,11 +746,14 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
     if ((mode == PutModePut) && !isExtensible())
         return false;
 
+    PropertyStorage newStorage = propertyStorage();
+    if (structure()->shouldGrowPropertyStorage())
+        newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
+
     Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset);
-    
-    ASSERT(offset < structure->propertyStorageCapacity());
-    setStructureAndReallocateStorageIfNecessary(globalData, structure);
 
+    ASSERT(offset < structure->propertyStorageCapacity());
+    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.
@@ -779,26 +762,6 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
     return true;
 }
 
-inline void JSObject::setStructureAndReallocateStorageIfNecessary(JSGlobalData& globalData, unsigned oldCapacity, Structure* newStructure)
-{
-    ASSERT(oldCapacity <= newStructure->propertyStorageCapacity());
-    
-    if (oldCapacity == newStructure->propertyStorageCapacity()) {
-        setStructure(globalData, newStructure);
-        return;
-    }
-    
-    PropertyStorage newStorage = growPropertyStorage(
-        globalData, oldCapacity, newStructure->suggestedNewPropertyStorageSize());
-    setPropertyStorage(globalData, newStorage, newStructure);
-}
-
-inline void JSObject::setStructureAndReallocateStorageIfNecessary(JSGlobalData& globalData, Structure* newStructure)
-{
-    setStructureAndReallocateStorageIfNecessary(
-        globalData, structure()->propertyStorageCapacity(), newStructure);
-}
-
 inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
 {
     ASSERT(value);
@@ -825,13 +788,21 @@ inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, Prope
 {
     ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
     PropertyStorage newStorage = propertyStorage();
-    if (structure()->putWillGrowPropertyStorage())
+    if (structure()->shouldGrowPropertyStorage())
         newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
     size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getCallableObject(value));
     setPropertyStorage(globalData, newStorage, structure());
     putDirectOffset(globalData, offset, value);
 }
 
+inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure)
+{
+    PropertyStorage newStorage = propertyStorage();
+    if (structure()->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
+        newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
+    setPropertyStorage(globalData, newStorage, newStructure);
+}
+
 inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
 {
     return methodTable()->defaultValue(this, exec, preferredType);
index a2585b0..5691261 100644 (file)
@@ -156,7 +156,7 @@ Structure::Structure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSV
     , m_prototype(globalData, this, prototype)
     , m_classInfo(classInfo)
     , m_transitionWatchpointSet(InitializedWatching)
-    , m_propertyStorageCapacity(typeInfo.isFinalObject() ? JSFinalObject_inlineStorageCapacity : 0)
+    , m_propertyStorageCapacity(typeInfo.isFinalObject() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity)
     , m_offset(noOffset)
     , m_dictionaryKind(NoneDictionaryKind)
     , m_isPinnedPropertyTable(false)
@@ -256,21 +256,19 @@ void Structure::materializePropertyMap(JSGlobalData& globalData)
     }
 }
 
-inline size_t nextPropertyStorageCapacity(size_t currentCapacity)
-{
-    if (!currentCapacity)
-        return 4;
-    return currentCapacity * 2;
-}
-
 void Structure::growPropertyStorageCapacity()
 {
-    m_propertyStorageCapacity = nextPropertyStorageCapacity(m_propertyStorageCapacity);
+    if (isUsingInlineStorage())
+        m_propertyStorageCapacity = JSObject::baseExternalStorageCapacity;
+    else
+        m_propertyStorageCapacity *= 2;
 }
 
 size_t Structure::suggestedNewPropertyStorageSize()
 {
-    return nextPropertyStorageCapacity(m_propertyStorageCapacity);
+    if (isUsingInlineStorage())
+        return JSObject::baseExternalStorageCapacity;
+    return m_propertyStorageCapacity * 2;
 }
  
 void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, PropertyName propertyName)
index bb53c42..448a81c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -103,23 +103,7 @@ namespace JSC {
         bool isFrozen(JSGlobalData&);
         bool isExtensible() const { return !m_preventExtensions; }
         bool didTransition() const { return m_didTransition; }
-        bool putWillGrowPropertyStorage()
-        {
-            ASSERT(propertyStorageCapacity() >= propertyStorageSize());
-            
-            if (!m_propertyTable) {
-                unsigned currentSize = static_cast<unsigned>(m_offset + 1);
-                ASSERT(propertyStorageCapacity() >= currentSize);
-                return currentSize == propertyStorageCapacity();
-            }
-            
-            ASSERT(propertyStorageCapacity() >= m_propertyTable->propertyStorageSize());
-            if (m_propertyTable->hasDeletedOffset())
-                return false;
-            
-            ASSERT(propertyStorageCapacity() >= m_propertyTable->size());
-            return m_propertyTable->size() == propertyStorageCapacity();
-        }
+        bool shouldGrowPropertyStorage() { return propertyStorageCapacity() == propertyStorageSize(); }
         JS_EXPORT_PRIVATE size_t suggestedNewPropertyStorageSize(); 
 
         Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
@@ -155,7 +139,6 @@ namespace JSC {
         void growPropertyStorageCapacity();
         unsigned propertyStorageCapacity() const { ASSERT(structure()->classInfo() == &s_info); return m_propertyStorageCapacity; }
         unsigned propertyStorageSize() const { ASSERT(structure()->classInfo() == &s_info); return (m_propertyTable ? m_propertyTable->propertyStorageSize() : static_cast<unsigned>(m_offset + 1)); }
-        size_t inlineStorageCapacity() const;
         bool isUsingInlineStorage() const;
 
         size_t get(JSGlobalData&, PropertyName);