Title: [189766] trunk/Source/_javascript_Core
Revision
189766
Author
fpi...@apple.com
Date
2015-09-14 17:55:17 -0700 (Mon, 14 Sep 2015)

Log Message

LLInt get/put inline caches shouldn't use tons of opcodes
https://bugs.webkit.org/show_bug.cgi?id=149106

Reviewed by Geoffrey Garen.

Our LLInt get/put inline caches currently use separate opcodes to reduce branching. For
example, instead of having get_by_id branch on the kind of offset (inline or
out-of-line), we have two get_by_id instructions: get_by_id and get_by_id_out_of_line.
But the problem with this approach is that it doesn't scale. In the property type
inference work (https://bugs.webkit.org/show_bug.cgi?id=148610), we need each kind of put
inline cache to support 11 different kinds of type checks. It seemed ridiculous to add 60
new put_by_id opcodes (there are currently 6 variants of put_by_id, so after adding type
checks, we'd have 6 * 11 = 66 variants of put_by_id).

So, this patch completely changes the strategy to mostly using branching inside the
opcode implementation. It's unlikely to have a performance effect. For example, the long
road to generational GC caused a seemingly prohibitive regression in LLInt inline caches,
and yet nobody noticed. The regression was because the inline cache was in terms of the
structure, not the structure ID, so the code was doing a structure ID table lookup. If we
didn't notice that, then we probably won't notice a couple new branches. (Also, this
patch fixes that regression - the code no longer does such lookups except in the one
unavoidable case in put_by_id transition chain checking.)

This patch also turns the isDirect operand of put_by_id into a flags field. I will use
this flags field to encode the desired type check in bug 148610.

This patch has no effect on performance according to run-jsc-benchmarks.

Relanding this patch with LLInt fixes for non-x86. Previous attempts to fix non-x86 LLInt
build also caused every 64-bit test to crash on every platform. So the patch got rolled
out. This fixes the non-x86 LLInt build while also ensuring that 64-bit platforms don't
crash.

* CMakeLists.txt:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
* _javascript_Core.xcodeproj/project.pbxproj:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::printGetByIdCacheStatus):
(JSC::CodeBlock::printPutByIdCacheStatus):
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::propagateTransitions):
(JSC::CodeBlock::finalizeLLIntInlineCaches):
* bytecode/CodeBlock.h:
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
* bytecode/Instruction.h:
(JSC::Instruction::Instruction):
* bytecode/PutByIdFlags.cpp: Added.
(WTF::printInternal):
* bytecode/PutByIdFlags.h: Added.
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedInstruction::UnlinkedInstruction):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitPutById):
(JSC::BytecodeGenerator::emitDirectPutById):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_put_by_id):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_put_by_id):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (189765 => 189766)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2015-09-15 00:55:17 UTC (rev 189766)
@@ -107,6 +107,7 @@
     bytecode/PolymorphicAccess.cpp
     bytecode/PreciseJumpTargets.cpp
     bytecode/PropertyCondition.cpp
+    bytecode/PutByIdFlags.cpp
     bytecode/PutByIdStatus.cpp
     bytecode/PutByIdVariant.cpp
     bytecode/ReduceWhitespace.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (189765 => 189766)


--- trunk/Source/_javascript_Core/ChangeLog	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-09-15 00:55:17 UTC (rev 189766)
@@ -1,3 +1,85 @@
+2015-09-14  Filip Pizlo  <fpi...@apple.com>
+
+        LLInt get/put inline caches shouldn't use tons of opcodes
+        https://bugs.webkit.org/show_bug.cgi?id=149106
+
+        Reviewed by Geoffrey Garen.
+
+        Our LLInt get/put inline caches currently use separate opcodes to reduce branching. For
+        example, instead of having get_by_id branch on the kind of offset (inline or
+        out-of-line), we have two get_by_id instructions: get_by_id and get_by_id_out_of_line.
+        But the problem with this approach is that it doesn't scale. In the property type
+        inference work (https://bugs.webkit.org/show_bug.cgi?id=148610), we need each kind of put
+        inline cache to support 11 different kinds of type checks. It seemed ridiculous to add 60
+        new put_by_id opcodes (there are currently 6 variants of put_by_id, so after adding type
+        checks, we'd have 6 * 11 = 66 variants of put_by_id).
+
+        So, this patch completely changes the strategy to mostly using branching inside the
+        opcode implementation. It's unlikely to have a performance effect. For example, the long
+        road to generational GC caused a seemingly prohibitive regression in LLInt inline caches,
+        and yet nobody noticed. The regression was because the inline cache was in terms of the
+        structure, not the structure ID, so the code was doing a structure ID table lookup. If we
+        didn't notice that, then we probably won't notice a couple new branches. (Also, this
+        patch fixes that regression - the code no longer does such lookups except in the one
+        unavoidable case in put_by_id transition chain checking.)
+
+        This patch also turns the isDirect operand of put_by_id into a flags field. I will use
+        this flags field to encode the desired type check in bug 148610.
+
+        This patch has no effect on performance according to run-jsc-benchmarks.
+
+        Relanding this patch with LLInt fixes for non-x86. Previous attempts to fix non-x86 LLInt
+        build also caused every 64-bit test to crash on every platform. So the patch got rolled
+        out. This fixes the non-x86 LLInt build while also ensuring that 64-bit platforms don't
+        crash.
+
+        * CMakeLists.txt:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::printGetByIdOp):
+        (JSC::CodeBlock::printGetByIdCacheStatus):
+        (JSC::CodeBlock::printPutByIdCacheStatus):
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::propagateTransitions):
+        (JSC::CodeBlock::finalizeLLIntInlineCaches):
+        * bytecode/CodeBlock.h:
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFromLLInt):
+        * bytecode/Instruction.h:
+        (JSC::Instruction::Instruction):
+        * bytecode/PutByIdFlags.cpp: Added.
+        (WTF::printInternal):
+        * bytecode/PutByIdFlags.h: Added.
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFromLLInt):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedInstruction::UnlinkedInstruction):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitPutById):
+        (JSC::BytecodeGenerator::emitDirectPutById):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_put_by_id):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_put_by_id):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+
 2015-09-14  Commit Queue  <commit-qu...@webkit.org>
 
         Unreviewed, rolling out r189751, r189752, and r189754.

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (189765 => 189766)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-09-15 00:55:17 UTC (rev 189766)
@@ -346,6 +346,7 @@
     <ClCompile Include="..\bytecode\PolymorphicAccess.cpp" />
     <ClCompile Include="..\bytecode\PreciseJumpTargets.cpp" />
     <ClCompile Include="..\bytecode\PropertyCondition.cpp" />
