Bug 54524 - Allow JSObject to fully utilize cell's capacity for inline storage.
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Feb 2011 21:35:19 +0000 (21:35 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Feb 2011 21:35:19 +0000 (21:35 +0000)
Reviewed by Geoff Garen.

Currently JSObject is both directly instantiated for regular JS objects, and
derived to implement subtypes. A consequence of this is that we need to ensure
that sufficient space from the cell is left unused and available for any data
members that will be introduced by subclasses of JSObject. By restructuring
the internal storage array out of JSObject we can increase the size in the
internal storage for regular objects.

Add classes JSFinalObject and JSNonFinalObject. JSNonFinalObject retains as
much additional capacity as is currently available to allow for data members
in subclasses. JSFinalObject utilizes all available space for internal storage,
and only allows construction through JSFinalObject::create().

Source/JavaScriptCore:

The additional storage made available in the JSObject means that we need no
longer rely on a union of the internal storage with a pointer to storage that
is only valid for external storage. This means we can go back to always having
a valid pointer to property storage, regardless of whether this is internal or
external. This simplifies some cases of access to the array from C code, and
significantly simplifies JIT access, since repatching no longer needs to be
able to change between a load of the storage pointer / a LEA of the internal
storage.

* API/JSObjectRef.cpp:
(JSObjectMake):
* assembler/ARMAssembler.h:
* assembler/ARMv7Assembler.h:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::repatchPointer):
* assembler/MIPSAssembler.h:
* assembler/MacroAssemblerARM.h:
* assembler/MacroAssemblerARMv7.h:
* assembler/MacroAssemblerMIPS.h:
* assembler/MacroAssemblerX86.h:
* assembler/MacroAssemblerX86_64.h:
* assembler/RepatchBuffer.h:
* assembler/X86Assembler.h:
* debugger/DebuggerActivation.cpp:
(JSC::DebuggerActivation::DebuggerActivation):
* debugger/DebuggerActivation.h:
* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_resolve_global):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_resolve_global):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::emit_op_get_by_pname):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::compilePutDirectOffset):
(JSC::JIT::patchGetByIdSelf):
(JSC::JIT::patchPutByIdReplace):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::compilePutDirectOffset):
(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::patchGetByIdSelf):
(JSC::JIT::patchPutByIdReplace):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):
(JSC::JIT::emit_op_get_by_pname):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* runtime/Arguments.h:
(JSC::Arguments::Arguments):
* runtime/ErrorInstance.cpp:
(JSC::ErrorInstance::ErrorInstance):
* runtime/ErrorInstance.h:
* runtime/ExceptionHelpers.cpp:
(JSC::InterruptedExecutionError::InterruptedExecutionError):
(JSC::TerminatedExecutionError::TerminatedExecutionError):
* runtime/JSArray.cpp:
(JSC::JSArray::JSArray):
* runtime/JSArray.h:
* runtime/JSByteArray.cpp:
(JSC::JSByteArray::JSByteArray):
* runtime/JSByteArray.h:
(JSC::JSByteArray::JSByteArray):
* runtime/JSFunction.cpp:
(JSC::JSFunction::getOwnPropertySlot):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalObject.h:
(JSC::constructEmptyObject):
* runtime/JSNotAnObject.h:
(JSC::JSNotAnObject::JSNotAnObject):
* runtime/JSObject.cpp:
(JSC::JSObject::createInheritorID):
(JSC::JSObject::allocatePropertyStorage):
* runtime/JSObject.h:
(JSC::JSObject::propertyStorage):
(JSC::JSNonFinalObject::JSNonFinalObject):
(JSC::JSNonFinalObject::createStructure):
(JSC::JSFinalObject::create):
(JSC::JSFinalObject::createStructure):
(JSC::JSFinalObject::JSFinalObject):
(JSC::JSObject::offsetOfInlineStorage):
(JSC::constructEmptyObject):
(JSC::createEmptyObjectStructure):
(JSC::JSObject::JSObject):
(JSC::JSObject::~JSObject):
(JSC::Structure::isUsingInlineStorage):
* runtime/JSObjectWithGlobalObject.cpp:
(JSC::JSObjectWithGlobalObject::JSObjectWithGlobalObject):
* runtime/JSObjectWithGlobalObject.h:
(JSC::JSObjectWithGlobalObject::JSObjectWithGlobalObject):
* runtime/JSTypeInfo.h:
(JSC::TypeInfo::TypeInfo):
(JSC::TypeInfo::isVanilla):
* runtime/JSVariableObject.h:
(JSC::JSVariableObject::JSVariableObject):
* runtime/JSWrapperObject.h:
(JSC::JSWrapperObject::JSWrapperObject):
* runtime/ObjectConstructor.cpp:
(JSC::constructObject):
* runtime/ObjectPrototype.cpp:
(JSC::ObjectPrototype::ObjectPrototype):
* runtime/ObjectPrototype.h:
* runtime/StrictEvalActivation.cpp:
(JSC::StrictEvalActivation::StrictEvalActivation):
* runtime/StrictEvalActivation.h:
* runtime/Structure.cpp:
(JSC::Structure::Structure):
(JSC::Structure::growPropertyStorageCapacity):

Source/JavaScriptGlue:

* UserObjectImp.cpp:
* UserObjectImp.h:
    Update JSObject -> JSNonFinalObject.

Source/WebCore:

* bindings/js/JSDOMWindowShell.h:
    Update JSObject -> JSNonFinalObject.

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

55 files changed:
Source/JavaScriptCore/API/JSObjectRef.cpp
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/assembler/ARMAssembler.h
Source/JavaScriptCore/assembler/ARMv7Assembler.h
Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
Source/JavaScriptCore/assembler/MIPSAssembler.h
Source/JavaScriptCore/assembler/MacroAssemblerARM.h
Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
Source/JavaScriptCore/assembler/MacroAssemblerX86.h
Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
Source/JavaScriptCore/assembler/RepatchBuffer.h
Source/JavaScriptCore/assembler/X86Assembler.h
Source/JavaScriptCore/debugger/DebuggerActivation.cpp
Source/JavaScriptCore/debugger/DebuggerActivation.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/runtime/Arguments.h
Source/JavaScriptCore/runtime/ErrorInstance.cpp
Source/JavaScriptCore/runtime/ErrorInstance.h
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSArray.h
Source/JavaScriptCore/runtime/JSByteArray.cpp
Source/JavaScriptCore/runtime/JSByteArray.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGlobalData.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSNotAnObject.h
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp
Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h
Source/JavaScriptCore/runtime/JSTypeInfo.h
Source/JavaScriptCore/runtime/JSVariableObject.h
Source/JavaScriptCore/runtime/JSWrapperObject.h
Source/JavaScriptCore/runtime/MarkedBlock.h
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/ObjectPrototype.cpp
Source/JavaScriptCore/runtime/ObjectPrototype.h
Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
Source/JavaScriptCore/runtime/StrictEvalActivation.h
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptGlue/ChangeLog
Source/JavaScriptGlue/UserObjectImp.cpp
Source/JavaScriptGlue/UserObjectImp.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSDOMWindowShell.h
Source/WebCore/bridge/qt/qt_runtime.cpp
Source/WebCore/bridge/testqtbindings.cpp

index d3c1993..a46ce94 100644 (file)
@@ -79,7 +79,7 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
     APIEntryShim entryShim(exec);
 
     if (!jsClass)
