Inline property storage should not be wasted when it is exhausted
https://bugs.webkit.org/show_bug.cgi?id=90347

Reviewed by Gavin Barraclough.
        
Previously, if we switched an object from using inline storage to out-of-line
storage, we would abandon the inline storage. This would have two main implications:
(i) all accesses to the object, even for properties that were previously in inline
storage, must now take an extra indirection; and (ii) we waste a non-trivial amount
of space since we must allocate additional out-of-line storage to hold properties
that would have fit in the inline storage. There's also the copying cost when
switching to out-of-line storage - we must copy all inline properties into ouf-of-line
storage.
        
This patch changes the way that object property storage works so that we can use both
inline and out-of-line storage concurrently. This is accomplished by introducing a
new notion of property offset. This PropertyOffset is a 32-bit signed integer and it
behaves as follows:
        
offset == -1: invalid offset, indicating a property that does not exist.
        
0 <= offset <= inlineStorageCapacity: offset into inline storage.
        
inlineStorageCapacity < offset: offset into out-of-line storage.
        
Because non-final objects don't have inline storage, the only valid PropertyOffsets
for those objects' properties are -1 or > inlineStorageCapacity.
        
This now means that the decision to use inline or out-of-line storage for an access is
made based on the offset, rather than the structure. It also means that any access
where the offset is a variable must have an extra branch, unless the type of the
object is also known (if it's known to be a non-final object then we can just assert
that the offset is >= inlineStorageCapacity).
        
This looks like a big Kraken speed-up and a slight V8 speed-up.

* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/ARMv7Assembler.h:
(ARMv7Assembler):
(JSC::ARMv7Assembler::ldrWide8BitImmediate):
(JSC::ARMv7Assembler::replaceWithLoad):
(JSC::ARMv7Assembler::replaceWithAddressComputation):
* assembler/AbstractMacroAssembler.h:
(AbstractMacroAssembler):
(ConvertibleLoadLabel):
(JSC::AbstractMacroAssembler::ConvertibleLoadLabel::ConvertibleLoadLabel):
(JSC::AbstractMacroAssembler::ConvertibleLoadLabel::isSet):
(JSC::AbstractMacroAssembler::labelIgnoringWatchpoints):
(JSC::AbstractMacroAssembler::replaceWithLoad):
(JSC::AbstractMacroAssembler::replaceWithAddressComputation):
* assembler/CodeLocation.h:
(JSC):
(CodeLocationCommon):
(CodeLocationConvertibleLoad):
(JSC::CodeLocationConvertibleLoad::CodeLocationConvertibleLoad):
(JSC::CodeLocationCommon::convertibleLoadAtOffset):
* assembler/LinkBuffer.cpp:
(JSC::LinkBuffer::finalizeCodeWithDisassembly):
* assembler/LinkBuffer.h:
(LinkBuffer):
(JSC::LinkBuffer::locationOf):
* assembler/MacroAssemblerARMv7.h:
(MacroAssemblerARMv7):
(JSC::MacroAssemblerARMv7::convertibleLoadPtr):
* assembler/MacroAssemblerX86.h:
(JSC::MacroAssemblerX86::convertibleLoadPtr):
(MacroAssemblerX86):
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::convertibleLoadPtr):
(MacroAssemblerX86_64):
* assembler/RepatchBuffer.h:
(RepatchBuffer):
(JSC::RepatchBuffer::replaceWithLoad):
(JSC::RepatchBuffer::replaceWithAddressComputation):
(JSC::RepatchBuffer::setLoadInstructionIsActive):
* assembler/X86Assembler.h:
(JSC::X86Assembler::replaceWithLoad):
(X86Assembler):
(JSC::X86Assembler::replaceWithAddressComputation):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::dump):
(JSC::CodeBlock::finalizeUnconditionally):
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
(JSC::GetByIdStatus::computeForChain):
(JSC::GetByIdStatus::computeFor):
* bytecode/GetByIdStatus.h:
(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::offset):
(GetByIdStatus):
* bytecode/Opcode.h:
(JSC):
(JSC::padOpcodeName):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
(JSC::PutByIdStatus::computeFor):
* bytecode/PutByIdStatus.h:
(JSC::PutByIdStatus::PutByIdStatus):
(JSC::PutByIdStatus::offset):
(PutByIdStatus):
* bytecode/ResolveGlobalStatus.cpp:
(JSC):
(JSC::computeForStructure):
* bytecode/ResolveGlobalStatus.h:
(JSC::ResolveGlobalStatus::ResolveGlobalStatus):
(JSC::ResolveGlobalStatus::offset):
(ResolveGlobalStatus):
* bytecode/StructureSet.h:
(StructureSet):
* bytecode/StructureStubInfo.h:
* dfg/DFGByteCodeParser.cpp:
(ByteCodeParser):
(JSC::DFG::ByteCodeParser::handleGetByOffset):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGJITCompiler.h:
(JSC::DFG::PropertyAccessRecord::PropertyAccessRecord):
(PropertyAccessRecord):
* dfg/DFGRepatch.cpp:
(JSC::DFG::dfgRepatchByIdSelfAccess):
(JSC::DFG::generateProtoChainAccessStub):
(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDList):
(JSC::DFG::tryBuildGetByIDProtoList):
(JSC::DFG::emitPutReplaceStub):
(JSC::DFG::emitPutTransitionStub):
(JSC::DFG::tryCachePutByID):
(JSC::DFG::tryBuildPutByIdList):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::compile):
* heap/MarkStack.cpp:
(JSC::visitChildren):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::tryCacheGetByID):
(JSC::Interpreter::privateExecute):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
(JSC::PropertyStubCompilationInfo::copyToStubInfo):
* jit/JIT.h:
(JSC::PropertyStubCompilationInfo::PropertyStubCompilationInfo):
(JSC::JIT::compileGetByIdProto):
(JSC::JIT::compileGetByIdSelfList):
(JSC::JIT::compileGetByIdProtoList):
(JSC::JIT::compileGetByIdChainList):
(JSC::JIT::compileGetByIdChain):
(JSC::JIT::compilePutByIdTransition):
(JIT):
* jit/JITInlineMethods.h:
(JSC::JIT::emitAllocateBasicJSObject):
* 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_method_check):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::compilePutDirectOffset):
(JSC::JIT::privateCompilePutByIdTransition):
(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::emit_op_method_check):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::compilePutDirectOffset):
(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::privateCompilePutByIdTransition):
(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::JITThunks::tryCacheGetByID):
(JSC::DEFINE_STUB_FUNCTION):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* offlineasm/x86.rb:
* runtime/JSGlobalObject.h:
(JSGlobalObject):
(JSC::JSGlobalObject::functionNameOffset):
* runtime/JSObject.cpp:
(JSC::JSObject::visitChildren):
(JSC):
(JSC::JSFinalObject::visitChildren):
(JSC::JSObject::put):
(JSC::JSObject::deleteProperty):
(JSC::JSObject::getPropertySpecificValue):
(JSC::JSObject::removeDirect):
(JSC::JSObject::growOutOfLineStorage):
(JSC::JSObject::getOwnPropertyDescriptor):
* runtime/JSObject.h:
(JSObject):
(JSC::JSObject::getDirect):
(JSC::JSObject::getDirectLocation):
(JSC::JSObject::hasInlineStorage):
(JSC::JSObject::inlineStorageUnsafe):
(JSC::JSObject::inlineStorage):
(JSC::JSObject::outOfLineStorage):
(JSC::JSObject::locationForOffset):
(JSC::JSObject::offsetForLocation):
(JSC::JSObject::getDirectOffset):
(JSC::JSObject::putDirectOffset):
(JSC::JSObject::putUndefinedAtDirectOffset):
(JSC::JSObject::addressOfOutOfLineStorage):
(JSC::JSObject::finishCreation):
(JSC::JSNonFinalObject::JSNonFinalObject):
(JSC::JSNonFinalObject::finishCreation):
(JSFinalObject):
(JSC::JSFinalObject::finishCreation):
(JSC::JSFinalObject::JSFinalObject):
(JSC::JSObject::offsetOfOutOfLineStorage):
(JSC::JSObject::setOutOfLineStorage):
(JSC::JSObject::JSObject):
(JSC):
(JSC::JSCell::fastGetOwnProperty):
(JSC::JSObject::putDirectInternal):
(JSC::JSObject::setStructureAndReallocateStorageIfNecessary):
(JSC::JSObject::putDirectWithoutTransition):
(JSC::offsetRelativeToPatchedStorage):
(JSC::indexRelativeToBase):
(JSC::offsetRelativeToBase):
* runtime/JSPropertyNameIterator.cpp:
(JSC::JSPropertyNameIterator::create):
* runtime/JSPropertyNameIterator.h:
(JSPropertyNameIterator):
(JSC::JSPropertyNameIterator::getOffset):
(JSC::JSPropertyNameIterator::finishCreation):
* runtime/JSValue.cpp:
(JSC::JSValue::putToPrimitive):
* runtime/Operations.h:
(JSC::normalizePrototypeChain):
* runtime/Options.cpp:
(JSC):
(JSC::Options::initialize):
* runtime/PropertyMapHashTable.h:
(PropertyMapEntry):
(JSC::PropertyMapEntry::PropertyMapEntry):
(PropertyTable):
(JSC::PropertyTable::PropertyTable):
(JSC::PropertyTable::getDeletedOffset):
(JSC::PropertyTable::addDeletedOffset):
(JSC::PropertyTable::nextOffset):
(JSC):
(JSC::PropertyTable::sizeInMemory):
* runtime/PropertyOffset.h: Added.
(JSC):
(JSC::checkOffset):
(JSC::validateOffset):
(JSC::isValidOffset):
(JSC::isInlineOffset):
(JSC::isOutOfLineOffset):
(JSC::offsetInInlineStorage):
(JSC::offsetInOutOfLineStorage):
(JSC::offsetInRespectiveStorage):
(JSC::numberOfOutOfLineSlotsForLastOffset):
(JSC::numberOfSlotsForLastOffset):
(JSC::nextPropertyOffsetFor):
(JSC::firstPropertyOffsetFor):
* runtime/PropertySlot.h:
(JSC::PropertySlot::cachedOffset):
(JSC::PropertySlot::setValue):
(JSC::PropertySlot::setCacheableGetterSlot):
(JSC::PropertySlot::clearOffset):
* runtime/PutPropertySlot.h:
(JSC::PutPropertySlot::setExistingProperty):
(JSC::PutPropertySlot::setNewProperty):
(JSC::PutPropertySlot::cachedOffset):
(PutPropertySlot):
* runtime/Structure.cpp:
(JSC::Structure::Structure):
(JSC::Structure::materializePropertyMap):
(JSC::nextOutOfLineStorageCapacity):
(JSC::Structure::growOutOfLineCapacity):
(JSC::Structure::suggestedNewOutOfLineStorageCapacity):
(JSC::Structure::addPropertyTransitionToExistingStructure):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::removePropertyTransition):
(JSC::Structure::flattenDictionaryStructure):
(JSC::Structure::addPropertyWithoutTransition):
(JSC::Structure::removePropertyWithoutTransition):
(JSC::Structure::copyPropertyTableForPinning):
(JSC::Structure::get):
(JSC::Structure::putSpecificValue):
(JSC::Structure::remove):
* runtime/Structure.h:
(Structure):
(JSC::Structure::putWillGrowOutOfLineStorage):
(JSC::Structure::previousID):
(JSC::Structure::outOfLineCapacity):
(JSC::Structure::outOfLineSizeForKnownFinalObject):
(JSC::Structure::outOfLineSizeForKnownNonFinalObject):
(JSC::Structure::outOfLineSize):
(JSC::Structure::hasInlineStorage):
(JSC::Structure::inlineCapacity):
(JSC::Structure::inlineSizeForKnownFinalObject):
(JSC::Structure::inlineSize):
(JSC::Structure::totalStorageSize):
(JSC::Structure::totalStorageCapacity):
(JSC::Structure::firstValidOffset):
(JSC::Structure::lastValidOffset):
(JSC::Structure::isValidOffset):
(JSC::Structure::isEmpty):
(JSC::Structure::transitionCount):
(JSC::Structure::get):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121925 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h
index 67aa185..987c4a1 100644
--- a/Source/JavaScriptCore/jit/JIT.h
+++ b/Source/JavaScriptCore/jit/JIT.h
@@ -157,6 +157,7 @@
         MacroAssembler::Label hotPathBegin;
         MacroAssembler::DataLabelPtr getStructureToCompare;
         MacroAssembler::PatchableJump getStructureCheck;
