Unreviewed, rolling out r189751, r189752, and r189754.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Sep 2015 23:44:33 +0000 (23:44 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Sep 2015 23:44:33 +0000 (23:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149143

caused crashes everywhere (Requested by alexchristensen on
#webkit).

Reverted changesets:

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

"Unreviewed, fix non-x86 LLInt build."
http://trac.webkit.org/changeset/189752

"Unreviewed, really fix non-x86 LLInt build without also
breaking everything else."
http://trac.webkit.org/changeset/189754

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

24 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/BytecodeList.json
Source/JavaScriptCore/bytecode/BytecodeUseDef.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
Source/JavaScriptCore/bytecode/Instruction.h
Source/JavaScriptCore/bytecode/PutByIdFlags.cpp [deleted file]
Source/JavaScriptCore/bytecode/PutByIdFlags.h [deleted file]
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

index a6ce71c..dd8f546 100644 (file)
@@ -107,7 +107,6 @@ set(JavaScriptCore_SOURCES
     bytecode/PolymorphicAccess.cpp
     bytecode/PreciseJumpTargets.cpp
     bytecode/PropertyCondition.cpp
-    bytecode/PutByIdFlags.cpp
     bytecode/PutByIdStatus.cpp
     bytecode/PutByIdVariant.cpp
     bytecode/ReduceWhitespace.cpp
index 6fe4be1..2c655c4 100644 (file)
@@ -1,3 +1,24 @@
+2015-09-14  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r189751, r189752, and r189754.
+        https://bugs.webkit.org/show_bug.cgi?id=149143
+
+        caused crashes everywhere (Requested by alexchristensen on
+        #webkit).
+
+        Reverted changesets:
+
+        "LLInt get/put inline caches shouldn't use tons of opcodes"
+        https://bugs.webkit.org/show_bug.cgi?id=149106
+        http://trac.webkit.org/changeset/189751
+
+        "Unreviewed, fix non-x86 LLInt build."
+        http://trac.webkit.org/changeset/189752
+
+        "Unreviewed, really fix non-x86 LLInt build without also
+        breaking everything else."
+        http://trac.webkit.org/changeset/189754
+
 2015-09-14  Filip Pizlo  <fpizlo@apple.com>
 
         Unreviewed, really fix non-x86 LLInt build without also breaking everything else.
index bc7d07e..34791d1 100644 (file)
     <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" />
     <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" />
index 56816ed..d6007c9 100644 (file)
     <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>
     <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>
index c7a254c..9fdf15b 100644 (file)
                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 */; };
                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>"; };
                                0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */,
                                0FD3E4071B618B6600C80E1E /* PropertyCondition.cpp */,
                                0FD3E4081B618B6600C80E1E /* PropertyCondition.h */,
-                               0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */,
-                               0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */,
                                0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
                                0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
                                0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */,
                                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 */,
                                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 */,
index 6c07463..f99e645 100644 (file)
             { "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 },
index d839867..af775b3 100644 (file)
@@ -93,6 +93,11 @@ void computeUsesForBytecodeOffset(
         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: {
@@ -129,6 +134,7 @@ void computeUsesForBytecodeOffset(
     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:
@@ -271,6 +277,11 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset,
     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:
@@ -317,6 +328,7 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset,
     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:
index cb48868..0229e81 100644 (file)
@@ -273,6 +273,9 @@ void CodeBlock::printGetByIdOp(PrintStream& out, ExecState* exec, int location,
     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;
@@ -328,8 +331,7 @@ void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int l
     
     if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
         out.printf(" llint(array_length)");
-    else if (StructureID structureID = instruction[4].u.structureID) {
-        Structure* structure = m_vm->heap.structureIDTable().get(structureID);
+    else if (Structure* structure = instruction[4].u.structure.get()) {
         out.printf(" llint(");
         dumpStructure(out, "struct", structure, ident);
         out.printf(")");
@@ -380,31 +382,42 @@ void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int l
 #endif
 }
 
-void CodeBlock::printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
+void CodeBlock::printPutByIdCacheStatus(PrintStream& out, ExecState* exec, 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 (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);
+    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(");
             dumpStructure(out, "prev", structure, ident);
             out.print(", ");
-            dumpStructure(out, "next", newStructure, ident);
+            dumpStructure(out, "next", instruction[6].u.structure.get(), ident);
             if (StructureChain* chain = instruction[7].u.structureChain.get()) {
                 out.print(", ");
                 dumpChain(out, chain, ident);
             }
-        } else
-            dumpStructure(out, "struct", structure, ident);
-        out.print(")");
+            out.print(")");
+            break;
+            
+        default:
+            out.print(" llint(unknown)");
+            break;
+        }
     }
 
 #if ENABLE(JIT)
@@ -988,6 +1001,7 @@ void CodeBlock::dumpBytecode(
             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);
@@ -996,7 +1010,32 @@ void CodeBlock::dumpBytecode(
         }
         case op_put_by_id: {
             printPutByIdOp(out, exec, location, it, "put_by_id");
-            printPutByIdCacheStatus(out, location, stubInfos);
+            printPutByIdCacheStatus(out, exec, 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: {
@@ -1897,6 +1936,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             instructions[i + opLength - 1] = profile;
             break;
         }
+        case op_get_by_id_out_of_line:
         case op_get_array_length:
             CRASH();
 
@@ -2377,17 +2417,12 @@ void CodeBlock::propagateTransitions(SlotVisitor& visitor)
         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: {
-                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);
+            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);
                 else
                     allAreMarkedSoFar = false;
                 break;
@@ -2518,32 +2553,36 @@ void CodeBlock::finalizeLLIntInlineCaches()
     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: {
-            StructureID oldStructureID = curInstruction[4].u.structureID;
-            if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID)))
+        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()))
                 break;
             if (Options::verboseOSR())
-                dataLogF("Clearing LLInt property access.\n");
-            curInstruction[4].u.structureID = 0;
+                dataLogF("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
+            curInstruction[4].u.structure.clear();
             curInstruction[5].u.operand = 0;
             break;
-        }
-        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)))
+        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()))
                 break;
-            if (Options::verboseOSR())
-                dataLogF("Clearing LLInt put transition.\n");
-            curInstruction[4].u.structureID = 0;
-            curInstruction[5].u.operand = 0;
-            curInstruction[6].u.structureID = 0;
+            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();
             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:
index 53d234f..e1d1ca9 100644 (file)
@@ -969,7 +969,7 @@ private:
     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&, int location, const StubInfoMap&);