-        return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient
+        return toRef(constructEmptyObject(exec));
 
     JSCallbackObject<JSObjectWithGlobalObject>* object = new (exec) JSCallbackObject<JSObjectWithGlobalObject>(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
     if (JSObject* prototype = jsClass->prototype(exec))
index afd2709..9f81b2b 100644 (file)
@@ -1,3 +1,144 @@
+2011-02-15  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Geoff Garen.
+
+        Bug 54524 - Allow JSObject to fully utilize cell's capacity for inline storage.
+
+        Currently JSObject is both directly instantiated for regular JS objects, and
+        derived to implement subtypes. A consequence of this is that we need to ensure
+        that sufficient space from the cell is left unused and available for any data
+        members that will be introduced by subclasses of JSObject. By restructuring
+        the internal storage array out of JSObject we can increase the size in the
+        internal storage for regular objects.
+
+        Add classes JSFinalObject and JSNonFinalObject. JSNonFinalObject retains as
+        much additional capacity as is currently available to allow for data members
+        in subclasses. JSFinalObject utilizes all available space for internal storage,
+        and only allows construction through JSFinalObject::create().
+
+        The additional storage made available in the JSObject means that we need no
+        longer rely on a union of the internal storage with a pointer to storage that
+        is only valid for external storage. This means we can go back to always having
+        a valid pointer to property storage, regardless of whether this is internal or
+        external. This simplifies some cases of access to the array from C code, and
+        significantly simplifies JIT access, since repatching no longer needs to be
+        able to change between a load of the storage pointer / a LEA of the internal
+        storage.
+
+        * API/JSObjectRef.cpp:
+        (JSObjectMake):
+        * assembler/ARMAssembler.h:
+        * assembler/ARMv7Assembler.h:
+        * assembler/AbstractMacroAssembler.h:
+        (JSC::AbstractMacroAssembler::repatchPointer):
+        * assembler/MIPSAssembler.h:
+        * assembler/MacroAssemblerARM.h:
+        * assembler/MacroAssemblerARMv7.h:
+        * assembler/MacroAssemblerMIPS.h:
+        * assembler/MacroAssemblerX86.h:
+        * assembler/MacroAssemblerX86_64.h:
+        * assembler/RepatchBuffer.h:
+        * assembler/X86Assembler.h:
+        * debugger/DebuggerActivation.cpp:
+        (JSC::DebuggerActivation::DebuggerActivation):
+        * debugger/DebuggerActivation.h:
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::privateExecute):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_resolve_global):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_resolve_global):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::compileGetDirectOffset):
+        (JSC::JIT::emit_op_get_by_pname):
+        (JSC::JIT::compileGetByIdHotPath):
+        (JSC::JIT::emit_op_put_by_id):
+        (JSC::JIT::compilePutDirectOffset):
+        (JSC::JIT::patchGetByIdSelf):
+        (JSC::JIT::patchPutByIdReplace):
+        (JSC::JIT::privateCompileGetByIdProto):
+        (JSC::JIT::privateCompileGetByIdSelfList):
+        (JSC::JIT::privateCompileGetByIdProtoList):
+        (JSC::JIT::privateCompileGetByIdChainList):
+        (JSC::JIT::privateCompileGetByIdChain):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::compileGetByIdHotPath):
+        (JSC::JIT::emit_op_put_by_id):
+        (JSC::JIT::compilePutDirectOffset):
+        (JSC::JIT::compileGetDirectOffset):
+        (JSC::JIT::patchGetByIdSelf):
+        (JSC::JIT::patchPutByIdReplace):
+        (JSC::JIT::privateCompileGetByIdProto):
+        (JSC::JIT::privateCompileGetByIdSelfList):
+        (JSC::JIT::privateCompileGetByIdProtoList):
+        (JSC::JIT::privateCompileGetByIdChainList):
+        (JSC::JIT::privateCompileGetByIdChain):
+        (JSC::JIT::emit_op_get_by_pname):
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * runtime/Arguments.h:
+        (JSC::Arguments::Arguments):
+        * runtime/ErrorInstance.cpp:
+        (JSC::ErrorInstance::ErrorInstance):
+        * runtime/ErrorInstance.h:
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::InterruptedExecutionError::InterruptedExecutionError):
+        (JSC::TerminatedExecutionError::TerminatedExecutionError):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::JSArray):
+        * runtime/JSArray.h:
+        * runtime/JSByteArray.cpp:
+        (JSC::JSByteArray::JSByteArray):
+        * runtime/JSByteArray.h:
+        (JSC::JSByteArray::JSByteArray):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::getOwnPropertySlot):
+        * runtime/JSGlobalData.cpp:
+        (JSC::JSGlobalData::JSGlobalData):
+        * runtime/JSGlobalObject.h:
+        (JSC::constructEmptyObject):
+        * runtime/JSNotAnObject.h:
+        (JSC::JSNotAnObject::JSNotAnObject):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::createInheritorID):
+        (JSC::JSObject::allocatePropertyStorage):
+        * runtime/JSObject.h:
+        (JSC::JSObject::propertyStorage):
+        (JSC::JSNonFinalObject::JSNonFinalObject):
+        (JSC::JSNonFinalObject::createStructure):
+        (JSC::JSFinalObject::create):
+        (JSC::JSFinalObject::createStructure):
+        (JSC::JSFinalObject::JSFinalObject):
+        (JSC::JSObject::offsetOfInlineStorage):
+        (JSC::constructEmptyObject):
+        (JSC::createEmptyObjectStructure):
+        (JSC::JSObject::JSObject):
+        (JSC::JSObject::~JSObject):
+        (JSC::Structure::isUsingInlineStorage):
+        * runtime/JSObjectWithGlobalObject.cpp:
+        (JSC::JSObjectWithGlobalObject::JSObjectWithGlobalObject):
+        * runtime/JSObjectWithGlobalObject.h:
+        (JSC::JSObjectWithGlobalObject::JSObjectWithGlobalObject):
+        * runtime/JSTypeInfo.h:
+        (JSC::TypeInfo::TypeInfo):
+        (JSC::TypeInfo::isVanilla):
+        * runtime/JSVariableObject.h:
+        (JSC::JSVariableObject::JSVariableObject):
+        * runtime/JSWrapperObject.h:
+        (JSC::JSWrapperObject::JSWrapperObject):
+        * runtime/ObjectConstructor.cpp:
+        (JSC::constructObject):
+        * runtime/ObjectPrototype.cpp:
+        (JSC::ObjectPrototype::ObjectPrototype):
+        * runtime/ObjectPrototype.h:
+        * runtime/StrictEvalActivation.cpp:
+        (JSC::StrictEvalActivation::StrictEvalActivation):
+        * runtime/StrictEvalActivation.h:
+        * runtime/Structure.cpp:
+        (JSC::Structure::Structure):
+        (JSC::Structure::growPropertyStorageCapacity):
+
 2011-02-16  Oliver Hunt  <oliver@apple.com>
 
         Reviewed by Geoff Garen.
index 77ec60f..3828488 100644 (file)
@@ -786,17 +786,6 @@ namespace JSC {
             patchPointerInternal(reinterpret_cast<intptr_t>(from), to);
         }
 
-        static void repatchLoadPtrToLEA(void* from)
-        {
-            // On arm, this is a patch from LDR to ADD. It is restricted conversion,
-            // from special case to special case, altough enough for its purpose
-            ARMWord* insn = reinterpret_cast<ARMWord*>(from);
-            ASSERT((*insn & 0x0ff00f00) == 0x05900000);
-
-            *insn = (*insn & 0xf00ff0ff) | 0x02800000;
-            ExecutableAllocator::cacheFlush(insn, sizeof(ARMWord));
-        }
-
         // Linkers
         static intptr_t getAbsoluteJumpAddress(void* base, int offset = 0)
         {
index 874dcde..ab21ec3 100644 (file)
@@ -1845,22 +1845,6 @@ public:
         setPointer(where, value);
     }
 