+        MacroAssembler::ConvertibleLoadLabel propertyStorageLoad;
 #if USE(JSVALUE64)
         MacroAssembler::DataLabelCompact getDisplacementLabel;
 #else
@@ -185,17 +186,24 @@
 #endif
 
 
-        PropertyStubCompilationInfo(PropertyStubGetById_T, unsigned bytecodeIndex, MacroAssembler::Label hotPathBegin,
+        PropertyStubCompilationInfo(
+            PropertyStubGetById_T, unsigned bytecodeIndex, MacroAssembler::Label hotPathBegin,
+            MacroAssembler::DataLabelPtr structureToCompare,
+            MacroAssembler::PatchableJump structureCheck,
+            MacroAssembler::ConvertibleLoadLabel propertyStorageLoad,
 #if USE(JSVALUE64)
-            MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::PatchableJump structureCheck, MacroAssembler::DataLabelCompact displacementLabel, MacroAssembler::Label putResult)
+            MacroAssembler::DataLabelCompact displacementLabel,
 #else
-            MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::PatchableJump structureCheck, MacroAssembler::DataLabelCompact displacementLabel1, MacroAssembler::DataLabelCompact displacementLabel2, MacroAssembler::Label putResult)
+            MacroAssembler::DataLabelCompact displacementLabel1,
+            MacroAssembler::DataLabelCompact displacementLabel2,
 #endif