+    void printPutByIdCacheStatus(PrintStream&, ExecState*, 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);
 
index 0a36a83..5b02034 100644 (file)
@@ -70,20 +70,15 @@ GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
     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);
 
-    StructureID structureID = instruction[4].u.structureID;
-    if (!structureID)
+    Structure* structure = instruction[4].u.structure.get();
+    if (!structure)
         return GetByIdStatus(NoInformation, false);
 
-    Structure* structure = vm.heap.structureIDTable().get(structureID);
-
     if (structure->takesSlowPathInDFGForImpureProperty())
         return GetByIdStatus(NoInformation, false);
 
index 173ee97..c20a4f7 100644 (file)
@@ -32,7 +32,6 @@
 #include "BasicBlockLocation.h"
 #include "MacroAssembler.h"
 #include "Opcode.h"
-#include "PutByIdFlags.h"
 #include "SymbolTable.h"
 #include "TypeLocation.h"
 #include "PropertySlot.h"
@@ -76,11 +75,6 @@ struct Instruction {
         u.operand = operand;
     }
 
-    Instruction(PutByIdFlags flags)
-    {
-        u.putByIdFlags = flags;
-    }
-
     Instruction(VM& vm, JSCell* owner, Structure* structure)
     {
         u.structure.clear();
@@ -113,7 +107,6 @@ struct Instruction {
         Opcode opcode;
         int operand;
         WriteBarrierBase<Structure> structure;
-        StructureID structureID;
         WriteBarrierBase<SymbolTable> symbolTable;
         WriteBarrierBase<StructureChain> structureChain;
         WriteBarrierBase<JSCell> jsCell;
@@ -132,7 +125,6 @@ struct Instruction {
         ToThisStatus toThisStatus;
         TypeLocation* location;
         BasicBlockLocation* basicBlockLocation;
-        PutByIdFlags putByIdFlags;
     } u;
         
 private:
diff --git a/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp b/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp
deleted file mode 100644 (file)
index 3fcc70c..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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
-
diff --git a/Source/JavaScriptCore/bytecode/PutByIdFlags.h b/Source/JavaScriptCore/bytecode/PutByIdFlags.h
deleted file mode 100644 (file)
index a766c7d..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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
-
index fb3a3e8..c0afab2 100644 (file)
@@ -66,36 +66,37 @@ PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
     UNUSED_PARAM(profiledBlock);
     UNUSED_PARAM(bytecodeIndex);
     UNUSED_PARAM(uid);
-
-    VM& vm = *profiledBlock->vm();
-    
     Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
 
-    StructureID structureID = instruction[4].u.structureID;
-    if (!structureID)
+    Structure* structure = instruction[4].u.structure.get();
+    if (!structure)
         return PutByIdStatus(NoInformation);
     
-    Structure* structure = vm.heap.structureIDTable().get(structureID);
-
-    StructureID newStructureID = instruction[6].u.structureID;
-    if (!newStructureID) {
+    if (instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id)
+        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_out_of_line)) {
         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[8].u.putByIdFlags & PutByIdIsDirect)) {
+    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)) {
         conditionSet =
             generateConditionsForPropertySetterMissConcurrently(
                 *profiledBlock->vm(), profiledBlock->globalObject(), structure, uid);
index af2eae0..fa514c1 100644 (file)
@@ -36,7 +36,6 @@
 #include "JSCell.h"
 #include "JSString.h"
 #include "ParserModes.h"
-#include "PutByIdFlags.h"
 #include "RegExp.h"
 #include "SpecialPointer.h"
 #include "UnlinkedFunctionExecutable.h"
@@ -98,12 +97,10 @@ struct UnlinkedInstruction {
     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;
 };
 
index f54d8db..a0b012b 100644 (file)
@@ -2103,11 +2103,11 @@ RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& p
     instructions().append(base->index());
     instructions().append(propertyIndex);
     instructions().append(value->index());
-    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
+    instructions().append(0);
+    instructions().append(0);
+    instructions().append(0);
+    instructions().append(0);
+    instructions().append(0);
 
     return value;
 }