-    static void repatchLoadPtrToLEA(void* where)
-    {
-        ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
-        uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
-
-        ASSERT((loadOp[0] & 0xfff0) == OP_LDR_reg_T2);
-        ASSERT((loadOp[1] & 0x0ff0) == 0);
-        int rn = loadOp[0] & 0xf;
-        int rt = loadOp[1] >> 12;
-        int rm = loadOp[1] & 0xf;
-
-        loadOp[0] = OP_ADD_reg_T3 | rn;
-        loadOp[1] = rt << 8 | rm;
-        ExecutableAllocator::cacheFlush(loadOp, sizeof(uint32_t));
-    }
-
 private:
     // VFP operations commonly take one or more 5-bit operands, typically representing a
     // floating point register number.  This will commonly be encoded in the instruction
index 07bd702..5ebc572 100644 (file)
@@ -535,11 +535,6 @@ protected:
     {
         AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
     }
-
-    static void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
-    {
-        AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation());
-    }
 };
 
 } // namespace JSC
index f7bea6c..6030680 100644 (file)
@@ -811,19 +811,7 @@ public:
         repatchInt32(from, reinterpret_cast<int32_t>(to));
     }
 
-    static void repatchLoadPtrToLEA(void* from)
-    {
-        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
-        insn = insn + 3;
-        ASSERT((*insn & 0xfc000000) == 0x8c000000); // lw
-        /* lw -> addiu */
-        *insn = 0x24000000 | (*insn & 0x03ffffff);
-
-        ExecutableAllocator::cacheFlush(insn, sizeof(MIPSWord));
-    }
-
 private:
-
     /* Update each jump in the buffer of newBase.  */
     void relocateJumps(void* oldBase, void* newBase)
     {
index 3fcfec8..66814b5 100644 (file)
@@ -271,13 +271,6 @@ public:
         return dataLabel;
     }
 
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
-    {
-        Label label(this);
-        load32(address, dest);
-        return label;
-    }
-
     void load16(BaseIndex address, RegisterID dest)
     {
         m_assembler.add_r(ARMRegisters::S1, address.base, m_assembler.lsl(address.index, address.scale));
index a3c1301..450a34c 100644 (file)
@@ -478,14 +478,6 @@ public:
         return label;
     }
 
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
-    {
-        Label label(this);
-        moveFixedWidthEncoding(Imm32(address.offset), dataTempRegister);
-        load32(ArmAddress(address.base, dataTempRegister), dest);
-        return label;
-    }
-
     void load16(BaseIndex address, RegisterID dest)
     {
         m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale);
index fcfbcda..4697dfc 100644 (file)
@@ -608,23 +608,6 @@ public:
         return dataLabel;
     }
 
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
-    {
-        m_fixedWidth = true;
-        /*
-            lui         addrTemp, address.offset >> 16
-            ori         addrTemp, addrTemp, address.offset & 0xffff
-            addu        addrTemp, addrTemp, address.base
-            lw          dest, 0(addrTemp)
-        */
-        Label label(this);
-        move(Imm32(address.offset), addrTempRegister);
-        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
-        m_assembler.lw(dest, addrTempRegister, 0);
-        m_fixedWidth = false;
-        return label;
-    }
-
     /* Need to use zero-extened load half-word for load16.  */
     void load16(ImplicitAddress address, RegisterID dest)
     {
index 0918996..92da5f0 100644 (file)
@@ -162,13 +162,6 @@ public:
         return DataLabelPtr(this);
     }
 
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
-    {
-        Label label(this);
-        load32(address, dest);
-        return label;
-    }
-
     bool supportsFloatingPoint() const { return m_isSSE2Present; }
     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
     bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
index 168c93f..ebbe0bd 100644 (file)
@@ -417,13 +417,6 @@ public:
         return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask);
     }
 
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
-    {
-        Label label(this);
-        loadPtr(address, dest);
-        return label;
-    }
-
     bool supportsFloatingPoint() const { return true; }
     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
     bool supportsFloatingPointTruncate() const { return true; }
index 72cf6b2..e9feb65 100644 (file)
@@ -92,11 +92,6 @@ public:
         MacroAssembler::repatchPointer(dataLabelPtr, value);
     }
 
-    void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
-    {
-        MacroAssembler::repatchLoadPtrToLEA(instruction);
-    }
-
     void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label)
     {
         relink(CodeLocationCall(CodePtr(returnAddress)), label);
index b352ad4..587d900 100644 (file)
@@ -1580,16 +1580,6 @@ public:
         setPointer(where, value);
     }
 