+            MacroAssembler::Label putResult)
             : m_type(GetById)
             , bytecodeIndex(bytecodeIndex)
             , hotPathBegin(hotPathBegin)
             , getStructureToCompare(structureToCompare)
             , getStructureCheck(structureCheck)
+            , propertyStorageLoad(propertyStorageLoad)
 #if USE(JSVALUE64)
             , getDisplacementLabel(displacementLabel)
 #else
@@ -206,15 +214,21 @@
         {
         }
 
-        PropertyStubCompilationInfo(PropertyStubPutById_T, unsigned bytecodeIndex, MacroAssembler::Label hotPathBegin,
+        PropertyStubCompilationInfo(
+            PropertyStubPutById_T, unsigned bytecodeIndex, MacroAssembler::Label hotPathBegin,
+            MacroAssembler::DataLabelPtr structureToCompare,
+            MacroAssembler::ConvertibleLoadLabel propertyStorageLoad,
 #if USE(JSVALUE64)
-            MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::DataLabel32 displacementLabel)
+            MacroAssembler::DataLabel32 displacementLabel
 #else
-            MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::DataLabel32 displacementLabel1, MacroAssembler::DataLabel32 displacementLabel2)
+            MacroAssembler::DataLabel32 displacementLabel1,
+            MacroAssembler::DataLabel32 displacementLabel2
 #endif
+            )
             : m_type(PutById)
             , bytecodeIndex(bytecodeIndex)
             , hotPathBegin(hotPathBegin)
+            , propertyStorageLoad(propertyStorageLoad)
             , putStructureToCompare(structureToCompare)
 #if USE(JSVALUE64)
             , putDisplacementLabel(displacementLabel)
@@ -295,40 +309,40 @@
             return JIT(globalData, codeBlock).privateCompile(functionEntryArityCheck, effort);
         }
 
-        static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress)
+        static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, ReturnAddressPtr returnAddress)
         {
             JIT jit(globalData, codeBlock);
             jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, ident, slot, cachedOffset, returnAddress, callFrame);
         }
 
-        static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
+        static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset)
         {
             JIT jit(globalData, codeBlock);
             jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, ident, slot, cachedOffset);
         }
-        static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
+        static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset)
         {
             JIT jit(globalData, codeBlock);
             jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, ident, slot, cachedOffset, callFrame);
         }
-        static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
+        static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset)
         {
             JIT jit(globalData, codeBlock);
             jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, ident, slot, cachedOffset, callFrame);
         }
 
-        static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress)
+        static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, PropertyOffset cachedOffset, ReturnAddressPtr returnAddress)
         {
             JIT jit(globalData, codeBlock);
             jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, ident, slot, cachedOffset, returnAddress, callFrame);
         }
         
-        static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
+        static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, PropertyOffset cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
         {
             JIT jit(globalData, codeBlock);
             jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
@@ -358,9 +372,9 @@
 
         static void resetPatchGetById(RepatchBuffer&, StructureStubInfo*);
         static void resetPatchPutById(RepatchBuffer&, StructureStubInfo*);
-        static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
-        static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct);
-        static void patchMethodCallProto(JSGlobalData&, CodeBlock* codeblock, MethodCallLinkInfo&, StructureStubInfo&, JSObject*, Structure*, JSObject*, ReturnAddressPtr);
+        static void patchGetByIdSelf(CodeBlock*, StructureStubInfo*, Structure*, PropertyOffset cachedOffset, ReturnAddressPtr);
+        static void patchPutByIdReplace(CodeBlock*, StructureStubInfo*, Structure*, PropertyOffset cachedOffset, ReturnAddressPtr, bool direct);
+        static void patchMethodCallProto(JSGlobalData&, CodeBlock*, MethodCallLinkInfo&, StructureStubInfo&, JSObject*, Structure*, JSObject*, ReturnAddressPtr);
 
         static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
         {
@@ -377,12 +391,12 @@
         void privateCompileLinkPass();
         void privateCompileSlowCases();
         JITCode privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffort);
-        void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
-        void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, const Identifier&, const PropertySlot&, size_t cachedOffset);
-        void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame);
-        void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame);
-        void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
-        void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress, bool direct);
+        void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, PropertyOffset cachedOffset, ReturnAddressPtr, CallFrame*);
+        void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, const Identifier&, const PropertySlot&, PropertyOffset cachedOffset);
+        void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, PropertyOffset cachedOffset, CallFrame*);
+        void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, PropertyOffset cachedOffset, CallFrame*);
+        void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, PropertyOffset cachedOffset, ReturnAddressPtr, CallFrame*);
+        void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, PropertyOffset cachedOffset, StructureChain*, ReturnAddressPtr, bool direct);
 
         PassRefPtr<ExecutableMemoryHandle> privateCompileCTIMachineTrampolines(JSGlobalData*, TrampolineStructure*);
         Label privateCompileCTINativeCall(JSGlobalData*, bool isConstruct = false);
@@ -436,6 +450,8 @@
         void emitValueProfilingSite() { }
 #endif
 
+        enum FinalObjectMode { MayBeFinal, KnownNotFinal };
+
 #if USE(JSVALUE32_64)
         bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant);
 
@@ -468,10 +484,10 @@
 
         void compileGetByIdHotPath();
         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
-        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
-        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, size_t cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, PropertyOffset cachedOffset);
+        void compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, PropertyOffset cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset, FinalObjectMode = MayBeFinal);
+        void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, PropertyOffset cachedOffset);
 
         // Arithmetic opcode helpers
         void emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
@@ -547,10 +563,10 @@
 
         void compileGetByIdHotPath(int baseVReg, Identifier*);
         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
-        void compileGetDirectOffset(RegisterID base, RegisterID result, size_t cachedOffset);
-        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, size_t cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID result, PropertyOffset cachedOffset);
+        void compileGetDirectOffset(JSObject* base, RegisterID result, PropertyOffset cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch, FinalObjectMode = MayBeFinal);
+        void compilePutDirectOffset(RegisterID base, RegisterID value, PropertyOffset cachedOffset);
 
 #endif // USE(JSVALUE32_64)