+    <ClCompile Include="..\bytecode\PutByIdFlags.cpp" />
     <ClCompile Include="..\bytecode\PutByIdStatus.cpp" />
     <ClCompile Include="..\bytecode\PutByIdVariant.cpp" />
     <ClCompile Include="..\bytecode\ReduceWhitespace.cpp" />
@@ -1046,6 +1047,7 @@
     <ClInclude Include="..\bytecode\PolymorphicAccess.h" />
     <ClInclude Include="..\bytecode\PreciseJumpTargets.h" />
     <ClInclude Include="..\bytecode\PropertyCondition.h" />
+    <ClInclude Include="..\bytecode\PutByIdFlags.h" />
     <ClInclude Include="..\bytecode\PutByIdStatus.h" />
     <ClInclude Include="..\bytecode\PutByIdVariant.h" />
     <ClInclude Include="..\bytecode\PutKind.h" />

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (189765 => 189766)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2015-09-15 00:55:17 UTC (rev 189766)
@@ -201,6 +201,9 @@
     <ClCompile Include="..\bytecode\PolymorphicAccess.cpp">
       <Filter>bytecode</Filter>
     </ClCompile>
+    <ClCompile Include="..\bytecode\PutByIdFlags.cpp">
+      <Filter>bytecode</Filter>
+    </ClCompile>
     <ClCompile Include="..\bytecode\PutByIdStatus.cpp">
       <Filter>bytecode</Filter>
     </ClCompile>
@@ -2094,6 +2097,9 @@
     <ClInclude Include="..\bytecode\PolymorphicAccess.h">
       <Filter>bytecode</Filter>
     </ClInclude>
+    <ClInclude Include="..\bytecode\PutByIdFlags.h">
+      <Filter>bytecode</Filter>
+    </ClInclude>
     <ClInclude Include="..\bytecode\PutByIdStatus.h">
       <Filter>bytecode</Filter>
     </ClInclude>

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (189765 => 189766)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-09-15 00:55:17 UTC (rev 189766)
@@ -105,6 +105,8 @@
 		0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */; };
 		0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */; };
+		0F15CD221BA5F9860031FFD3 /* PutByIdFlags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */; };
+		0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F1725FF1B48719A00AC3A55 /* DFGMinifiedGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */; };
 		0F18D3CF1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */; };
@@ -1932,6 +1934,8 @@
 		0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerProfiledBytecodes.cpp; path = profiler/ProfilerProfiledBytecodes.cpp; sourceTree = "<group>"; };
 		0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerProfiledBytecodes.h; path = profiler/ProfilerProfiledBytecodes.h; sourceTree = "<group>"; };
 		0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexingType.cpp; sourceTree = "<group>"; };
+		0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdFlags.cpp; sourceTree = "<group>"; };
+		0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdFlags.h; sourceTree = "<group>"; };
 		0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
 		0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMinifiedGraph.cpp; path = dfg/DFGMinifiedGraph.cpp; sourceTree = "<group>"; };
 		0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAdaptiveStructureWatchpoint.cpp; path = dfg/DFGAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; };
@@ -5600,6 +5604,8 @@
 				0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */,
 				0FD3E4071B618B6600C80E1E /* PropertyCondition.cpp */,
 				0FD3E4081B618B6600C80E1E /* PropertyCondition.h */,
+				0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */,
+				0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */,
 				0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
 				0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
 				0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */,
@@ -6740,6 +6746,7 @@
 				0F682FB319BCB36400FA3BAD /* DFGSSACalculator.h in Headers */,
 				0FB7F39D15ED8E4600F167B2 /* Reject.h in Headers */,
 				0F2D4DEA19832DAC007D4B19 /* TypeLocation.h in Headers */,
+				0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */,
 				A5BA15E8182340B300A82E69 /* RemoteInspector.h in Headers */,
 				A5BA15EA182340B400A82E69 /* RemoteInspectorConstants.h in Headers */,
 				A5BA15F0182345AF00A82E69 /* RemoteInspectorDebuggable.h in Headers */,
@@ -7472,6 +7479,7 @@
 				0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
 				0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
 				0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
+				0F15CD221BA5F9860031FFD3 /* PutByIdFlags.cpp in Sources */,
 				C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */,
 				0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
 				C2981FD817BAEE4B00A3BC98 /* DFGDesiredWeakReferences.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2015-09-15 00:55:17 UTC (rev 189766)
@@ -57,14 +57,8 @@
             { "name" : "op_is_function", "length" : 3 },
             { "name" : "op_in", "length" : 4 },
             { "name" : "op_get_by_id", "length" : 9  },
-            { "name" : "op_get_by_id_out_of_line", "length" : 9  },
             { "name" : "op_get_array_length", "length" : 9 },
             { "name" : "op_put_by_id", "length" : 9 },
-            { "name" : "op_put_by_id_out_of_line", "length" : 9 },
-            { "name" : "op_put_by_id_transition_direct", "length" : 9 },
-            { "name" : "op_put_by_id_transition_direct_out_of_line", "length" : 9 },
-            { "name" : "op_put_by_id_transition_normal", "length" : 9 },
-            { "name" : "op_put_by_id_transition_normal_out_of_line", "length" : 9 },
             { "name" : "op_del_by_id", "length" : 4 },
             { "name" : "op_get_by_val", "length" : 6 },
             { "name" : "op_put_by_val", "length" : 5 },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2015-09-15 00:55:17 UTC (rev 189766)
@@ -93,11 +93,6 @@
         return;
     }
     case op_put_by_index:
-    case op_put_by_id_transition_direct:
-    case op_put_by_id_transition_direct_out_of_line:
-    case op_put_by_id_transition_normal:
-    case op_put_by_id_transition_normal_out_of_line:
-    case op_put_by_id_out_of_line:
     case op_put_by_id:
     case op_put_to_scope:
     case op_put_to_arguments: {
@@ -134,7 +129,6 @@
     case op_get_from_scope:
     case op_to_primitive:
     case op_get_by_id:
-    case op_get_by_id_out_of_line:
     case op_get_array_length:
     case op_typeof:
     case op_is_undefined:
@@ -277,11 +271,6 @@
     case op_switch_char:
     case op_switch_string:
     case op_put_by_id:
-    case op_put_by_id_out_of_line:
-    case op_put_by_id_transition_direct:
-    case op_put_by_id_transition_direct_out_of_line:
-    case op_put_by_id_transition_normal:
-    case op_put_by_id_transition_normal_out_of_line:
     case op_put_getter_by_id:
     case op_put_setter_by_id:
     case op_put_getter_setter:
@@ -328,7 +317,6 @@
     case op_call_eval:
     case op_construct:
     case op_get_by_id:
-    case op_get_by_id_out_of_line:
     case op_get_array_length:
     case op_check_has_instance:
     case op_instanceof:

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -273,9 +273,6 @@
     case op_get_by_id:
         op = "get_by_id";
         break;
-    case op_get_by_id_out_of_line:
-        op = "get_by_id_out_of_line";
-        break;
     case op_get_array_length:
         op = "array_length";
         break;
@@ -331,7 +328,8 @@
     
     if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
         out.printf(" llint(array_length)");
-    else if (Structure* structure = instruction[4].u.structure.get()) {
+    else if (StructureID structureID = instruction[4].u.structureID) {
+        Structure* structure = m_vm->heap.structureIDTable().get(structureID);
         out.printf(" llint(");
         dumpStructure(out, "struct", structure, ident);
         out.printf(")");
@@ -382,42 +380,31 @@
 #endif
 }
 
-void CodeBlock::printPutByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
+void CodeBlock::printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
 {
     Instruction* instruction = instructions().begin() + location;
 
     const Identifier& ident = identifier(instruction[2].u.operand);
     
     UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
+
+    out.print(", ", instruction[8].u.putByIdFlags);
     
-    if (Structure* structure = instruction[4].u.structure.get()) {
-        switch (exec->interpreter()->getOpcodeID(instruction[0].u.opcode)) {
-        case op_put_by_id:
-        case op_put_by_id_out_of_line:
-            out.print(" llint(");
-            dumpStructure(out, "struct", structure, ident);
-            out.print(")");
-            break;
-            
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line:
-            out.print(" llint(");
+    if (StructureID structureID = instruction[4].u.structureID) {
+        Structure* structure = m_vm->heap.structureIDTable().get(structureID);
+        out.print(" llint(");
+        if (StructureID newStructureID = instruction[6].u.structureID) {
+            Structure* newStructure = m_vm->heap.structureIDTable().get(newStructureID);
             dumpStructure(out, "prev", structure, ident);
             out.print(", ");
-            dumpStructure(out, "next", instruction[6].u.structure.get(), ident);
+            dumpStructure(out, "next", newStructure, ident);
             if (StructureChain* chain = instruction[7].u.structureChain.get()) {
                 out.print(", ");
                 dumpChain(out, chain, ident);
             }
-            out.print(")");
-            break;
-            
-        default:
-            out.print(" llint(unknown)");
-            break;
-        }
+        } else
+            dumpStructure(out, "struct", structure, ident);
+        out.print(")");
     }
 
 #if ENABLE(JIT)
@@ -1001,7 +988,6 @@
             break;
         }
         case op_get_by_id:
-        case op_get_by_id_out_of_line:
         case op_get_array_length: {
             printGetByIdOp(out, exec, location, it);
             printGetByIdCacheStatus(out, exec, location, stubInfos);
@@ -1010,34 +996,9 @@
         }
         case op_put_by_id: {
             printPutByIdOp(out, exec, location, it, "put_by_id");
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
+            printPutByIdCacheStatus(out, location, stubInfos);
             break;
         }
-        case op_put_by_id_out_of_line: {
-            printPutByIdOp(out, exec, location, it, "put_by_id_out_of_line");
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_transition_direct: {
-            printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct");
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_transition_direct_out_of_line: {
-            printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct_out_of_line");
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_transition_normal: {
-            printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal");
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_transition_normal_out_of_line: {
-            printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal_out_of_line");
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
         case op_put_getter_by_id: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
@@ -1936,7 +1897,6 @@
             instructions[i + opLength - 1] = profile;
             break;
         }
-        case op_get_by_id_out_of_line:
         case op_get_array_length:
             CRASH();
 
@@ -2417,12 +2377,17 @@
         for (size_t i = 0; i < propertyAccessInstructions.size(); ++i) {
             Instruction* instruction = &instructions()[propertyAccessInstructions[i]];
             switch (interpreter->getOpcodeID(instruction[0].u.opcode)) {
-            case op_put_by_id_transition_direct:
-            case op_put_by_id_transition_normal:
-            case op_put_by_id_transition_direct_out_of_line:
-            case op_put_by_id_transition_normal_out_of_line: {
-                if (Heap::isMarked(instruction[4].u.structure.get()))
-                    visitor.append(&instruction[6].u.structure);
+            case op_put_by_id: {
+                StructureID oldStructureID = instruction[4].u.structureID;
+                StructureID newStructureID = instruction[6].u.structureID;
+                if (!oldStructureID || !newStructureID)
+                    break;
+                Structure* oldStructure =
+                    m_vm->heap.structureIDTable().get(oldStructureID);
+                Structure* newStructure =
+                    m_vm->heap.structureIDTable().get(newStructureID);
+                if (Heap::isMarked(oldStructure))
+                    visitor.appendUnbarrieredReadOnlyPointer(newStructure);
                 else
                     allAreMarkedSoFar = false;
                 break;
@@ -2553,36 +2518,32 @@
     for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
         Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
         switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
-        case op_get_by_id:
-        case op_get_by_id_out_of_line:
-        case op_put_by_id:
-        case op_put_by_id_out_of_line:
-            if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
+        case op_get_by_id: {
+            StructureID oldStructureID = curInstruction[4].u.structureID;
+            if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID)))
                 break;
             if (Options::verboseOSR())
-                dataLogF("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
-            curInstruction[4].u.structure.clear();
+                dataLogF("Clearing LLInt property access.\n");
+            curInstruction[4].u.structureID = 0;
             curInstruction[5].u.operand = 0;
             break;
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line:
-            if (Heap::isMarked(curInstruction[4].u.structure.get())
-                && Heap::isMarked(curInstruction[6].u.structure.get())
-                && Heap::isMarked(curInstruction[7].u.structureChain.get()))
+        }
+        case op_put_by_id: {
+            StructureID oldStructureID = curInstruction[4].u.structureID;
+            StructureID newStructureID = curInstruction[6].u.structureID;
+            StructureChain* chain = curInstruction[7].u.structureChain.get();
+            if ((!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID))) &&
+                (!newStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(newStructureID))) &&
+                (!chain || Heap::isMarked(chain)))
                 break;
-            if (Options::verboseOSR()) {
-                dataLogF("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
-                    curInstruction[4].u.structure.get(),
-                    curInstruction[6].u.structure.get(),
-                    curInstruction[7].u.structureChain.get());
-            }
-            curInstruction[4].u.structure.clear();
-            curInstruction[6].u.structure.clear();
+            if (Options::verboseOSR())
+                dataLogF("Clearing LLInt put transition.\n");
+            curInstruction[4].u.structureID = 0;
+            curInstruction[5].u.operand = 0;
+            curInstruction[6].u.structureID = 0;
             curInstruction[7].u.structureChain.clear();
-            curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id);
             break;
+        }
         case op_get_array_length:
             break;
         case op_to_this:

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2015-09-15 00:55:17 UTC (rev 189766)
@@ -969,7 +969,7 @@
     enum CacheDumpMode { DumpCaches, DontDumpCaches };
     void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&);
     void printPutByIdOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
-    void printPutByIdCacheStatus(PrintStream&, ExecState*, int location, const StubInfoMap&);
+    void printPutByIdCacheStatus(PrintStream&, int location, const StubInfoMap&);
     void printLocationAndOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
     void printLocationOpAndRegisterOperand(PrintStream&, ExecState*, int location, const Instruction*& it, const char* op, int operand);
 

Modified: trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -70,15 +70,20 @@
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(bytecodeIndex);
     UNUSED_PARAM(uid);
+
+    VM& vm = *profiledBlock->vm();
+    
     Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
     
     if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length))
         return GetByIdStatus(NoInformation, false);
 
-    Structure* structure = instruction[4].u.structure.get();
-    if (!structure)
+    StructureID structureID = instruction[4].u.structureID;
+    if (!structureID)
         return GetByIdStatus(NoInformation, false);
 
+    Structure* structure = vm.heap.structureIDTable().get(structureID);
+
     if (structure->takesSlowPathInDFGForImpureProperty())
         return GetByIdStatus(NoInformation, false);
 

Modified: trunk/Source/_javascript_Core/bytecode/Instruction.h (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecode/Instruction.h	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecode/Instruction.h	2015-09-15 00:55:17 UTC (rev 189766)
@@ -32,6 +32,7 @@
 #include "BasicBlockLocation.h"
 #include "MacroAssembler.h"
 #include "Opcode.h"
+#include "PutByIdFlags.h"
 #include "SymbolTable.h"
 #include "TypeLocation.h"
 #include "PropertySlot.h"
@@ -75,6 +76,11 @@
         u.operand = operand;
     }
 
+    Instruction(PutByIdFlags flags)
+    {
+        u.putByIdFlags = flags;
+    }
+
     Instruction(VM& vm, JSCell* owner, Structure* structure)
     {
         u.structure.clear();
@@ -107,6 +113,7 @@
         Opcode opcode;
         int operand;
         WriteBarrierBase<Structure> structure;
+        StructureID structureID;
         WriteBarrierBase<SymbolTable> symbolTable;
         WriteBarrierBase<StructureChain> structureChain;
         WriteBarrierBase<JSCell> jsCell;
@@ -125,6 +132,7 @@
         ToThisStatus toThisStatus;
         TypeLocation* location;
         BasicBlockLocation* basicBlockLocation;
+        PutByIdFlags putByIdFlags;
     } u;
         
 private:

Added: trunk/Source/_javascript_Core/bytecode/PutByIdFlags.cpp (0 => 189766)


--- trunk/Source/_javascript_Core/bytecode/PutByIdFlags.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/PutByIdFlags.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "PutByIdFlags.h"
+
+#include <wtf/CommaPrinter.h>
+#include <wtf/PrintStream.h>
+#include <wtf/StringPrintStream.h>
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream& out, PutByIdFlags flags) {
+    StringPrintStream stringOut;
+    CommaPrinter comma("|");
+    if (flags & PutByIdIsDirect)
+        stringOut.print(comma, "IsDirect");
+
+    CString string = stringOut.toCString();
+    if (!string.length())
+        out.print("None");
+    else
+        out.print(string);
+}
+
+} // namespace WTF
+

Added: trunk/Source/_javascript_Core/bytecode/PutByIdFlags.h (0 => 189766)


--- trunk/Source/_javascript_Core/bytecode/PutByIdFlags.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/PutByIdFlags.h	2015-09-15 00:55:17 UTC (rev 189766)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PutByIdFlags_h
+#define PutByIdFlags_h
+
+namespace JSC {
+
+enum PutByIdFlags {
+    PutByIdNone = 0,
+    PutByIdIsDirect = 1
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+class PrintStream;
+
+void printInternal(PrintStream&, JSC::PutByIdFlags);
+
+} // namespace WTF
+
+#endif // PutByIdFlags_h
+

Modified: trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -66,37 +66,36 @@
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(bytecodeIndex);
     UNUSED_PARAM(uid);
+
+    VM& vm = *profiledBlock->vm();
+    
     Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
 
-    Structure* structure = instruction[4].u.structure.get();
-    if (!structure)
+    StructureID structureID = instruction[4].u.structureID;
+    if (!structureID)
         return PutByIdStatus(NoInformation);
     
-    if (instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_out_of_line)) {
+    Structure* structure = vm.heap.structureIDTable().get(structureID);
+
+    StructureID newStructureID = instruction[6].u.structureID;
+    if (!newStructureID) {
         PropertyOffset offset = structure->getConcurrently(uid);
         if (!isValidOffset(offset))
             return PutByIdStatus(NoInformation);
         
         return PutByIdVariant::replace(structure, offset);
     }
+
+    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
     
     ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
     
-    ASSERT(instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_direct)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line));
-    
-    Structure* newStructure = instruction[6].u.structure.get();
-    
     PropertyOffset offset = newStructure->getConcurrently(uid);
     if (!isValidOffset(offset))
         return PutByIdStatus(NoInformation);
     
     ObjectPropertyConditionSet conditionSet;
-    if (instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line)) {
+    if (!(instruction[8].u.putByIdFlags & PutByIdIsDirect)) {
         conditionSet =
             generateConditionsForPropertySetterMissConcurrently(
                 *profiledBlock->vm(), profiledBlock->globalObject(), structure, uid);

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2015-09-15 00:55:17 UTC (rev 189766)
@@ -36,6 +36,7 @@
 #include "JSCell.h"
 #include "JSString.h"
 #include "ParserModes.h"
+#include "PutByIdFlags.h"
 #include "RegExp.h"
 #include "SpecialPointer.h"
 #include "UnlinkedFunctionExecutable.h"
@@ -97,10 +98,12 @@
     UnlinkedInstruction() { u.operand = 0; }
     UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
     UnlinkedInstruction(int operand) { u.operand = operand; }
+    UnlinkedInstruction(PutByIdFlags flags) { u.putByIdFlags = flags; }
     union {
         OpcodeID opcode;
         int32_t operand;
         unsigned index;
+        PutByIdFlags putByIdFlags;
     } u;
 };
 

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -2103,11 +2103,11 @@
     instructions().append(base->index());
     instructions().append(propertyIndex);
     instructions().append(value->index());
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
+    instructions().append(0); // old structure
+    instructions().append(0); // offset
+    instructions().append(0); // new structure
+    instructions().append(0); // structure chain
+    instructions().append(PutByIdNone); // is not direct
 
     return value;
 }
@@ -2125,11 +2125,11 @@
     instructions().append(base->index());
     instructions().append(propertyIndex);
     instructions().append(value->index());
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto);
+    instructions().append(0); // old structure
+    instructions().append(0); // offset
+    instructions().append(0); // new structure
+    instructions().append(0); // structure chain (unused if direct)
+    instructions().append((putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone);
     return value;
 }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -44,6 +44,7 @@
 #include "JSCInlines.h"
 #include "JSModuleEnvironment.h"
 #include "PreciseJumpTargets.h"
+#include "PutByIdFlags.h"
 #include "PutByIdStatus.h"
 #include "StackAlignment.h"
 #include "StringConstructor.h"
@@ -3513,7 +3514,6 @@
         }
             
         case op_get_by_id:
-        case op_get_by_id_out_of_line:
         case op_get_array_length: {
             SpeculatedType prediction = getPrediction();
             
@@ -3531,16 +3531,11 @@
 
             NEXT_OPCODE(op_get_by_id);
         }
-        case op_put_by_id:
-        case op_put_by_id_out_of_line:
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line: {
+        case op_put_by_id: {
             Node* value = get(VirtualRegister(currentInstruction[3].u.operand));
             Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
             unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
-            bool direct = currentInstruction[8].u.operand;
+            bool direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
 
             PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
                 m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -152,14 +152,8 @@
     case op_put_by_val:
     case op_put_by_val_direct:
     case op_get_by_id:
-    case op_get_by_id_out_of_line:
     case op_get_array_length:
     case op_put_by_id:
-    case op_put_by_id_out_of_line:
-    case op_put_by_id_transition_direct:
-    case op_put_by_id_transition_direct_out_of_line:
-    case op_put_by_id_transition_normal:
-    case op_put_by_id_transition_normal_out_of_line:
     case op_jmp:
     case op_jtrue:
     case op_jfalse:

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -217,7 +217,6 @@
         DEFINE_OP(op_load_arrowfunction_this)
         DEFINE_OP(op_eq)
         DEFINE_OP(op_eq_null)
-        case op_get_by_id_out_of_line:
         case op_get_array_length:
         DEFINE_OP(op_get_by_id)
         DEFINE_OP(op_get_by_val)
@@ -269,11 +268,6 @@
         DEFINE_OP(op_push_with_scope)
         DEFINE_OP(op_create_lexical_environment)
         DEFINE_OP(op_get_parent_scope)
-        case op_put_by_id_out_of_line:
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line:
         DEFINE_OP(op_put_by_id)
         DEFINE_OP(op_put_by_index)
         case op_put_by_val_direct:
@@ -386,7 +380,6 @@
         DEFINE_SLOWCASE_OP(op_create_this)
         DEFINE_SLOWCASE_OP(op_div)
         DEFINE_SLOWCASE_OP(op_eq)
-        case op_get_by_id_out_of_line:
         case op_get_array_length:
         DEFINE_SLOWCASE_OP(op_get_by_id)
         DEFINE_SLOWCASE_OP(op_get_by_val)
@@ -413,11 +406,6 @@
         DEFINE_SLOWCASE_OP(op_nstricteq)
         DEFINE_SLOWCASE_OP(op_dec)
         DEFINE_SLOWCASE_OP(op_inc)
-        case op_put_by_id_out_of_line:
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line:
         DEFINE_SLOWCASE_OP(op_put_by_id)
         case op_put_by_val_direct:
         DEFINE_SLOWCASE_OP(op_put_by_val)

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -607,7 +607,7 @@
 {
     int baseVReg = currentInstruction[1].u.operand;
     int valueVReg = currentInstruction[3].u.operand;
-    unsigned direct = currentInstruction[8].u.operand;
+    unsigned direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
 
     emitWriteBarrier(baseVReg, valueVReg, ShouldFilterBase);
 

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -623,7 +623,7 @@
     
     int base = currentInstruction[1].u.operand;
     int value = currentInstruction[3].u.operand;
-    int direct = currentInstruction[8].u.operand;
+    int direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
     
     emitWriteBarrier(base, value, ShouldFilterBase);
 

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (189765 => 189766)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2015-09-15 00:55:17 UTC (rev 189766)
@@ -570,20 +570,20 @@
         JSCell* baseCell = baseValue.asCell();
         Structure* structure = baseCell->structure();
         
+        // Start out by clearing out the old cache.
+        pc[0].u.opcode = LLInt::getOpcode(op_get_by_id);
+        pc[4].u.pointer = nullptr; // old structure
+        pc[5].u.pointer = nullptr; // offset
+        
         if (!structure->isUncacheableDictionary()
             && !structure->typeInfo().prohibitsPropertyCaching()
             && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) {
+            vm.heap.writeBarrier(codeBlock->ownerExecutable());
+            
             ConcurrentJITLocker locker(codeBlock->m_lock);
 
-            pc[4].u.structure.set(
-                vm, codeBlock->ownerExecutable(), structure);
-            if (isInlineOffset(slot.cachedOffset())) {
-                pc[0].u.opcode = LLInt::getOpcode(op_get_by_id);
-                pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
-            } else {
-                pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_out_of_line);
-                pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
-            }
+            pc[4].u.structureID = structure->id();
+            pc[5].u.operand = slot.cachedOffset();
         }
     }
 
@@ -618,7 +618,7 @@
     
     JSValue baseValue = LLINT_OP_C(1).jsValue();
     PutPropertySlot slot(baseValue, codeBlock->isStrictMode(), codeBlock->putByIdContext());
-    if (pc[8].u.operand)
+    if (pc[8].u.putByIdFlags & PutByIdIsDirect)
         asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
     else
         baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
@@ -627,6 +627,12 @@
     if (!LLINT_ALWAYS_ACCESS_SLOW
         && baseValue.isCell()
         && slot.isCacheablePut()) {
+
+        // Start out by clearing out the old cache.
+        pc[4].u.pointer = nullptr; // old structure
+        pc[5].u.pointer = nullptr; // offset
+        pc[6].u.pointer = nullptr; // new structure
+        pc[7].u.pointer = nullptr; // structure chain
         
         JSCell* baseCell = baseValue.asCell();
         Structure* structure = baseCell->structure();
@@ -634,56 +640,32 @@
         if (!structure->isUncacheableDictionary()
             && !structure->typeInfo().prohibitsPropertyCaching()
             && baseCell == slot.base()) {
+
+            vm.heap.writeBarrier(codeBlock->ownerExecutable());
             
             if (slot.type() == PutPropertySlot::NewProperty) {
                 GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap);
             
                 if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) {
                     ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
-                    
-                    // This is needed because some of the methods we call
-                    // below may GC.
-                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
 
                     if (normalizePrototypeChain(exec, structure) != InvalidPrototypeChain) {
                         ASSERT(structure->previousID()->isObject());
-                        pc[4].u.structure.set(
-                            vm, codeBlock->ownerExecutable(), structure->previousID());
-                        if (isInlineOffset(slot.cachedOffset()))
-                            pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
-                        else
-                            pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
-                        pc[6].u.structure.set(
-                            vm, codeBlock->ownerExecutable(), structure);
-                        StructureChain* chain = structure->prototypeChain(exec);
-                        ASSERT(chain);
-                        pc[7].u.structureChain.set(
-                            vm, codeBlock->ownerExecutable(), chain);
-                    
-                        if (pc[8].u.operand) {
-                            if (isInlineOffset(slot.cachedOffset()))
-                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct);
-                            else
-                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line);
-                        } else {
-                            if (isInlineOffset(slot.cachedOffset()))
-                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal);
-                            else
-                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line);
+                        pc[4].u.structureID = structure->previousID()->id();
+                        pc[5].u.operand = slot.cachedOffset();
+                        pc[6].u.structureID = structure->id();
+                        if (!(pc[8].u.putByIdFlags & PutByIdIsDirect)) {
+                            StructureChain* chain = structure->prototypeChain(exec);
+                            ASSERT(chain);
+                            pc[7].u.structureChain.set(
+                                vm, codeBlock->ownerExecutable(), chain);
                         }
                     }
                 }
             } else {
                 structure->didCachePropertyReplacement(vm, slot.cachedOffset());
-                pc[4].u.structure.set(
-                    vm, codeBlock->ownerExecutable(), structure);
-                if (isInlineOffset(slot.cachedOffset())) {
-                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
-                    pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
-                } else {
-                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_out_of_line);
-                    pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
-                }
+                pc[4].u.structureID = structure->id();
+                pc[5].u.operand = slot.cachedOffset();
             }
         }
     }

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (189765 => 189766)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2015-09-15 00:55:17 UTC (rev 189766)
@@ -1323,39 +1323,25 @@
 # to take fast path on the new cache. At worst we take slow path, which is what
 # we would have been doing anyway.
 
-macro getById(getPropertyStorage)
+_llint_op_get_by_id:
     traceExecution()
     loadi 8[PC], t0
     loadi 16[PC], t1
     loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
     loadi 20[PC], t2
-    getPropertyStorage(
-        t3,
-        t0,
-        macro (propertyStorage, scratch)
-            bpneq JSCell::m_structureID[t3], t1, .opGetByIdSlow
-            loadi 4[PC], t1
-            loadi TagOffset[propertyStorage, t2], scratch
-            loadi PayloadOffset[propertyStorage, t2], t2
-            storei scratch, TagOffset[cfr, t1, 8]
-            storei t2, PayloadOffset[cfr, t1, 8]
-            valueProfile(scratch, t2, 32, t1)
-            dispatch(9)
-        end)
+    bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
+    loadPropertyAtVariableOffset(t2, t3, t0, t1)
+    loadi 4[PC], t2
+    storei t0, TagOffset[cfr, t2, 8]
+    storei t1, PayloadOffset[cfr, t2, 8]
+    valueProfile(t0, t1, 32, t2)
+    dispatch(9)
 
-    .opGetByIdSlow:
-        callSlowPath(_llint_slow_path_get_by_id)
-        dispatch(9)
-end
+.opGetByIdSlow:
+    callSlowPath(_llint_slow_path_get_by_id)
+    dispatch(9)
 
-_llint_op_get_by_id:
-    getById(withInlineStorage)
 
-
-_llint_op_get_by_id_out_of_line:
-    getById(withOutOfLineStorage)
-
-
 _llint_op_get_array_length:
     traceExecution()
     loadi 8[PC], t0
@@ -1379,102 +1365,59 @@
     dispatch(9)
 
 
-macro putById(getPropertyStorage)
+_llint_op_put_by_id:
     traceExecution()
     writeBarrierOnOperands(1, 3)
     loadi 4[PC], t3
-    loadi 16[PC], t1
     loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
-    loadi 12[PC], t2
-    getPropertyStorage(
-        t0,
-        t3,
-        macro (propertyStorage, scratch)
-            bpneq JSCell::m_structureID[t0], t1, .opPutByIdSlow
-            loadi 20[PC], t1
-            loadConstantOrVariable2Reg(t2, scratch, t2)
-            storei scratch, TagOffset[propertyStorage, t1]
-            storei t2, PayloadOffset[propertyStorage, t1]
-            dispatch(9)
-        end)
+    loadi JSCell::m_structureID[t0], t2
+    bineq t2, 16[PC], .opPutByIdSlow
 
-    .opPutByIdSlow:
-        callSlowPath(_llint_slow_path_put_by_id)
-        dispatch(9)
-end
+    # At this point, we have:
+    # t2 -> currentStructureID
+    # t0 -> object base
 
-_llint_op_put_by_id:
-    putById(withInlineStorage)
+    loadi 24[PC], t1
 
+    btiz t1, .opPutByIdNotTransition
 
-_llint_op_put_by_id_out_of_line:
-    putById(withOutOfLineStorage)
+    # This is the transition case. t1 holds the new Structure*. t2 holds the old Structure*.
+    # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
+    # scratch.
+    loadp 28[PC], t3
+    btpz t3, .opPutByIdTransitionDirect
 
+    loadp StructureChain::m_vector[t3], t3
+    assert(macro (ok) btpnz t3, ok end)
 
-macro putByIdTransition(additionalChecks, getPropertyStorage)
-    traceExecution()
-    writeBarrierOnOperand(1)
-    loadi 4[PC], t3
-    loadi 16[PC], t1
-    loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
-    loadi 12[PC], t2
-    bpneq JSCell::m_structureID[t0], t1, .opPutByIdSlow
-    additionalChecks(t1, t3, .opPutByIdSlow)
-    loadi 20[PC], t1
-    getPropertyStorage(
-        t0,
-        t3,
-        macro (propertyStorage, scratch)
-            addp t1, propertyStorage, t3
-            loadConstantOrVariable2Reg(t2, t1, t2)
-            storei t1, TagOffset[t3]
-            loadi 24[PC], t1
-            storei t2, PayloadOffset[t3]
-            storep t1, JSCell::m_structureID[t0]
-            dispatch(9)
-        end)
+    loadp Structure::m_prototype[t2], t2
+    btpz t2, .opPutByIdTransitionChainDone
+.opPutByIdTransitionChainLoop:
+    loadp [t3], t1
+    bpneq t1, JSCell::m_structureID[t2], .opPutByIdSlow
+    addp 4, t3
+    loadp Structure::m_prototype[t1], t2
+    btpnz t2, .opPutByIdTransitionChainLoop
 
-    .opPutByIdSlow:
-        callSlowPath(_llint_slow_path_put_by_id)
-        dispatch(9)
-end
+.opPutByIdTransitionChainDone:
+    loadi 24[PC], t1
 
-macro noAdditionalChecks(oldStructure, scratch, slowPath)
-end
+.opPutByIdTransitionDirect:
+    storei t1, JSCell::m_structureID[t0]
 
-macro structureChainChecks(oldStructure, scratch, slowPath)
-    const protoCell = oldStructure   # Reusing the oldStructure register for the proto
+.opPutByIdNotTransition:
+    # The only thing live right now is t0, which holds the base.
+    loadi 12[PC], t1
+    loadConstantOrVariable(t1, t2, t3)
+    loadi 20[PC], t1
+    storePropertyAtVariableOffset(t1, t0, t2, t3)
+    dispatch(9)
 
-    loadp 28[PC], scratch
-    assert(macro (ok) btpnz scratch, ok end)
-    loadp StructureChain::m_vector[scratch], scratch
-    assert(macro (ok) btpnz scratch, ok end)
-    bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done
-.loop:
-    loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell
-    loadp JSCell::m_structureID[protoCell], oldStructure
-    bpneq oldStructure, [scratch], slowPath
-    addp 4, scratch
-    bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop
-.done:
-end
+.opPutByIdSlow:
+    callSlowPath(_llint_slow_path_put_by_id)
+    dispatch(9)
 
-_llint_op_put_by_id_transition_direct:
-    putByIdTransition(noAdditionalChecks, withInlineStorage)
 
-
-_llint_op_put_by_id_transition_direct_out_of_line:
-    putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
-
-
-_llint_op_put_by_id_transition_normal:
-    putByIdTransition(structureChainChecks, withInlineStorage)
-
-
-_llint_op_put_by_id_transition_normal_out_of_line:
-    putByIdTransition(structureChainChecks, withOutOfLineStorage)
-
-
 _llint_op_get_by_val:
     traceExecution()
     loadi 8[PC], t2

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (189765 => 189766)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2015-09-15 00:55:17 UTC (rev 189766)
@@ -468,15 +468,16 @@
     storeq value, ValueProfile::m_buckets[scratch]
 end
 
-macro loadStructure(cell, structure)
-end
-
-macro loadStructureWithScratch(cell, structure, scratch)
+macro structureIDToStructureWithScratch(structureIDThenStructure, scratch)
     loadp CodeBlock[cfr], scratch
     loadp CodeBlock::m_vm[scratch], scratch
     loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
+    loadp [scratch, structureIDThenStructure, 8], structureIDThenStructure
+end
+
+macro loadStructureWithScratch(cell, structure, scratch)
     loadi JSCell::m_structureID[cell], structure
-    loadp [scratch, structure, 8], structure
+    structureIDToStructureWithScratch(structure, scratch)
 end
 
 macro loadStructureAndClobberFirstArg(cell, structure)
@@ -1204,43 +1205,25 @@
     storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
 end
 
-macro getById(getPropertyStorage)
+_llint_op_get_by_id:
     traceExecution()
-    # We only do monomorphic get_by_id caching for now, and we do not modify the
-    # opcode. We do, however, allow for the cache to change anytime if fails, since
-    # ping-ponging is free. At best we get lucky and the get_by_id will continue
-    # to take fast path on the new cache. At worst we take slow path, which is what
-    # we would have been doing anyway.
     loadisFromInstruction(2, t0)
     loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
-    loadStructureWithScratch(t3, t2, t1)
-    loadpFromInstruction(4, t1)
-    bpneq t2, t1, .opGetByIdSlow
-    getPropertyStorage(
-        t3,
-        t0,
-        macro (propertyStorage, scratch)
-            loadisFromInstruction(5, t2)
-            loadisFromInstruction(1, t1)
-            loadq [propertyStorage, t2], scratch
-            storeq scratch, [cfr, t1, 8]
-            valueProfile(scratch, 8, t1)
-            dispatch(9)
-        end)
-            
-    .opGetByIdSlow:
-        callSlowPath(_llint_slow_path_get_by_id)
-        dispatch(9)
-end
+    loadi JSCell::m_structureID[t3], t1
+    loadisFromInstruction(4, t2)
+    bineq t2, t1, .opGetByIdSlow
+    loadisFromInstruction(5, t1)
+    loadisFromInstruction(1, t2)
+    loadPropertyAtVariableOffset(t1, t3, t0)
+    storeq t0, [cfr, t2, 8]
+    valueProfile(t0, 8, t1)
+    dispatch(9)
 
-_llint_op_get_by_id:
-    getById(withInlineStorage)
+.opGetByIdSlow:
+    callSlowPath(_llint_slow_path_get_by_id)
+    dispatch(9)
 
 
-_llint_op_get_by_id_out_of_line:
-    getById(withOutOfLineStorage)
-
-
 _llint_op_get_array_length:
     traceExecution()
     loadisFromInstruction(2, t0)
@@ -1264,99 +1247,67 @@
     dispatch(9)
 
 
-macro putById(getPropertyStorage)
+_llint_op_put_by_id:
     traceExecution()
     writeBarrierOnOperands(1, 3)
     loadisFromInstruction(1, t3)
     loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
-    loadStructureWithScratch(t0, t2, t1)
-    loadpFromInstruction(4, t1)
-    bpneq t2, t1, .opPutByIdSlow
-    getPropertyStorage(
-        t0,
-        t3,
-        macro (propertyStorage, scratch)
-            loadisFromInstruction(5, t1)
-            loadisFromInstruction(3, t2)
-            loadConstantOrVariable(t2, scratch)
-            storeq scratch, [propertyStorage, t1]
-            dispatch(9)
-        end)
-end
+    loadi JSCell::m_structureID[t0], t2
+    loadisFromInstruction(4, t1)
+    bineq t2, t1, .opPutByIdSlow
 
-_llint_op_put_by_id:
-    putById(withInlineStorage)
+    # At this point, we have:
+    # t1, t2 -> current structure ID
+    # t0 -> object base
 
-.opPutByIdSlow:
-    callSlowPath(_llint_slow_path_put_by_id)
-    dispatch(9)
+    loadisFromInstruction(6, t1)
+    
+    btiz t1, .opPutByIdNotTransition
 
+    # This is the transition case. t1 holds the new structureID. t2 holds the old structure ID.
+    # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
+    # scratch.
+    loadpFromInstruction(7, t3)
+    btpz t3, .opPutByIdTransitionDirect
 
-_llint_op_put_by_id_out_of_line:
-    putById(withOutOfLineStorage)
+    loadp StructureChain::m_vector[t3], t3
+    assert(macro (ok) btpnz t3, ok end)
 
+    structureIDToStructureWithScratch(t2, t1)
+    loadq Structure::m_prototype[t2], t2
+    bqeq t2, ValueNull, .opPutByIdTransitionChainDone
+.opPutByIdTransitionChainLoop:
+    # At this point, t2 contains a prototye, and [t3] contains the Structure* that we want that
+    # prototype to have. We don't want to have to load the Structure* for t2. Instead, we load
+    # the Structure* from [t3], and then we compare its id to the id in the header of t2.
+    loadp [t3], t1
+    loadi JSCell::m_structureID[t2], t2
+    # Now, t1 has the Structure* and t2 has the StructureID that we want that Structure* to have.
+    bineq t2, Structure::m_blob + StructureIDBlob::u.fields.structureID[t1], .opPutByIdSlow
+    addp 8, t3
+    loadq Structure::m_prototype[t1], t2
+    bqneq t2, ValueNull, .opPutByIdTransitionChainLoop
 
-macro putByIdTransition(additionalChecks, getPropertyStorage)
-    traceExecution()
-    writeBarrierOnOperand(1)
-    loadisFromInstruction(1, t3)
-    loadpFromInstruction(4, t1)
-    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
-    loadStructureWithScratch(t0, t2, t3)
-    bpneq t2, t1, .opPutByIdSlow
-    additionalChecks(t1, t3, t2)
-    loadisFromInstruction(3, t2)
-    loadisFromInstruction(5, t1)
-    getPropertyStorage(
-        t0,
-        t3,
-        macro (propertyStorage, scratch)
-            addp t1, propertyStorage, t3
-            loadConstantOrVariable(t2, t1)
-            storeq t1, [t3]
-            loadpFromInstruction(6, t1)
-            loadi Structure::m_blob + StructureIDBlob::u.words.word1[t1], t1
-            storei t1, JSCell::m_structureID[t0]
-            dispatch(9)
-        end)
-end
+.opPutByIdTransitionChainDone:
+    # Reload the new structure, since we clobbered it above.
+    loadisFromInstruction(6, t1)
 
-macro noAdditionalChecks(oldStructure, scratch, scratch2)
-end
+.opPutByIdTransitionDirect:
+    storei t1, JSCell::m_structureID[t0]
 
-macro structureChainChecks(oldStructure, scratch, scratch2)
-    const protoCell = oldStructure    # Reusing the oldStructure register for the proto
-    loadpFromInstruction(7, scratch)
-    assert(macro (ok) btpnz scratch, ok end)
-    loadp StructureChain::m_vector[scratch], scratch
-    assert(macro (ok) btpnz scratch, ok end)
-    bqeq Structure::m_prototype[oldStructure], ValueNull, .done
-.loop:
-    loadq Structure::m_prototype[oldStructure], protoCell
-    loadStructureAndClobberFirstArg(protoCell, scratch2)
-    move scratch2, oldStructure
-    bpneq oldStructure, [scratch], .opPutByIdSlow
-    addp 8, scratch
-    bqneq Structure::m_prototype[oldStructure], ValueNull, .loop
-.done:
-end
+.opPutByIdNotTransition:
+    # The only thing live right now is t0, which holds the base.
+    loadisFromInstruction(3, t1)
+    loadConstantOrVariable(t1, t2)
+    loadisFromInstruction(5, t1)
+    storePropertyAtVariableOffset(t1, t0, t2)
+    dispatch(9)
 
-_llint_op_put_by_id_transition_direct:
-    putByIdTransition(noAdditionalChecks, withInlineStorage)
+.opPutByIdSlow:
+    callSlowPath(_llint_slow_path_put_by_id)
+    dispatch(9)
 
 
-_llint_op_put_by_id_transition_direct_out_of_line:
-    putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
-
-
-_llint_op_put_by_id_transition_normal:
-    putByIdTransition(structureChainChecks, withInlineStorage)
-
-
-_llint_op_put_by_id_transition_normal_out_of_line:
-    putByIdTransition(structureChainChecks, withOutOfLineStorage)
-
-
 _llint_op_get_by_val:
     traceExecution()
     loadisFromInstruction(2, t2)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to