-    static void repatchLoadPtrToLEA(void* where)
-    {
-#if CPU(X86_64)
-        // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
-        // Skip over the prefix byte.
-        where = reinterpret_cast<char*>(where) + 1;
-#endif
-        *reinterpret_cast<unsigned char*>(where) = static_cast<unsigned char>(OP_LEA);
-    }
-    
     static unsigned getCallReturnOffset(JmpSrc call)
     {
         ASSERT(call.m_offset >= 0);
index fcd257c..62a2e54 100644 (file)
@@ -31,7 +31,7 @@
 namespace JSC {
 
 DebuggerActivation::DebuggerActivation(JSGlobalData& globalData, JSObject* activation)
-    : JSObject(DebuggerActivation::createStructure(jsNull()))
+    : JSNonFinalObject(DebuggerActivation::createStructure(jsNull()))
 {
     ASSERT(activation);
     ASSERT(activation->isActivationObject());
index b64060d..d20e3c4 100644 (file)
@@ -32,7 +32,7 @@ namespace JSC {
 
     class JSActivation;
 
-    class DebuggerActivation : public JSObject {
+    class DebuggerActivation : public JSNonFinalObject {
     public:
         DebuggerActivation(JSGlobalData&, JSObject*);
 
index b9a3b38..db2e32f 100644 (file)
@@ -4279,7 +4279,7 @@ skip_id_custom_self:
             structure = asObject(proto)->inheritorID();
         else
             structure = constructor->scope().node()->globalObject->emptyObjectStructure();
-        callFrame->uncheckedR(thisRegister) = JSValue(new (&callFrame->globalData()) JSObject(structure));
+        callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure);
 
         vPC += OPCODE_LENGTH(op_create_this);
         NEXT_INSTRUCTION();
index dc1650d..524bc17 100644 (file)
@@ -332,8 +332,8 @@ namespace JSC {
         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
 #endif
         void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset);
-        void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
-        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset);
+        void compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset);
         void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset);
 
         // Arithmetic opcode helpers
@@ -344,15 +344,11 @@ namespace JSC {
 #if CPU(X86)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 7;
-        static const int patchOffsetPutByIdExternalLoad = 13;
-        static const int patchLengthPutByIdExternalLoad = 3;
         static const int patchOffsetPutByIdPropertyMapOffset1 = 22;
         static const int patchOffsetPutByIdPropertyMapOffset2 = 28;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 7;
         static const int patchOffsetGetByIdBranchToSlowCase = 13;
-        static const int patchOffsetGetByIdExternalLoad = 13;
-        static const int patchLengthGetByIdExternalLoad = 3;
         static const int patchOffsetGetByIdPropertyMapOffset1 = 22;
         static const int patchOffsetGetByIdPropertyMapOffset2 = 28;
         static const int patchOffsetGetByIdPutResult = 28;
@@ -369,15 +365,11 @@ namespace JSC {
 #elif CPU(ARM_TRADITIONAL)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 4;
-        static const int patchOffsetPutByIdExternalLoad = 16;
-        static const int patchLengthPutByIdExternalLoad = 4;
         static const int patchOffsetPutByIdPropertyMapOffset1 = 20;
         static const int patchOffsetPutByIdPropertyMapOffset2 = 28;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 4;
         static const int patchOffsetGetByIdBranchToSlowCase = 16;
-        static const int patchOffsetGetByIdExternalLoad = 16;
-        static const int patchLengthGetByIdExternalLoad = 4;
         static const int patchOffsetGetByIdPropertyMapOffset1 = 20;
         static const int patchOffsetGetByIdPropertyMapOffset2 = 28;
         static const int patchOffsetGetByIdPutResult = 36;
@@ -410,15 +402,11 @@ namespace JSC {
 #elif CPU(ARM_THUMB2)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
-        static const int patchOffsetPutByIdExternalLoad = 26;
-        static const int patchLengthPutByIdExternalLoad = 12;
         static const int patchOffsetPutByIdPropertyMapOffset1 = 46;
         static const int patchOffsetPutByIdPropertyMapOffset2 = 58;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 10;
         static const int patchOffsetGetByIdBranchToSlowCase = 26;
-        static const int patchOffsetGetByIdExternalLoad = 26;
-        static const int patchLengthGetByIdExternalLoad = 12;
         static const int patchOffsetGetByIdPropertyMapOffset1 = 46;
         static const int patchOffsetGetByIdPropertyMapOffset2 = 58;
         static const int patchOffsetGetByIdPutResult = 62;
@@ -451,14 +439,10 @@ namespace JSC {
 #elif CPU(MIPS)
 #if WTF_MIPS_ISA(1)
         static const int patchOffsetPutByIdStructure = 16;
-        static const int patchOffsetPutByIdExternalLoad = 48;
-        static const int patchLengthPutByIdExternalLoad = 20;
         static const int patchOffsetPutByIdPropertyMapOffset1 = 68;
         static const int patchOffsetPutByIdPropertyMapOffset2 = 84;
         static const int patchOffsetGetByIdStructure = 16;
         static const int patchOffsetGetByIdBranchToSlowCase = 48;
-        static const int patchOffsetGetByIdExternalLoad = 48;
-        static const int patchLengthGetByIdExternalLoad = 20;
         static const int patchOffsetGetByIdPropertyMapOffset1 = 68;
         static const int patchOffsetGetByIdPropertyMapOffset2 = 88;
         static const int patchOffsetGetByIdPutResult = 108;
@@ -473,14 +457,10 @@ namespace JSC {
         static const int patchOffsetMethodCheckPutFunction = 88;
 #else // WTF_MIPS_ISA(1)
         static const int patchOffsetPutByIdStructure = 12;
-        static const int patchOffsetPutByIdExternalLoad = 44;
-        static const int patchLengthPutByIdExternalLoad = 16;
         static const int patchOffsetPutByIdPropertyMapOffset1 = 60;
         static const int patchOffsetPutByIdPropertyMapOffset2 = 76;
         static const int patchOffsetGetByIdStructure = 12;
         static const int patchOffsetGetByIdBranchToSlowCase = 44;
-        static const int patchOffsetGetByIdExternalLoad = 44;
-        static const int patchLengthGetByIdExternalLoad = 16;
         static const int patchOffsetGetByIdPropertyMapOffset1 = 60;
         static const int patchOffsetGetByIdPropertyMapOffset2 = 76;
         static const int patchOffsetGetByIdPutResult = 92;
@@ -551,21 +531,17 @@ namespace JSC {
         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
 #endif
         void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset);
-        void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset);
-        void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch);
+        void compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch);
         void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset);
 
 #if CPU(X86_64)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
-        static const int patchOffsetPutByIdExternalLoad = 20;
-        static const int patchLengthPutByIdExternalLoad = 4;
         static const int patchOffsetPutByIdPropertyMapOffset = 31;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 10;
         static const int patchOffsetGetByIdBranchToSlowCase = 20;
-        static const int patchOffsetGetByIdExternalLoad = 20;
-        static const int patchLengthGetByIdExternalLoad = 4;
         static const int patchOffsetGetByIdPropertyMapOffset = 31;
         static const int patchOffsetGetByIdPutResult = 31;
 #if ENABLE(OPCODE_SAMPLING)
@@ -581,14 +557,10 @@ namespace JSC {
 #elif CPU(X86)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 7;
-        static const int patchOffsetPutByIdExternalLoad = 13;
-        static const int patchLengthPutByIdExternalLoad = 3;
         static const int patchOffsetPutByIdPropertyMapOffset = 22;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 7;
         static const int patchOffsetGetByIdBranchToSlowCase = 13;
-        static const int patchOffsetGetByIdExternalLoad = 13;
-        static const int patchLengthGetByIdExternalLoad = 3;
         static const int patchOffsetGetByIdPropertyMapOffset = 22;
         static const int patchOffsetGetByIdPutResult = 22;
 #if ENABLE(OPCODE_SAMPLING)
@@ -604,14 +576,10 @@ namespace JSC {
 #elif CPU(ARM_THUMB2)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
-        static const int patchOffsetPutByIdExternalLoad = 26;
-        static const int patchLengthPutByIdExternalLoad = 12;
         static const int patchOffsetPutByIdPropertyMapOffset = 46;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 10;
         static const int patchOffsetGetByIdBranchToSlowCase = 26;
-        static const int patchOffsetGetByIdExternalLoad = 26;
-        static const int patchLengthGetByIdExternalLoad = 12;
         static const int patchOffsetGetByIdPropertyMapOffset = 46;
         static const int patchOffsetGetByIdPutResult = 50;
 #if ENABLE(OPCODE_SAMPLING)
@@ -627,14 +595,10 @@ namespace JSC {
 #elif CPU(ARM_TRADITIONAL)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 4;
-        static const int patchOffsetPutByIdExternalLoad = 16;
-        static const int patchLengthPutByIdExternalLoad = 4;
         static const int patchOffsetPutByIdPropertyMapOffset = 20;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 4;
         static const int patchOffsetGetByIdBranchToSlowCase = 16;
-        static const int patchOffsetGetByIdExternalLoad = 16;
-        static const int patchLengthGetByIdExternalLoad = 4;
         static const int patchOffsetGetByIdPropertyMapOffset = 20;
         static const int patchOffsetGetByIdPutResult = 28;
 #if ENABLE(OPCODE_SAMPLING)
@@ -666,13 +630,9 @@ namespace JSC {
 #elif CPU(MIPS)
 #if WTF_MIPS_ISA(1)
         static const int patchOffsetPutByIdStructure = 16;
-        static const int patchOffsetPutByIdExternalLoad = 48;
-        static const int patchLengthPutByIdExternalLoad = 20;
         static const int patchOffsetPutByIdPropertyMapOffset = 68;
         static const int patchOffsetGetByIdStructure = 16;
         static const int patchOffsetGetByIdBranchToSlowCase = 48;
-        static const int patchOffsetGetByIdExternalLoad = 48;
-        static const int patchLengthGetByIdExternalLoad = 20;
         static const int patchOffsetGetByIdPropertyMapOffset = 68;
         static const int patchOffsetGetByIdPutResult = 88;
 #if ENABLE(OPCODE_SAMPLING)
@@ -686,13 +646,9 @@ namespace JSC {
         static const int patchOffsetMethodCheckPutFunction = 88;
 #else // WTF_MIPS_ISA(1)
         static const int patchOffsetPutByIdStructure = 12;
-        static const int patchOffsetPutByIdExternalLoad = 44;
-        static const int patchLengthPutByIdExternalLoad = 16;
         static const int patchOffsetPutByIdPropertyMapOffset = 60;
         static const int patchOffsetGetByIdStructure = 12;
         static const int patchOffsetGetByIdBranchToSlowCase = 44;
-        static const int patchOffsetGetByIdExternalLoad = 44;
-        static const int patchLengthGetByIdExternalLoad = 16;
         static const int patchOffsetGetByIdPropertyMapOffset = 60;
         static const int patchOffsetGetByIdPutResult = 76;
 #if ENABLE(OPCODE_SAMPLING)
index f458ea2..4ea5ec0 100644 (file)
@@ -689,7 +689,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
 
     // Load cached property
     // Assume that the global object always uses external storage.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT0);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT0);
     load32(offsetAddr, regT1);
     loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand);
index dda74c8..c3c01c4 100644 (file)
@@ -804,7 +804,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
     addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure))));
 
     // Load property.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT2);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT2);
     load32(offsetAddr, regT3);
     load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
     load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
index 1b95eec..b497319 100644 (file)
@@ -138,18 +138,10 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
     stubCall.call(dst);
 }
 
-void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch)
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch)
 {
-    ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
-    ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
-
-    Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
-    loadPtr(BaseIndex(base, offset, ScalePtr, OBJECT_OFFSETOF(JSObject, m_inlineStorage)), result);
-    Jump finishedLoad = jump();
-    notUsingInlineStorage.link(this);
-    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), scratch);
+    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), scratch);
     loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result);
-    finishedLoad.link(this);
 }
 
 void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
@@ -172,7 +164,7 @@ void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
     load32(addressFor(i), regT3);
     sub32(Imm32(1), regT3);
     addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
-    compileGetDirectOffset(regT0, regT0, regT2, regT3, regT1);
+    compileGetDirectOffset(regT0, regT0, regT3, regT1);
 
     emitPutVirtualRegister(dst, regT0);
 }
@@ -427,11 +419,7 @@ void JIT::compileGetByIdHotPath(int, int baseVReg, Identifier*, unsigned propert
     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure);
     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase)
 
-    Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
-    Label externalLoadComplete(this);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetGetByIdExternalLoad);
-    ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthGetByIdExternalLoad);
-
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
     DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel), patchOffsetGetByIdPropertyMapOffset);
 
@@ -507,12 +495,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure);
 
-    // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
-    Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
-    Label externalLoadComplete(this);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetPutByIdExternalLoad);
-    ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthPutByIdExternalLoad);
-
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
     DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));
 
     END_UNINTERRUPTED_SEQUENCE(sequencePutById);
@@ -547,9 +530,9 @@ void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, Structure* s
 {
     int offset = cachedOffset * sizeof(JSValue);
     if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
+        offset += JSObject::offsetOfInlineStorage();
     else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
     storePtr(value, Address(base, offset));
 }
 
@@ -557,22 +540,18 @@ void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, Structure* s
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset)
 {
     int offset = cachedOffset * sizeof(JSValue);
-    if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
-    else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
-    loadPtr(Address(base, offset), result);
+    if (structure->isUsingInlineStorage()) {
+        offset += JSObject::offsetOfInlineStorage();
+        loadPtr(Address(base, offset), result);
+    } else {
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), result);
+        loadPtr(Address(result, offset), result);
+    }
 }
 
-void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset)
+void JIT::compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset)
 {
-    if (base->isUsingInlineStorage())
-        loadPtr(static_cast<void*>(&base->m_inlineStorage[cachedOffset]), result);
-    else {
-        PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
-        loadPtr(static_cast<void*>(protoPropertyStorage), temp);
-        loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result);
-    } 
+    loadPtr(static_cast<void*>(&base->m_propertyStorage[cachedOffset]), result);
 }
 
 void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
@@ -668,11 +647,6 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
 
     int offset = sizeof(JSValue) * cachedOffset;
 
-    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
-    // and makes the subsequent load's offset automatically correct
-    if (structure->isUsingInlineStorage())
-        repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad));
-
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset), offset);
@@ -708,11 +682,6 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo,
 
     int offset = sizeof(JSValue) * cachedOffset;
 
-    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
-    // and makes the subsequent load's offset automatically correct
-    if (structure->isUsingInlineStorage())
-        repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetPutByIdExternalLoad));
-
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure);
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset), offset);
@@ -779,7 +748,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     // Checks out okay!
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -794,7 +763,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
         stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
     LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
 
@@ -831,11 +800,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        if (!structure->isUsingInlineStorage()) {
-            move(regT0, regT1);
-            compileGetDirectOffset(regT1, regT1, structure, cachedOffset);
-        } else
-            compileGetDirectOffset(regT0, regT1, structure, cachedOffset);
+        compileGetDirectOffset(regT0, regT1, structure, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -905,7 +870,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -920,7 +885,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
         stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
 
     Jump success = jump();
 
@@ -975,7 +940,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -990,7 +955,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
         stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
 
     LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
@@ -1045,7 +1010,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -1060,7 +1025,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
         stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
 
     LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
index 710a155..82e74bc 100644 (file)
@@ -434,11 +434,7 @@ void JIT::compileGetByIdHotPath()
     ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure);
     ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase);
     
-    Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT2);
-    Label externalLoadComplete(this);
-    ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetGetByIdExternalLoad);
-    ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthGetByIdExternalLoad);
-    
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT2);
     DataLabel32 displacementLabel1 = loadPtrWithAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT0); // payload
     ASSERT(differenceBetween(hotPathBegin, displacementLabel1) == patchOffsetGetByIdPropertyMapOffset1);
     DataLabel32 displacementLabel2 = loadPtrWithAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT1); // tag
@@ -512,12 +508,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
     ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetPutByIdStructure);
     
-    // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
-    Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
-    Label externalLoadComplete(this);
-    ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetPutByIdExternalLoad);
-    ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthPutByIdExternalLoad);
-    
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
     DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT0, patchGetByIdDefaultOffset)); // payload
     DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT0, patchGetByIdDefaultOffset)); // tag
     
@@ -552,9 +543,9 @@ void JIT::compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterI
 {
     int offset = cachedOffset;
     if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage) /  sizeof(Register);
+        offset += JSObject::offsetOfInlineStorage() /  sizeof(Register);
     else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
     emitStore(offset, valueTag, valuePayload, base);
 }
 
@@ -562,27 +553,20 @@ void JIT::compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterI
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset)
 {
     int offset = cachedOffset;
-    if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage) / sizeof(Register);
-    else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
-    emitLoad(offset, resultTag, resultPayload, base);
+    if (structure->isUsingInlineStorage()) {
+        offset += JSObject::offsetOfInlineStorage() / sizeof(Register);
+        emitLoad(offset, resultTag, resultPayload, base);
+    } else {
+        RegisterID temp = resultPayload;
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), temp);
+        emitLoad(offset, resultTag, resultPayload, temp);
+    }
 }
 
-void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
+void JIT::compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
 {
-    if (base->isUsingInlineStorage()) {
-        load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
-        load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag), resultTag);
-        return;
-    }
-    
-    size_t offset = cachedOffset * sizeof(JSValue);
-    
-    PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
-    loadPtr(static_cast<void*>(protoPropertyStorage), temp);
-    load32(Address(temp, offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
-    load32(Address(temp, offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
+    load32(reinterpret_cast<char*>(&base->m_propertyStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
+    load32(reinterpret_cast<char*>(&base->m_propertyStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag), resultTag);
 }
 
 void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
@@ -683,12 +667,7 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
     
     int offset = sizeof(JSValue) * cachedOffset;
-    
-    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
-    // and makes the subsequent load's offset automatically correct
-    if (structure->isUsingInlineStorage())
-        repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad));
-    
+
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
@@ -724,12 +703,7 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo,
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
     
     int offset = sizeof(JSValue) * cachedOffset;
-    
-    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
-    // and makes the subsequent load's offset automatically correct
-    if (structure->isUsingInlineStorage())
-        repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetPutByIdExternalLoad));
-    
+
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure);
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
@@ -799,7 +773,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     // Checks out okay!
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -814,7 +788,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
         stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
     Jump success = jump();
     