@@ -2125,11 +2125,11 @@ RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identif
     instructions().append(base->index());
     instructions().append(propertyIndex);
     instructions().append(value->index());
-    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);
+    instructions().append(0);
+    instructions().append(0);
+    instructions().append(0);
+    instructions().append(0);
+    instructions().append(putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto);
     return value;
 }
 
index 7bd3b37..786b921 100644 (file)
@@ -44,7 +44,6 @@
 #include "JSCInlines.h"
 #include "JSModuleEnvironment.h"
 #include "PreciseJumpTargets.h"
-#include "PutByIdFlags.h"
 #include "PutByIdStatus.h"
 #include "StackAlignment.h"
 #include "StringConstructor.h"
@@ -3514,6 +3513,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
             
         case op_get_by_id:
+        case op_get_by_id_out_of_line:
         case op_get_array_length: {
             SpeculatedType prediction = getPrediction();
             
@@ -3531,11 +3531,16 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
             NEXT_OPCODE(op_get_by_id);
         }
-        case op_put_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: {
             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.putByIdFlags & PutByIdIsDirect;
+            bool direct = currentInstruction[8].u.operand;
 
             PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
                 m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,
index 34d8842..eca20da 100644 (file)
@@ -152,8 +152,14 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc
     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:
index 6a9827c..b1ea289 100644 (file)
@@ -217,6 +217,7 @@ void JIT::privateCompileMainPass()
         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)
