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)