@@ -856,11 +830,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        if (!structure->isUsingInlineStorage()) {
-            move(regT0, regT1);
-            compileGetDirectOffset(regT1, regT2, regT1, structure, cachedOffset);
-        } else
-            compileGetDirectOffset(regT0, regT2, regT1, structure, cachedOffset);
+        compileGetDirectOffset(regT0, regT2, regT1, structure, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -930,7 +900,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -945,7 +915,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
         stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
     Jump success = jump();
     
@@ -999,7 +969,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -1014,7 +984,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
         stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
 
     Jump success = jump();
     
@@ -1069,7 +1039,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
@@ -1084,7 +1054,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
         stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     Jump success = jump();
     
     LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
@@ -1117,21 +1087,13 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 
 #endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
-void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset)
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset)
 {
-    ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
-    ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
     ASSERT(sizeof(JSValue) == 8);
     
-    Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
-    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
-    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
-    Jump finishedLoad = jump();
-    notUsingInlineStorage.link(this);
-    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
     loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
     loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
-    finishedLoad.link(this);
 }
 
 void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
@@ -1156,7 +1118,7 @@ void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
     load32(addressFor(i), regT3);
     sub32(Imm32(1), regT3);
     addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
-    compileGetDirectOffset(regT2, regT1, regT0, regT0, regT3);    
+    compileGetDirectOffset(regT2, regT1, regT0, regT3);    
     
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_pname), dst, regT1, regT0);
index 74f505f..40c69f3 100644 (file)
@@ -1176,7 +1176,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this)
         structure = asObject(proto)->inheritorID();
     else
         structure = constructor->scope().node()->globalObject->emptyObjectStructure();
-    JSValue result = new (&callFrame->globalData()) JSObject(structure);
+    JSValue result = constructEmptyObject(callFrame, structure);
 
     return JSValue::encode(result);
 }
index 658538b..324e891 100644 (file)
@@ -58,7 +58,7 @@ namespace JSC {
     };
 
 
-    class Arguments : public JSObject {
+    class Arguments : public JSNonFinalObject {
     public:
         // Use an enum because otherwise gcc insists on doing a memory
         // read.
@@ -145,7 +145,7 @@ namespace JSC {
     }
 
     inline Arguments::Arguments(CallFrame* callFrame)
-        : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
+        : JSNonFinalObject(callFrame->lexicalGlobalObject()->argumentsStructure())
         , d(adoptPtr(new ArgumentsData))
     {
         JSFunction* callee;
@@ -185,7 +185,7 @@ namespace JSC {
     }
 
     inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
-        : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
+        : JSNonFinalObject(callFrame->lexicalGlobalObject()->argumentsStructure())
         , d(adoptPtr(new ArgumentsData))
     {
         ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
index a6208d5..39b43db 100644 (file)
@@ -26,14 +26,14 @@ namespace JSC {
 const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 };
 
 ErrorInstance::ErrorInstance(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure)
-    : JSObject(structure)
+    : JSNonFinalObject(structure)
     , m_appendSourceToMessage(false)
 {
     putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, ""));
 }
 
 ErrorInstance::ErrorInstance(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const UString& message)
-    : JSObject(structure)
+    : JSNonFinalObject(structure)
     , m_appendSourceToMessage(false)
 {
     putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
index b3bebec..bb02714 100644 (file)
@@ -25,7 +25,7 @@
 
 namespace JSC {
 
-    class ErrorInstance : public JSObject {
+    class ErrorInstance : public JSNonFinalObject {
     public:
 
         virtual const ClassInfo* classInfo() const { return &info; }
index 4a58800..d3c637e 100644 (file)
 
 namespace JSC {
 
-class InterruptedExecutionError : public JSObject {
+class InterruptedExecutionError : public JSNonFinalObject {
 public:
     InterruptedExecutionError(JSGlobalData* globalData)
-        : JSObject(globalData->interruptedExecutionErrorStructure)
+        : JSNonFinalObject(globalData->interruptedExecutionErrorStructure)
     {
     }
 
@@ -58,10 +58,10 @@ JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
     return new (globalData) InterruptedExecutionError(globalData);
 }
 
-class TerminatedExecutionError : public JSObject {
+class TerminatedExecutionError : public JSNonFinalObject {
 public:
     TerminatedExecutionError(JSGlobalData* globalData)
-        : JSObject(globalData->terminatedExecutionErrorStructure)
+        : JSNonFinalObject(globalData->terminatedExecutionErrorStructure)
     {
     }
 
index ded6d87..b0b26a5 100644 (file)
@@ -127,7 +127,7 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
 #endif
 
 JSArray::JSArray(VPtrStealingHackType)
-    : JSObject(createStructure(jsNull()))
+    : JSNonFinalObject(createStructure(jsNull()))
 {
     unsigned initialCapacity = 0;
 
@@ -144,7 +144,7 @@ JSArray::JSArray(VPtrStealingHackType)
 }
 
 JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
-    : JSObject(structure)
+    : JSNonFinalObject(structure)
 {
     unsigned initialCapacity = 0;
 
@@ -159,7 +159,7 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
 }
 
 JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength, ArrayCreationMode creationMode)
-    : JSObject(structure)
+    : JSNonFinalObject(structure)
 {
     unsigned initialCapacity;
     if (creationMode == CreateCompact)
@@ -199,7 +199,7 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength,
 }
 
 JSArray::JSArray(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, const ArgList& list)
-    : JSObject(structure)
+    : JSNonFinalObject(structure)
 {
     unsigned initialCapacity = list.size();
     unsigned initialStorage;
index b5caa47..19693cf 100644 (file)
@@ -57,7 +57,7 @@ namespace JSC {
 
     enum ArrayCreationMode { CreateCompact, CreateInitialized };
 
-    class JSArray : public JSObject {
+    class JSArray : public JSNonFinalObject {
         friend class JIT;
         friend class Walker;
 
index 3f7d806..8a7c14a 100644 (file)
@@ -36,7 +36,7 @@ namespace JSC {
 const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 };
 
 JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo)
-    : JSObject(structure)
+    : JSNonFinalObject(structure)
     , m_storage(storage)
     , m_classInfo(classInfo)
 {
index 44bae2d..b9b8d4d 100644 (file)
@@ -32,7 +32,7 @@
 
 namespace JSC {
 
-    class JSByteArray : public JSObject {
+    class JSByteArray : public JSNonFinalObject {
         friend class JSGlobalData;
     public:
         bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
@@ -94,7 +94,7 @@ namespace JSC {
     private:
         enum VPtrStealingHackType { VPtrStealingHack };
         JSByteArray(VPtrStealingHackType)
-            : JSObject(createStructure(jsNull()))
+            : JSNonFinalObject(createStructure(jsNull()))
             , m_classInfo(0)
         {
         }
index c569722..b8afca9 100644 (file)
@@ -206,7 +206,7 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
         WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName);
 
         if (!location) {
-            JSObject* prototype = new (exec) JSObject(scope().globalObject()->emptyObjectStructure());
+            JSObject* prototype = constructEmptyObject(exec, scope().globalObject()->emptyObjectStructure());
             prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, this, DontEnum);
             putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
             location = getDirectLocation(propertyName);
index cff7252..93249a2 100644 (file)
@@ -123,8 +123,8 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
     , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
     , stringTable(fastNew<HashTable>(JSC::stringTable))
     , activationStructure(JSActivation::createStructure(jsNull()))
-    , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull()))
-    , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull()))
+    , interruptedExecutionErrorStructure(createEmptyObjectStructure(jsNull()))
+    , terminatedExecutionErrorStructure(createEmptyObjectStructure(jsNull()))
     , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
     , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull()))
     , stringStructure(JSString::createStructure(jsNull()))
index d13d2da..821716a 100644 (file)
@@ -401,16 +401,16 @@ namespace JSC {
         return globalData().dynamicGlobalObject;
     }
 
-    inline JSObject* constructEmptyObject(ExecState* exec)
-    {
-        return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
-    }
-    
     inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject)
     {
-        return new (exec) JSObject(globalObject->emptyObjectStructure());
+        return constructEmptyObject(exec, globalObject->emptyObjectStructure());
     }
 
+    inline JSObject* constructEmptyObject(ExecState* exec)
+    {
+        return constructEmptyObject(exec, exec->lexicalGlobalObject());
+    }
+    
     inline JSArray* constructEmptyArray(ExecState* exec)
     {
         return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
index 9f527cf..1273ff5 100644 (file)
@@ -36,10 +36,10 @@ namespace JSC {
     // This unholy class is used to allow us to avoid multiple exception checks
     // in certain SquirrelFish bytecodes -- effectively it just silently consumes
     // any operations performed on the result of a failed toObject call.
-    class JSNotAnObject : public JSObject {
+    class JSNotAnObject : public JSNonFinalObject {
     public:
         JSNotAnObject(ExecState* exec)
-            : JSObject(exec->globalData().notAnObjectStructure)
+            : JSNonFinalObject(exec->globalData().notAnObjectStructure)
         {
         }
 
index 277ffff..192ed8d 100644 (file)
@@ -42,6 +42,8 @@
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSObject);
+ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
+ASSERT_CLASS_FILLS_CELL(JSFinalObject);
 
 const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
 
@@ -555,13 +557,28 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr
 
 Structure* JSObject::createInheritorID()
 {
-    m_inheritorID = JSObject::createStructure(this);
+    m_inheritorID = createEmptyObjectStructure(this);
     return m_inheritorID.get();
 }
 
 void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
 {
-    allocatePropertyStorageInline(oldSize, 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::baseExternalStorageCapacity);
+
+    PropertyStorage oldPropertyStorage = m_propertyStorage;
+    PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize];
+
+    for (unsigned i = 0; i < oldSize; ++i)
+       newPropertyStorage[i] = oldPropertyStorage[i];
+
+    if (!wasInline)
+        delete [] oldPropertyStorage;
+
+    m_propertyStorage = newPropertyStorage;
 }
 
 bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor)
index b79249c..b0f5499 100644 (file)
@@ -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);
 
@@ -215,16 +213,9 @@ namespace JSC {
         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 +237,21 @@ namespace JSC {
             ASSERT(index < m_structure->anonymousSlotCount());
             return locationForOffset(index)->get();
         }
+
+        static size_t offsetOfInlineStorage();
         
     protected:
         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 +262,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 +284,87 @@ 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:
+        explicit JSNonFinalObject(NonNullPassRefPtr<Structure> structure)
+            : JSObject(structure, m_inlineStorage)
+        {
+            ASSERT(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double) == 0);
+        }
+
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+        }
+
+    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);
+        }
+
+    private:
+        explicit JSFinalObject(NonNullPassRefPtr<Structure> structure)
+            : JSObject(structure, m_inlineStorage)
+        {
+            ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double) == 0);
+        }
+
+        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 +376,20 @@ 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(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 +433,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
@@ -727,26 +797,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);
index c16acb1..9370139 100644 (file)
@@ -31,7 +31,7 @@
 namespace JSC {
 
 JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure)
-    : JSObject(structure)
+    : JSNonFinalObject(structure)
 {
     COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one);
     ASSERT(!globalObject || globalObject->isGlobalObject());
index 9416a62..e2843ff 100644 (file)
@@ -32,7 +32,7 @@ namespace JSC {
 
 class JSGlobalObject;
 
-class JSObjectWithGlobalObject : public JSObject {
+class JSObjectWithGlobalObject : public JSNonFinalObject {
 public:
     static PassRefPtr<Structure> createStructure(JSValue proto)
     {
@@ -45,7 +45,7 @@ protected:
     JSObjectWithGlobalObject(JSGlobalObject*, NonNullPassRefPtr<Structure>);
 
     JSObjectWithGlobalObject(NonNullPassRefPtr<Structure> structure)
-        : JSObject(structure)
+        : JSNonFinalObject(structure)
     {
         // Should only be used by JSFunction when we aquire the JSFunction vptr.
     }
index e225bc7..fdcaf31 100644 (file)
@@ -43,20 +43,21 @@ namespace JSC {
     static const unsigned OverridesGetOwnPropertySlot = 1 << 5;
     static const unsigned OverridesMarkChildren = 1 << 6;
     static const unsigned OverridesGetPropertyNames = 1 << 7;
+    static const unsigned IsJSFinalObject = 1 << 8;
 
     class TypeInfo {
         friend class JIT;
     public:
         TypeInfo(JSType type, unsigned flags = 0)
             : m_type(type)
+            , m_flags(flags & 0xFF)
+            , m_flags2(flags >> 8)
         {
-            ASSERT(flags <= 0xFF);
+            ASSERT(flags <= 0x1FF);
             ASSERT(type <= 0xFF);
             // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
-            if ((flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
-                m_flags = flags | ImplementsDefaultHasInstance;
-            else
-                m_flags = flags;
+            if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
+                m_flags |= ImplementsDefaultHasInstance;
         }
 
         JSType type() const { return (JSType)m_type; }
@@ -69,10 +70,12 @@ namespace JSC {
         bool overridesMarkChildren() const { return m_flags & OverridesMarkChildren; }
         bool overridesGetPropertyNames() const { return m_flags & OverridesGetPropertyNames; }
         unsigned flags() const { return m_flags; }
+        unsigned isFinal() const { return m_flags2 && (IsJSFinalObject >> 8); }
 
     private:
         unsigned char m_type;
         unsigned char m_flags;
+        unsigned char m_flags2;
     };
 
 }
index 96a0ec4..2250760 100644 (file)
@@ -40,7 +40,7 @@ namespace JSC {
 
     class Register;
 
-    class JSVariableObject : public JSObject {
+    class JSVariableObject : public JSNonFinalObject {
         friend class JIT;
 
     public:
@@ -84,7 +84,7 @@ namespace JSC {
         };
 
         JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data)
-            : JSObject(structure)
+            : JSNonFinalObject(structure)
             , d(data) // Subclass owns this pointer.
         {
         }
index 0b0d3fd..cd781f1 100644 (file)
@@ -28,7 +28,7 @@ namespace JSC {
 
     // This class is used as a base for classes such as String,
     // Number, Boolean and Date which are wrappers for primitive types.
-    class JSWrapperObject : public JSObject {
+    class JSWrapperObject : public JSNonFinalObject {
     protected:
         explicit JSWrapperObject(JSGlobalData&, NonNullPassRefPtr<Structure>);
 
@@ -51,7 +51,7 @@ namespace JSC {
     };
 
     inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure)
-        : JSObject(structure)
+        : JSNonFinalObject(structure)
     {
         putAnonymousValue(globalData, 0, jsNull());
     }
index 3669c78..5cedb7a 100644 (file)
@@ -27,6 +27,7 @@
 #include <wtf/PageAllocationAligned.h>
 
 #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedBlock::CELL_SIZE, class_fits_in_cell)
+#define ASSERT_CLASS_FILLS_CELL(class) COMPILE_ASSERT(sizeof(class) == MarkedBlock::CELL_SIZE, class_fills_cell)
 
 namespace JSC {
 
index f31da67..300dac9 100644 (file)
@@ -66,7 +66,7 @@ static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& a
 {
     JSValue arg = args.at(0);
     if (arg.isUndefinedOrNull())
-        return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+        return constructEmptyObject(exec);
     return arg.toObject(exec);
 }
 
index 57a8a31..4e4416e 100644 (file)
@@ -42,7 +42,7 @@ static EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecStat
 static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*);
 
 ObjectPrototype::ObjectPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
-    : JSObject(stucture)
+    : JSNonFinalObject(stucture)
     , m_hasNoPropertiesWithUInt32Names(true)
 {
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
index 0382ae4..2112554 100644 (file)
@@ -25,7 +25,7 @@
 
 namespace JSC {
 
-    class ObjectPrototype : public JSObject {
+    class ObjectPrototype : public JSNonFinalObject {
     public:
         ObjectPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
 
index 5bb013b..24c501e 100644 (file)
@@ -29,7 +29,7 @@
 namespace JSC {
 
 StrictEvalActivation::StrictEvalActivation(ExecState* exec)
-    : JSObject(exec->globalData().strictEvalActivationStructure)
+    : JSNonFinalObject(exec->globalData().strictEvalActivationStructure)
 {
 }
 
index 1385eec..e2885cc 100644 (file)
@@ -30,7 +30,7 @@
 
 namespace JSC {
 
-class StrictEvalActivation : public JSObject {
+class StrictEvalActivation : public JSNonFinalObject {
 public:
     StrictEvalActivation(ExecState*);
     virtual bool deleteProperty(ExecState*, const Identifier&);
index 967e4d7..a2d615c 100644 (file)
@@ -228,7 +228,7 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anony
     , m_prototype(prototype)
     , m_specificValueInPrevious(0)
     , m_propertyTable(0)
-    , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
+    , m_propertyStorageCapacity(typeInfo.isFinal() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity)
     , m_offset(noOffset)
     , m_dictionaryKind(NoneDictionaryKind)
     , m_isPinnedPropertyTable(false)
@@ -387,8 +387,8 @@ void Structure::materializePropertyMap()
 
 void Structure::growPropertyStorageCapacity()
 {
-    if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
-        m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity;
+    if (isUsingInlineStorage())
+        m_propertyStorageCapacity = JSObject::baseExternalStorageCapacity;
     else
         m_propertyStorageCapacity *= 2;
 }
index cf52edd..e72b9b9 100644 (file)
@@ -1,3 +1,25 @@
+2011-02-15  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Geoff Garen.
+
+        Bug 54524 - Allow JSObject to fully utilize cell's capacity for inline storage.
+
+        Currently JSObject is both directly instantiated for regular JS objects, and
+        derived to implement subtypes. A consequence of this is that we need to ensure
+        that sufficient space from the cell is left unused and available for any data
+        members that will be introduced by subclasses of JSObject. By restructuring
+        the internal storage array out of JSObject we can increase the size in the
+        internal storage for regular objects.
+
+        Add classes JSFinalObject and JSNonFinalObject. JSNonFinalObject retains as
+        much additional capacity as is currently available to allow for data members
+        in subclasses. JSFinalObject utilizes all available space for internal storage,
+        and only allows construction through JSFinalObject::create().
+
+        * UserObjectImp.cpp:
+        * UserObjectImp.h:
+            Update JSObject -> JSNonFinalObject.
+
 2011-02-14  Oliver Hunt  <oliver@apple.com>
 
         Reviewed by Gavin Barraclough and Geoff Garen.
index 340864b..e8bb0f6 100644 (file)
@@ -35,7 +35,7 @@
 const ClassInfo UserObjectImp::info = { "UserObject", 0, 0, 0 };
 
 UserObjectImp::UserObjectImp(PassRefPtr<Structure> structure, JSUserObject* userObject)
-    : JSObject(structure)
+    : JSNonFinalObject(structure)
     , fJSUserObject((JSUserObject*)userObject->Retain())
 {
 }
index dbd4faa..3a8cba9 100644 (file)
@@ -34,7 +34,7 @@
 #include "JSObject.h"
 #include <JavaScriptCore/JSType.h>
 
-class UserObjectImp : public JSObject {
+class UserObjectImp : public JSNonFinalObject {
 public:
     UserObjectImp(PassRefPtr<Structure>, JSUserObject*);
     virtual ~UserObjectImp();
index 76eb04e..f9c333c 100644 (file)
@@ -1,3 +1,24 @@
+2011-02-15  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Geoff Garen.
+
+        Bug 54524 - Allow JSObject to fully utilize cell's capacity for inline storage.
+
+        Currently JSObject is both directly instantiated for regular JS objects, and
+        derived to implement subtypes. A consequence of this is that we need to ensure
+        that sufficient space from the cell is left unused and available for any data
+        members that will be introduced by subclasses of JSObject. By restructuring
+        the internal storage array out of JSObject we can increase the size in the
+        internal storage for regular objects.
+
+        Add classes JSFinalObject and JSNonFinalObject. JSNonFinalObject retains as
+        much additional capacity as is currently available to allow for data members
+        in subclasses. JSFinalObject utilizes all available space for internal storage,
+        and only allows construction through JSFinalObject::create().
+
+        * bindings/js/JSDOMWindowShell.h:
+            Update JSObject -> JSNonFinalObject.
+
 2011-02-16  Carol Szabo  <carol.szabo@nokia.com>
 
         Reviewed by David Hyatt.
index d585fd4..3fa86b1 100644 (file)
@@ -37,8 +37,8 @@ namespace WebCore {
     class DOMWindow;
     class Frame;
 
-    class JSDOMWindowShell : public JSC::JSObject {
-        typedef JSC::JSObject Base;
+    class JSDOMWindowShell : public JSC::JSNonFinalObject {
+        typedef JSC::JSNonFinalObject Base;
     public:
         JSDOMWindowShell(PassRefPtr<DOMWindow>, DOMWrapperWorld* world);
         virtual ~JSDOMWindowShell();
index b8fb7c7..3e80648 100644 (file)
@@ -1832,7 +1832,7 @@ void QtConnectionObject::execute(void **argv)
                         fimp = static_cast<JSFunction*>(m_funcObject.get());
 
                         JSObject* qt_sender = QtInstance::getQtInstance(sender(), ro, QScriptEngine::QtOwnership)->createRuntimeObject(exec);
-                        JSObject* wrapper = new (exec) JSObject(JSObject::createStructure(jsNull()));
+                        JSObject* wrapper = constructEmptyObject(exec, createEmptyObjectStructure(jsNull()));
                         PutPropertySlot slot;
                         wrapper->put(exec, Identifier(exec, "__qt_sender__"), qt_sender, slot);
                         oldsc = fimp->scope();
index 73df155..34841ed 100644 (file)
@@ -74,7 +74,7 @@ public slots:
 using namespace JSC;
 using namespace JSC::Bindings;
 
-class Global : public JSObject {
+class Global : public JSNonFinalObject {
 public:
   virtual UString className() const { return "global"; }
 };