@@ -268,6 +269,11 @@ void JIT::privateCompileMainPass()
         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:
@@ -380,6 +386,7 @@ void JIT::privateCompileSlowCases()
         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)
@@ -406,6 +413,11 @@ void JIT::privateCompileSlowCases()
         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)
index 8c5d15d..3319ec4 100644 (file)
@@ -607,7 +607,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
 {
     int baseVReg = currentInstruction[1].u.operand;
     int valueVReg = currentInstruction[3].u.operand;
-    unsigned direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
+    unsigned direct = currentInstruction[8].u.operand;
 
     emitWriteBarrier(baseVReg, valueVReg, ShouldFilterBase);
 
index f8101e8..ea3395c 100644 (file)
@@ -623,7 +623,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     
     int base = currentInstruction[1].u.operand;
     int value = currentInstruction[3].u.operand;
-    int direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
+    int direct = currentInstruction[8].u.operand;
     
     emitWriteBarrier(base, value, ShouldFilterBase);
 
index 445dd5c..a78b39d 100644 (file)
@@ -570,20 +570,20 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
         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.structureID = structure->id();
-            pc[5].u.operand = slot.cachedOffset();
+            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);
+            }
         }
     }
 
@@ -618,7 +618,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
     
     JSValue baseValue = LLINT_OP_C(1).jsValue();
     PutPropertySlot slot(baseValue, codeBlock->isStrictMode(), codeBlock->putByIdContext());
-    if (pc[8].u.putByIdFlags & PutByIdIsDirect)
+    if (pc[8].u.operand)
         asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
     else
         baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
@@ -627,12 +627,6 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
     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();
@@ -640,32 +634,56 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
         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.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);
+                        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);
                         }
                     }
                 }
             } else {
                 structure->didCachePropertyReplacement(vm, slot.cachedOffset());
-                pc[4].u.structureID = structure->id();
-                pc[5].u.operand = 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);
+                }
             }
         }
     }
index 821470c..99fc1d9 100644 (file)
@@ -1323,23 +1323,37 @@ end
 # to take fast path on the new cache. At worst we take slow path, which is what
 # we would have been doing anyway.
 
-_llint_op_get_by_id:
+macro getById(getPropertyStorage)
     traceExecution()
     loadi 8[PC], t0
     loadi 16[PC], t1
     loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
     loadi 20[PC], t2
-    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)
+    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)
 
-.opGetByIdSlow:
-    callSlowPath(_llint_slow_path_get_by_id)
-    dispatch(9)
+    .opGetByIdSlow:
+        callSlowPath(_llint_slow_path_get_by_id)
+        dispatch(9)
+end
+
+_llint_op_get_by_id:
+    getById(withInlineStorage)
+
+
+_llint_op_get_by_id_out_of_line:
+    getById(withOutOfLineStorage)
 
 
 _llint_op_get_array_length:
@@ -1365,57 +1379,100 @@ _llint_op_get_array_length:
     dispatch(9)
 
 
-_llint_op_put_by_id:
+macro putById(getPropertyStorage)
     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)
+
+    .opPutByIdSlow:
+        callSlowPath(_llint_slow_path_put_by_id)
+        dispatch(9)
+end
+
+_llint_op_put_by_id:
+    putById(withInlineStorage)
+
+
+_llint_op_put_by_id_out_of_line:
+    putById(withOutOfLineStorage)
+
+
+macro putByIdTransition(additionalChecks, getPropertyStorage)
+    traceExecution()
+    writeBarrierOnOperand(1)
+    loadi 4[PC], t3
+    loadi 16[PC], t1
     loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
-    loadi JSCell::m_structureID[t0], t2
-    bineq t2, 16[PC], .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)
 
-    # At this point, we have:
-    # t2 -> currentStructureID
-    # t0 -> object base
+    .opPutByIdSlow:
+        callSlowPath(_llint_slow_path_put_by_id)
+        dispatch(9)
+end
 
-    loadi 24[PC], t1
+macro noAdditionalChecks(oldStructure, scratch, slowPath)
+end
 
-    btiz t1, .opPutByIdNotTransition
+macro structureChainChecks(oldStructure, scratch, slowPath)
+    const protoCell = oldStructure   # Reusing the oldStructure register for the proto
+
+    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
 
-    # 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
+_llint_op_put_by_id_transition_direct:
+    putByIdTransition(noAdditionalChecks, withInlineStorage)
 
-    loadp StructureChain::m_vector[t3], t3
-    assert(macro (ok) btpnz t3, ok 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
+_llint_op_put_by_id_transition_direct_out_of_line:
+    putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
 
-.opPutByIdTransitionChainDone:
-    loadi 24[PC], t1
 
-.opPutByIdTransitionDirect:
-    storei t1, JSCell::m_structureID[t0]
+_llint_op_put_by_id_transition_normal:
+    putByIdTransition(structureChainChecks, withInlineStorage)
 
-.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)
 
-.opPutByIdSlow:
-    callSlowPath(_llint_slow_path_put_by_id)
-    dispatch(9)
+_llint_op_put_by_id_transition_normal_out_of_line:
+    putByIdTransition(structureChainChecks, withOutOfLineStorage)
 
 
 _llint_op_get_by_val:
index 966a7e4..564ebb0 100644 (file)
@@ -468,16 +468,15 @@ macro valueProfile(value, operand, scratch)
     storeq value, ValueProfile::m_buckets[scratch]
 end
 
-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
+macro loadStructure(cell, structure)
 end
 
 macro loadStructureWithScratch(cell, structure, scratch)
+    loadp CodeBlock[cfr], scratch
+    loadp CodeBlock::m_vm[scratch], scratch
+    loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
     loadi JSCell::m_structureID[cell], structure
-    structureIDToStructureWithScratch(structure, scratch)
+    loadp [scratch, structure, 8], structure
 end
 
 macro loadStructureAndClobberFirstArg(cell, structure)
@@ -1205,23 +1204,41 @@ macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value
     storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
 end
 
-_llint_op_get_by_id:
+macro getById(getPropertyStorage)
     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)
-    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)
+    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
 
-.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:
@@ -1247,65 +1264,97 @@ _llint_op_get_array_length:
     dispatch(9)
 
 
-_llint_op_put_by_id:
+macro putById(getPropertyStorage)
     traceExecution()
     writeBarrierOnOperands(1, 3)
     loadisFromInstruction(1, t3)
     loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
-    loadi JSCell::m_structureID[t0], t2
-    loadisFromInstruction(4, t1)
-    bineq t2, t1, .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
 
-    # At this point, we have:
-    # t1, t2 -> current structure ID
-    # t0 -> object base
+_llint_op_put_by_id:
+    putById(withInlineStorage)
 
-    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
-
-    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
+.opPutByIdSlow:
+    callSlowPath(_llint_slow_path_put_by_id)
+    dispatch(9)
 
-.opPutByIdTransitionChainDone:
-    # Reload the new structure, since we clobbered it above.
-    loadisFromInstruction(6, t1)
 
-.opPutByIdTransitionDirect:
-    storei t1, JSCell::m_structureID[t0]
+_llint_op_put_by_id_out_of_line:
+    putById(withOutOfLineStorage)
 
-.opPutByIdNotTransition:
-    # The only thing live right now is t0, which holds the base.
-    loadisFromInstruction(3, t1)
-    loadConstantOrVariable(t1, t2)
+
+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)
-    storePropertyAtVariableOffset(t1, t0, t2)
-    dispatch(9)
+    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
 
-.opPutByIdSlow:
-    callSlowPath(_llint_slow_path_put_by_id)
-    dispatch(9)
+macro noAdditionalChecks(oldStructure, scratch, scratch2)
+end
+
+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
+
+_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: