| Differences between
and this patch
- Source/JavaScriptCore/ChangeLog +77 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2015-09-13  Filip Pizlo  <fpizlo@apple.com>
2
3
        LLInt get/put inline caches shouldn't use tons of opcodes
4
        https://bugs.webkit.org/show_bug.cgi?id=149106
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Our LLInt get/put inline caches currently use separate opcodes to reduce branching. For
9
        example, instead of having get_by_id branch on the kind of offset (inline or
10
        out-of-line), we have two get_by_id instructions: get_by_id and get_by_id_out_of_line.
11
        But the problem with this approach is that it doesn't scale. In the property type
12
        inference work (https://bugs.webkit.org/show_bug.cgi?id=148610), we need each kind of put
13
        inline cache to support 11 different kinds of type checks. It seemed ridiculous to add 60
14
        new put_by_id opcodes (there are currently 6 variants of put_by_id, so after adding type
15
        checks, we'd have 6 * 11 = 66 variants of put_by_id).
16
17
        So, this patch completely changes the strategy to mostly using branching inside the
18
        opcode implementation. It's unlikely to have a performance effect. For example, the long
19
        road to generational GC caused a seemingly prohibitive regression in LLInt inline caches,
20
        and yet nobody noticed. The regression was because the inline cache was in terms of the
21
        structure, not the structure ID, so the code was doing a structure ID table lookup. If we
22
        didn't notice that, then we probably won't notice a couple new branches. (Also, this
23
        patch fixes that regression - the code no longer does such lookups except in the one
24
        unavoidable case in put_by_id transition chain checking.)
25
26
        This patch also turns the isDirect operand of put_by_id into a flags field. I will use
27
        this flags field to encode the desired type check in bug 148610.
28
29
        * CMakeLists.txt:
30
        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
31
        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
32
        * JavaScriptCore.xcodeproj/project.pbxproj:
33
        * bytecode/BytecodeList.json:
34
        * bytecode/BytecodeUseDef.h:
35
        (JSC::computeUsesForBytecodeOffset):
36
        (JSC::computeDefsForBytecodeOffset):
37
        * bytecode/CodeBlock.cpp:
38
        (JSC::CodeBlock::printGetByIdOp):
39
        (JSC::CodeBlock::printGetByIdCacheStatus):
40
        (JSC::CodeBlock::printPutByIdCacheStatus):
41
        (JSC::CodeBlock::dumpBytecode):
42
        (JSC::CodeBlock::CodeBlock):
43
        (JSC::CodeBlock::propagateTransitions):
44
        (JSC::CodeBlock::finalizeLLIntInlineCaches):
45
        * bytecode/CodeBlock.h:
46
        * bytecode/GetByIdStatus.cpp:
47
        (JSC::GetByIdStatus::computeFromLLInt):
48
        * bytecode/Instruction.h:
49
        (JSC::Instruction::Instruction):
50
        * bytecode/PutByIdFlags.cpp: Added.
51
        (WTF::printInternal):
52
        * bytecode/PutByIdFlags.h: Added.
53
        * bytecode/PutByIdStatus.cpp:
54
        (JSC::PutByIdStatus::computeFromLLInt):
55
        * bytecode/UnlinkedCodeBlock.h:
56
        (JSC::UnlinkedInstruction::UnlinkedInstruction):
57
        * bytecompiler/BytecodeGenerator.cpp:
58
        (JSC::BytecodeGenerator::emitPutById):
59
        (JSC::BytecodeGenerator::emitDirectPutById):
60
        * dfg/DFGAbstractInterpreterInlines.h:
61
        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
62
        * dfg/DFGByteCodeParser.cpp:
63
        (JSC::DFG::ByteCodeParser::parseBlock):
64
        * dfg/DFGCapabilities.cpp:
65
        (JSC::DFG::capabilityLevel):
66
        * jit/JIT.cpp:
67
        (JSC::JIT::privateCompileMainPass):
68
        (JSC::JIT::privateCompileSlowCases):
69
        * jit/JITPropertyAccess.cpp:
70
        (JSC::JIT::emit_op_put_by_id):
71
        * jit/JITPropertyAccess32_64.cpp:
72
        (JSC::JIT::emit_op_put_by_id):
73
        * llint/LLIntSlowPaths.cpp:
74
        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
75
        * llint/LowLevelInterpreter32_64.asm:
76
        * llint/LowLevelInterpreter64.asm:
77
1
2015-09-11  Filip Pizlo  <fpizlo@apple.com>
78
2015-09-11  Filip Pizlo  <fpizlo@apple.com>
2
79
3
        REGRESSION(r189585): run-perf-tests Speedometer fails with a console error
80
        REGRESSION(r189585): run-perf-tests Speedometer fails with a console error
- Source/JavaScriptCore/CMakeLists.txt +1 lines
Lines 107-112 set(JavaScriptCore_SOURCES Source/JavaScriptCore/CMakeLists.txt_sec1
107
    bytecode/PolymorphicAccess.cpp
107
    bytecode/PolymorphicAccess.cpp
108
    bytecode/PreciseJumpTargets.cpp
108
    bytecode/PreciseJumpTargets.cpp
109
    bytecode/PropertyCondition.cpp
109
    bytecode/PropertyCondition.cpp
110
    bytecode/PutByIdFlags.cpp
110
    bytecode/PutByIdStatus.cpp
111
    bytecode/PutByIdStatus.cpp
111
    bytecode/PutByIdVariant.cpp
112
    bytecode/PutByIdVariant.cpp
112
    bytecode/ReduceWhitespace.cpp
113
    bytecode/ReduceWhitespace.cpp
- Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj +2 lines
Lines 346-351 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec1
346
    <ClCompile Include="..\bytecode\PolymorphicAccess.cpp" />
346
    <ClCompile Include="..\bytecode\PolymorphicAccess.cpp" />
347
    <ClCompile Include="..\bytecode\PreciseJumpTargets.cpp" />
347
    <ClCompile Include="..\bytecode\PreciseJumpTargets.cpp" />
348
    <ClCompile Include="..\bytecode\PropertyCondition.cpp" />
348
    <ClCompile Include="..\bytecode\PropertyCondition.cpp" />
349
    <ClCompile Include="..\bytecode\PutByIdFlags.cpp" />
349
    <ClCompile Include="..\bytecode\PutByIdStatus.cpp" />
350
    <ClCompile Include="..\bytecode\PutByIdStatus.cpp" />
350
    <ClCompile Include="..\bytecode\PutByIdVariant.cpp" />
351
    <ClCompile Include="..\bytecode\PutByIdVariant.cpp" />
351
    <ClCompile Include="..\bytecode\ReduceWhitespace.cpp" />
352
    <ClCompile Include="..\bytecode\ReduceWhitespace.cpp" />
Lines 1046-1051 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj_sec2
1046
    <ClInclude Include="..\bytecode\PolymorphicAccess.h" />
1047
    <ClInclude Include="..\bytecode\PolymorphicAccess.h" />
1047
    <ClInclude Include="..\bytecode\PreciseJumpTargets.h" />
1048
    <ClInclude Include="..\bytecode\PreciseJumpTargets.h" />
1048
    <ClInclude Include="..\bytecode\PropertyCondition.h" />
1049
    <ClInclude Include="..\bytecode\PropertyCondition.h" />
1050
    <ClInclude Include="..\bytecode\PutByIdFlags.h" />
1049
    <ClInclude Include="..\bytecode\PutByIdStatus.h" />
1051
    <ClInclude Include="..\bytecode\PutByIdStatus.h" />
1050
    <ClInclude Include="..\bytecode\PutByIdVariant.h" />
1052
    <ClInclude Include="..\bytecode\PutByIdVariant.h" />
1051
    <ClInclude Include="..\bytecode\PutKind.h" />
1053
    <ClInclude Include="..\bytecode\PutKind.h" />
- Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters +6 lines
Lines 201-206 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters_sec1
201
    <ClCompile Include="..\bytecode\PolymorphicAccess.cpp">
201
    <ClCompile Include="..\bytecode\PolymorphicAccess.cpp">
202
      <Filter>bytecode</Filter>
202
      <Filter>bytecode</Filter>
203
    </ClCompile>
203
    </ClCompile>
204
    <ClCompile Include="..\bytecode\PutByIdFlags.cpp">
205
      <Filter>bytecode</Filter>
206
    </ClCompile>
204
    <ClCompile Include="..\bytecode\PutByIdStatus.cpp">
207
    <ClCompile Include="..\bytecode\PutByIdStatus.cpp">
205
      <Filter>bytecode</Filter>
208
      <Filter>bytecode</Filter>
206
    </ClCompile>
209
    </ClCompile>
Lines 2094-2099 Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters_sec2
2094
    <ClInclude Include="..\bytecode\PolymorphicAccess.h">
2097
    <ClInclude Include="..\bytecode\PolymorphicAccess.h">
2095
      <Filter>bytecode</Filter>
2098
      <Filter>bytecode</Filter>
2096
    </ClInclude>
2099
    </ClInclude>
2100
    <ClInclude Include="..\bytecode\PutByIdFlags.h">
2101
      <Filter>bytecode</Filter>
2102
    </ClInclude>
2097
    <ClInclude Include="..\bytecode\PutByIdStatus.h">
2103
    <ClInclude Include="..\bytecode\PutByIdStatus.h">
2098
      <Filter>bytecode</Filter>
2104
      <Filter>bytecode</Filter>
2099
    </ClInclude>
2105
    </ClInclude>
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +8 lines
Lines 105-110 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
105
		0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */; };
105
		0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */; };
106
		0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */; settings = {ATTRIBUTES = (Private, ); }; };
106
		0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */; settings = {ATTRIBUTES = (Private, ); }; };
107
		0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */; };
107
		0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */; };
108
		0F15CD221BA5F9860031FFD3 /* PutByIdFlags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */; };
109
		0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */; settings = {ATTRIBUTES = (Private, ); }; };
108
		0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
110
		0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
109
		0F1725FF1B48719A00AC3A55 /* DFGMinifiedGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */; };
111
		0F1725FF1B48719A00AC3A55 /* DFGMinifiedGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */; };
110
		0F18D3CF1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */; };
112
		0F18D3CF1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */; };
Lines 1932-1937 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
1932
		0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerProfiledBytecodes.cpp; path = profiler/ProfilerProfiledBytecodes.cpp; sourceTree = "<group>"; };
1934
		0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerProfiledBytecodes.cpp; path = profiler/ProfilerProfiledBytecodes.cpp; sourceTree = "<group>"; };
1933
		0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerProfiledBytecodes.h; path = profiler/ProfilerProfiledBytecodes.h; sourceTree = "<group>"; };
1935
		0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerProfiledBytecodes.h; path = profiler/ProfilerProfiledBytecodes.h; sourceTree = "<group>"; };
1934
		0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexingType.cpp; sourceTree = "<group>"; };
1936
		0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexingType.cpp; sourceTree = "<group>"; };
1937
		0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdFlags.cpp; sourceTree = "<group>"; };
1938
		0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdFlags.h; sourceTree = "<group>"; };
1935
		0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
1939
		0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; };
1936
		0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMinifiedGraph.cpp; path = dfg/DFGMinifiedGraph.cpp; sourceTree = "<group>"; };
1940
		0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMinifiedGraph.cpp; path = dfg/DFGMinifiedGraph.cpp; sourceTree = "<group>"; };
1937
		0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAdaptiveStructureWatchpoint.cpp; path = dfg/DFGAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; };
1941
		0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAdaptiveStructureWatchpoint.cpp; path = dfg/DFGAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; };
Lines 5600-5605 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
5600
				0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */,
5604
				0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */,
5601
				0FD3E4071B618B6600C80E1E /* PropertyCondition.cpp */,
5605
				0FD3E4071B618B6600C80E1E /* PropertyCondition.cpp */,
5602
				0FD3E4081B618B6600C80E1E /* PropertyCondition.h */,
5606
				0FD3E4081B618B6600C80E1E /* PropertyCondition.h */,
5607
				0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */,
5608
				0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */,
5603
				0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
5609
				0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
5604
				0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
5610
				0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
5605
				0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */,
5611
				0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */,
Lines 6740-6745 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
6740
				0F682FB319BCB36400FA3BAD /* DFGSSACalculator.h in Headers */,
6746
				0F682FB319BCB36400FA3BAD /* DFGSSACalculator.h in Headers */,
6741
				0FB7F39D15ED8E4600F167B2 /* Reject.h in Headers */,
6747
				0FB7F39D15ED8E4600F167B2 /* Reject.h in Headers */,
6742
				0F2D4DEA19832DAC007D4B19 /* TypeLocation.h in Headers */,
6748
				0F2D4DEA19832DAC007D4B19 /* TypeLocation.h in Headers */,
6749
				0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */,
6743
				A5BA15E8182340B300A82E69 /* RemoteInspector.h in Headers */,
6750
				A5BA15E8182340B300A82E69 /* RemoteInspector.h in Headers */,
6744
				A5BA15EA182340B400A82E69 /* RemoteInspectorConstants.h in Headers */,
6751
				A5BA15EA182340B400A82E69 /* RemoteInspectorConstants.h in Headers */,
6745
				A5BA15F0182345AF00A82E69 /* RemoteInspectorDebuggable.h in Headers */,
6752
				A5BA15F0182345AF00A82E69 /* RemoteInspectorDebuggable.h in Headers */,
Lines 7472-7477 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
7472
				0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
7479
				0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
7473
				0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
7480
				0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
7474
				0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
7481
				0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
7482
				0F15CD221BA5F9860031FFD3 /* PutByIdFlags.cpp in Sources */,
7475
				C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */,
7483
				C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */,
7476
				0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
7484
				0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
7477
				C2981FD817BAEE4B00A3BC98 /* DFGDesiredWeakReferences.cpp in Sources */,
7485
				C2981FD817BAEE4B00A3BC98 /* DFGDesiredWeakReferences.cpp in Sources */,
- Source/JavaScriptCore/bytecode/BytecodeList.json -6 lines
Lines 57-70 Source/JavaScriptCore/bytecode/BytecodeList.json_sec1
57
            { "name" : "op_is_function", "length" : 3 },
57
            { "name" : "op_is_function", "length" : 3 },
58
            { "name" : "op_in", "length" : 4 },
58
            { "name" : "op_in", "length" : 4 },
59
            { "name" : "op_get_by_id", "length" : 9  },
59
            { "name" : "op_get_by_id", "length" : 9  },
60
            { "name" : "op_get_by_id_out_of_line", "length" : 9  },
61
            { "name" : "op_get_array_length", "length" : 9 },
60
            { "name" : "op_get_array_length", "length" : 9 },
62
            { "name" : "op_put_by_id", "length" : 9 },
61
            { "name" : "op_put_by_id", "length" : 9 },
63
            { "name" : "op_put_by_id_out_of_line", "length" : 9 },
64
            { "name" : "op_put_by_id_transition_direct", "length" : 9 },
65
            { "name" : "op_put_by_id_transition_direct_out_of_line", "length" : 9 },
66
            { "name" : "op_put_by_id_transition_normal", "length" : 9 },
67
            { "name" : "op_put_by_id_transition_normal_out_of_line", "length" : 9 },
68
            { "name" : "op_del_by_id", "length" : 4 },
62
            { "name" : "op_del_by_id", "length" : 4 },
69
            { "name" : "op_get_by_val", "length" : 6 },
63
            { "name" : "op_get_by_val", "length" : 6 },
70
            { "name" : "op_put_by_val", "length" : 5 },
64
            { "name" : "op_put_by_val", "length" : 5 },
- Source/JavaScriptCore/bytecode/BytecodeUseDef.h -12 lines
Lines 93-103 void computeUsesForBytecodeOffset( Source/JavaScriptCore/bytecode/BytecodeUseDef.h_sec1
93
        return;
93
        return;
94
    }
94
    }
95
    case op_put_by_index:
95
    case op_put_by_index:
96
    case op_put_by_id_transition_direct:
97
    case op_put_by_id_transition_direct_out_of_line:
98
    case op_put_by_id_transition_normal:
99
    case op_put_by_id_transition_normal_out_of_line:
100
    case op_put_by_id_out_of_line:
101
    case op_put_by_id:
96
    case op_put_by_id:
102
    case op_put_to_scope:
97
    case op_put_to_scope:
103
    case op_put_to_arguments: {
98
    case op_put_to_arguments: {
Lines 134-140 void computeUsesForBytecodeOffset( Source/JavaScriptCore/bytecode/BytecodeUseDef.h_sec2
134
    case op_get_from_scope:
129
    case op_get_from_scope:
135
    case op_to_primitive:
130
    case op_to_primitive:
136
    case op_get_by_id:
131
    case op_get_by_id:
137
    case op_get_by_id_out_of_line:
138
    case op_get_array_length:
132
    case op_get_array_length:
139
    case op_typeof:
133
    case op_typeof:
140
    case op_is_undefined:
134
    case op_is_undefined:
Lines 277-287 void computeDefsForBytecodeOffset(CodeBl Source/JavaScriptCore/bytecode/BytecodeUseDef.h_sec3
277
    case op_switch_char:
271
    case op_switch_char:
278
    case op_switch_string:
272
    case op_switch_string:
279
    case op_put_by_id:
273
    case op_put_by_id:
280
    case op_put_by_id_out_of_line:
281
    case op_put_by_id_transition_direct:
282
    case op_put_by_id_transition_direct_out_of_line:
283
    case op_put_by_id_transition_normal:
284
    case op_put_by_id_transition_normal_out_of_line:
285
    case op_put_getter_by_id:
274
    case op_put_getter_by_id:
286
    case op_put_setter_by_id:
275
    case op_put_setter_by_id:
287
    case op_put_getter_setter:
276
    case op_put_getter_setter:
Lines 328-334 void computeDefsForBytecodeOffset(CodeBl Source/JavaScriptCore/bytecode/BytecodeUseDef.h_sec4
328
    case op_call_eval:
317
    case op_call_eval:
329
    case op_construct:
318
    case op_construct:
330
    case op_get_by_id:
319
    case op_get_by_id:
331
    case op_get_by_id_out_of_line:
332
    case op_get_array_length:
320
    case op_get_array_length:
333
    case op_check_has_instance:
321
    case op_check_has_instance:
334
    case op_instanceof:
322
    case op_instanceof:
- Source/JavaScriptCore/bytecode/CodeBlock.cpp -85 / +46 lines
Lines 273-281 void CodeBlock::printGetByIdOp(PrintStre Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec1
273
    case op_get_by_id:
273
    case op_get_by_id:
274
        op = "get_by_id";
274
        op = "get_by_id";
275
        break;
275
        break;
276
    case op_get_by_id_out_of_line:
277
        op = "get_by_id_out_of_line";
278
        break;
279
    case op_get_array_length:
276
    case op_get_array_length:
280
        op = "array_length";
277
        op = "array_length";
281
        break;
278
        break;
Lines 331-337 void CodeBlock::printGetByIdCacheStatus( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec2
331
    
328
    
332
    if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
329
    if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
333
        out.printf(" llint(array_length)");
330
        out.printf(" llint(array_length)");
334
    else if (Structure* structure = instruction[4].u.structure.get()) {
331
    else if (StructureID structureID = instruction[4].u.structureID) {
332
        Structure* structure = m_vm->heap.structureIDTable().get(structureID);
335
        out.printf(" llint(");
333
        out.printf(" llint(");
336
        dumpStructure(out, "struct", structure, ident);
334
        dumpStructure(out, "struct", structure, ident);
337
        out.printf(")");
335
        out.printf(")");
Lines 382-423 void CodeBlock::printGetByIdCacheStatus( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec3
382
#endif
380
#endif
383
}
381
}
384
382
385
void CodeBlock::printPutByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
383
void CodeBlock::printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
386
{
384
{
387
    Instruction* instruction = instructions().begin() + location;
385
    Instruction* instruction = instructions().begin() + location;
388
386
389
    const Identifier& ident = identifier(instruction[2].u.operand);
387
    const Identifier& ident = identifier(instruction[2].u.operand);
390
    
388
    
391
    UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
389
    UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
390
391
    out.print(", ", instruction[8].u.putByIdFlags);
392
    
392
    
393
    if (Structure* structure = instruction[4].u.structure.get()) {
393
    if (StructureID structureID = instruction[4].u.structureID) {
394
        switch (exec->interpreter()->getOpcodeID(instruction[0].u.opcode)) {
394
        Structure* structure = m_vm->heap.structureIDTable().get(structureID);
395
        case op_put_by_id:
395
        out.print(" llint(");
396
        case op_put_by_id_out_of_line:
396
        if (StructureID newStructureID = instruction[6].u.structureID) {
397
            out.print(" llint(");
397
            Structure* newStructure = m_vm->heap.structureIDTable().get(newStructureID);
398
            dumpStructure(out, "struct", structure, ident);
399
            out.print(")");
400
            break;
401
            
402
        case op_put_by_id_transition_direct:
403
        case op_put_by_id_transition_normal:
404
        case op_put_by_id_transition_direct_out_of_line:
405
        case op_put_by_id_transition_normal_out_of_line:
406
            out.print(" llint(");
407
            dumpStructure(out, "prev", structure, ident);
398
            dumpStructure(out, "prev", structure, ident);
408
            out.print(", ");
399
            out.print(", ");
409
            dumpStructure(out, "next", instruction[6].u.structure.get(), ident);
400
            dumpStructure(out, "next", newStructure, ident);
410
            if (StructureChain* chain = instruction[7].u.structureChain.get()) {
401
            if (StructureChain* chain = instruction[7].u.structureChain.get()) {
411
                out.print(", ");
402
                out.print(", ");
412
                dumpChain(out, chain, ident);
403
                dumpChain(out, chain, ident);
413
            }
404
            }
414
            out.print(")");
405
        } else
415
            break;
406
            dumpStructure(out, "struct", structure, ident);
416
            
407
        out.print(")");
417
        default:
418
            out.print(" llint(unknown)");
419
            break;
420
        }
421
    }
408
    }
422
409
423
#if ENABLE(JIT)
410
#if ENABLE(JIT)
Lines 1001-1007 void CodeBlock::dumpBytecode( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec4
1001
            break;
988
            break;
1002
        }
989
        }
1003
        case op_get_by_id:
990
        case op_get_by_id:
1004
        case op_get_by_id_out_of_line:
1005
        case op_get_array_length: {
991
        case op_get_array_length: {
1006
            printGetByIdOp(out, exec, location, it);
992
            printGetByIdOp(out, exec, location, it);
1007
            printGetByIdCacheStatus(out, exec, location, stubInfos);
993
            printGetByIdCacheStatus(out, exec, location, stubInfos);
Lines 1010-1041 void CodeBlock::dumpBytecode( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec5
1010
        }
996
        }
1011
        case op_put_by_id: {
997
        case op_put_by_id: {
1012
            printPutByIdOp(out, exec, location, it, "put_by_id");
998
            printPutByIdOp(out, exec, location, it, "put_by_id");
1013
            printPutByIdCacheStatus(out, exec, location, stubInfos);
999
            printPutByIdCacheStatus(out, location, stubInfos);
1014
            break;
1015
        }
1016
        case op_put_by_id_out_of_line: {
1017
            printPutByIdOp(out, exec, location, it, "put_by_id_out_of_line");
1018
            printPutByIdCacheStatus(out, exec, location, stubInfos);
1019
            break;
1020
        }
1021
        case op_put_by_id_transition_direct: {
1022
            printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct");
1023
            printPutByIdCacheStatus(out, exec, location, stubInfos);
1024
            break;
1025
        }
1026
        case op_put_by_id_transition_direct_out_of_line: {
1027
            printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct_out_of_line");
1028
            printPutByIdCacheStatus(out, exec, location, stubInfos);
1029
            break;
1030
        }
1031
        case op_put_by_id_transition_normal: {
1032
            printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal");
1033
            printPutByIdCacheStatus(out, exec, location, stubInfos);
1034
            break;
1035
        }
1036
        case op_put_by_id_transition_normal_out_of_line: {
1037
            printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal_out_of_line");
1038
            printPutByIdCacheStatus(out, exec, location, stubInfos);
1039
            break;
1000
            break;
1040
        }
1001
        }
1041
        case op_put_getter_by_id: {
1002
        case op_put_getter_by_id: {
Lines 1936-1942 CodeBlock::CodeBlock(ScriptExecutable* o Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec6
1936
            instructions[i + opLength - 1] = profile;
1897
            instructions[i + opLength - 1] = profile;
1937
            break;
1898
            break;
1938
        }
1899
        }
1939
        case op_get_by_id_out_of_line:
1940
        case op_get_array_length:
1900
        case op_get_array_length:
1941
            CRASH();
1901
            CRASH();
1942
1902
Lines 2417-2428 void CodeBlock::propagateTransitions(Slo Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec7
2417
        for (size_t i = 0; i < propertyAccessInstructions.size(); ++i) {
2377
        for (size_t i = 0; i < propertyAccessInstructions.size(); ++i) {
2418
            Instruction* instruction = &instructions()[propertyAccessInstructions[i]];
2378
            Instruction* instruction = &instructions()[propertyAccessInstructions[i]];
2419
            switch (interpreter->getOpcodeID(instruction[0].u.opcode)) {
2379
            switch (interpreter->getOpcodeID(instruction[0].u.opcode)) {
2420
            case op_put_by_id_transition_direct:
2380
            case op_put_by_id: {
2421
            case op_put_by_id_transition_normal:
2381
                StructureID oldStructureID = instruction[4].u.structureID;
2422
            case op_put_by_id_transition_direct_out_of_line:
2382
                StructureID newStructureID = instruction[6].u.structureID;
2423
            case op_put_by_id_transition_normal_out_of_line: {
2383
                if (!oldStructureID || !newStructureID)
2424
                if (Heap::isMarked(instruction[4].u.structure.get()))
2384
                    break;
2425
                    visitor.append(&instruction[6].u.structure);
2385
                Structure* oldStructure =
2386
                    m_vm->heap.structureIDTable().get(oldStructureID);
2387
                Structure* newStructure =
2388
                    m_vm->heap.structureIDTable().get(newStructureID);
2389
                if (Heap::isMarked(oldStructure))
2390
                    visitor.appendUnbarrieredReadOnlyPointer(newStructure);
2426
                else
2391
                else
2427
                    allAreMarkedSoFar = false;
2392
                    allAreMarkedSoFar = false;
2428
                break;
2393
                break;
Lines 2553-2588 void CodeBlock::finalizeLLIntInlineCache Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec8
2553
    for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
2518
    for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
2554
        Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
2519
        Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
2555
        switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
2520
        switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
2556
        case op_get_by_id:
2521
        case op_get_by_id: {
2557
        case op_get_by_id_out_of_line:
2522
            StructureID oldStructureID = curInstruction[4].u.structureID;
2558
        case op_put_by_id:
2523
            if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID)))
2559
        case op_put_by_id_out_of_line:
2560
            if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
2561
                break;
2524
                break;
2562
            if (Options::verboseOSR())
2525
            if (Options::verboseOSR())
2563
                dataLogF("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
2526
                dataLogF("Clearing LLInt property access.\n");
2564
            curInstruction[4].u.structure.clear();
2527
            curInstruction[4].u.structureID = 0;
2565
            curInstruction[5].u.operand = 0;
2528
            curInstruction[5].u.operand = 0;
2566
            break;
2529
            break;
2567
        case op_put_by_id_transition_direct:
2530
        }
2568
        case op_put_by_id_transition_normal:
2531
        case op_put_by_id: {
2569
        case op_put_by_id_transition_direct_out_of_line:
2532
            StructureID oldStructureID = curInstruction[4].u.structureID;
2570
        case op_put_by_id_transition_normal_out_of_line:
2533
            StructureID newStructureID = curInstruction[6].u.structureID;
2571
            if (Heap::isMarked(curInstruction[4].u.structure.get())
2534
            StructureChain* chain = curInstruction[7].u.structureChain.get();
2572
                && Heap::isMarked(curInstruction[6].u.structure.get())
2535
            if ((!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID))) &&
2573
                && Heap::isMarked(curInstruction[7].u.structureChain.get()))
2536
                (!newStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(newStructureID))) &&
2574
                break;
2537
                (!chain || Heap::isMarked(chain)))
2575
            if (Options::verboseOSR()) {
2538
                break;
2576
                dataLogF("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
2539
            if (Options::verboseOSR())
2577
                    curInstruction[4].u.structure.get(),
2540
                dataLogF("Clearing LLInt put transition.\n");
2578
                    curInstruction[6].u.structure.get(),
2541
            curInstruction[4].u.structureID = 0;
2579
                    curInstruction[7].u.structureChain.get());
2542
            curInstruction[5].u.operand = 0;
2580
            }
2543
            curInstruction[6].u.structureID = 0;
2581
            curInstruction[4].u.structure.clear();
2582
            curInstruction[6].u.structure.clear();
2583
            curInstruction[7].u.structureChain.clear();
2544
            curInstruction[7].u.structureChain.clear();
2584
            curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id);
2585
            break;
2545
            break;
2546
        }
2586
        case op_get_array_length:
2547
        case op_get_array_length:
2587
            break;
2548
            break;
2588
        case op_to_this:
2549
        case op_to_this:
- Source/JavaScriptCore/bytecode/CodeBlock.h -1 / +1 lines
Lines 969-975 private: Source/JavaScriptCore/bytecode/CodeBlock.h_sec1
969
    enum CacheDumpMode { DumpCaches, DontDumpCaches };
969
    enum CacheDumpMode { DumpCaches, DontDumpCaches };
970
    void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&);
970
    void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&);
971
    void printPutByIdOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
971
    void printPutByIdOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
972
    void printPutByIdCacheStatus(PrintStream&, ExecState*, int location, const StubInfoMap&);
972
    void printPutByIdCacheStatus(PrintStream&, int location, const StubInfoMap&);
973
    void printLocationAndOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
973
    void printLocationAndOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
974
    void printLocationOpAndRegisterOperand(PrintStream&, ExecState*, int location, const Instruction*& it, const char* op, int operand);
974
    void printLocationOpAndRegisterOperand(PrintStream&, ExecState*, int location, const Instruction*& it, const char* op, int operand);
975
975
- Source/JavaScriptCore/bytecode/GetByIdStatus.cpp -2 / +7 lines
Lines 70-84 GetByIdStatus GetByIdStatus::computeFrom Source/JavaScriptCore/bytecode/GetByIdStatus.cpp_sec1
70
    UNUSED_PARAM(profiledBlock);
70
    UNUSED_PARAM(profiledBlock);
71
    UNUSED_PARAM(bytecodeIndex);
71
    UNUSED_PARAM(bytecodeIndex);
72
    UNUSED_PARAM(uid);
72
    UNUSED_PARAM(uid);
73
74
    VM& vm = *profiledBlock->vm();
75
    
73
    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
76
    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
74
    
77
    
75
    if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length))
78
    if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length))
76
        return GetByIdStatus(NoInformation, false);
79
        return GetByIdStatus(NoInformation, false);
77
80
78
    Structure* structure = instruction[4].u.structure.get();
81
    StructureID structureID = instruction[4].u.structureID;
79
    if (!structure)
82
    if (!structureID)
80
        return GetByIdStatus(NoInformation, false);
83
        return GetByIdStatus(NoInformation, false);
81
84
85
    Structure* structure = vm.heap.structureIDTable().get(structureID);
86
82
    if (structure->takesSlowPathInDFGForImpureProperty())
87
    if (structure->takesSlowPathInDFGForImpureProperty())
83
        return GetByIdStatus(NoInformation, false);
88
        return GetByIdStatus(NoInformation, false);
84
89
- Source/JavaScriptCore/bytecode/Instruction.h +8 lines
Lines 32-37 Source/JavaScriptCore/bytecode/Instruction.h_sec1
32
#include "BasicBlockLocation.h"
32
#include "BasicBlockLocation.h"
33
#include "MacroAssembler.h"
33
#include "MacroAssembler.h"
34
#include "Opcode.h"
34
#include "Opcode.h"
35
#include "PutByIdFlags.h"
35
#include "SymbolTable.h"
36
#include "SymbolTable.h"
36
#include "TypeLocation.h"
37
#include "TypeLocation.h"
37
#include "PropertySlot.h"
38
#include "PropertySlot.h"
Lines 75-80 struct Instruction { Source/JavaScriptCore/bytecode/Instruction.h_sec2
75
        u.operand = operand;
76
        u.operand = operand;
76
    }
77
    }
77
78
79
    Instruction(PutByIdFlags flags)
80
    {
81
        u.putByIdFlags = flags;
82
    }
83
78
    Instruction(VM& vm, JSCell* owner, Structure* structure)
84
    Instruction(VM& vm, JSCell* owner, Structure* structure)
79
    {
85
    {
80
        u.structure.clear();
86
        u.structure.clear();
Lines 107-112 struct Instruction { Source/JavaScriptCore/bytecode/Instruction.h_sec3
107
        Opcode opcode;
113
        Opcode opcode;
108
        int operand;
114
        int operand;
109
        WriteBarrierBase<Structure> structure;
115
        WriteBarrierBase<Structure> structure;
116
        StructureID structureID;
110
        WriteBarrierBase<SymbolTable> symbolTable;
117
        WriteBarrierBase<SymbolTable> symbolTable;
111
        WriteBarrierBase<StructureChain> structureChain;
118
        WriteBarrierBase<StructureChain> structureChain;
112
        WriteBarrierBase<JSCell> jsCell;
119
        WriteBarrierBase<JSCell> jsCell;
Lines 125-130 struct Instruction { Source/JavaScriptCore/bytecode/Instruction.h_sec4
125
        ToThisStatus toThisStatus;
132
        ToThisStatus toThisStatus;
126
        TypeLocation* location;
133
        TypeLocation* location;
127
        BasicBlockLocation* basicBlockLocation;
134
        BasicBlockLocation* basicBlockLocation;
135
        PutByIdFlags putByIdFlags;
128
    } u;
136
    } u;
129
        
137
        
130
private:
138
private:
- Source/JavaScriptCore/bytecode/PutByIdFlags.cpp +51 lines
Line 0 Source/JavaScriptCore/bytecode/PutByIdFlags.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "PutByIdFlags.h"
28
29
#include <wtf/CommaPrinter.h>
30
#include <wtf/PrintStream.h>
31
#include <wtf/StringPrintStream.h>
32
33
namespace WTF {
34
35
using namespace JSC;
36
37
void printInternal(PrintStream& out, PutByIdFlags flags) {
38
    StringPrintStream stringOut;
39
    CommaPrinter comma("|");
40
    if (flags & PutByIdIsDirect)
41
        stringOut.print(comma, "IsDirect");
42
43
    CString string = stringOut.toCString();
44
    if (!string.length())
45
        out.print("None");
46
    else
47
        out.print(string);
48
}
49
50
} // namespace WTF
51
- Source/JavaScriptCore/bytecode/PutByIdFlags.h +47 lines
Line 0 Source/JavaScriptCore/bytecode/PutByIdFlags.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef PutByIdFlags_h
27
#define PutByIdFlags_h
28
29
namespace JSC {
30
31
enum PutByIdFlags {
32
    PutByIdNone = 0,
33
    PutByIdIsDirect = 1
34
};
35
36
} // namespace JSC
37
38
namespace WTF {
39
40
class PrintStream;
41
42
void printInternal(PrintStream&, JSC::PutByIdFlags);
43
44
} // namespace WTF
45
46
#endif // PutByIdFlags_h
47
- Source/JavaScriptCore/bytecode/PutByIdStatus.cpp -13 / +12 lines
Lines 66-102 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec1
66
    UNUSED_PARAM(profiledBlock);
66
    UNUSED_PARAM(profiledBlock);
67
    UNUSED_PARAM(bytecodeIndex);
67
    UNUSED_PARAM(bytecodeIndex);
68
    UNUSED_PARAM(uid);
68
    UNUSED_PARAM(uid);
69
70
    VM& vm = *profiledBlock->vm();
71
    
69
    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
72
    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
70
73
71
    Structure* structure = instruction[4].u.structure.get();
74
    StructureID structureID = instruction[4].u.structureID;
72
    if (!structure)
75
    if (!structureID)
73
        return PutByIdStatus(NoInformation);
76
        return PutByIdStatus(NoInformation);
74
    
77
    
75
    if (instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id)
78
    Structure* structure = vm.heap.structureIDTable().get(structureID);
76
        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_out_of_line)) {
79
80
    StructureID newStructureID = instruction[6].u.structureID;
81
    if (!newStructureID) {
77
        PropertyOffset offset = structure->getConcurrently(uid);
82
        PropertyOffset offset = structure->getConcurrently(uid);
78
        if (!isValidOffset(offset))
83
        if (!isValidOffset(offset))
79
            return PutByIdStatus(NoInformation);
84
            return PutByIdStatus(NoInformation);
80
        
85
        
81
        return PutByIdVariant::replace(structure, offset);
86
        return PutByIdVariant::replace(structure, offset);
82
    }
87
    }
88
89
    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
83
    
90
    
84
    ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
91
    ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
85
    
92
    
86
    ASSERT(instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_direct)
87
        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal)
88
        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line)
89
        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line));
90
    
91
    Structure* newStructure = instruction[6].u.structure.get();
92
    
93
    PropertyOffset offset = newStructure->getConcurrently(uid);
93
    PropertyOffset offset = newStructure->getConcurrently(uid);
94
    if (!isValidOffset(offset))
94
    if (!isValidOffset(offset))
95
        return PutByIdStatus(NoInformation);
95
        return PutByIdStatus(NoInformation);
96
    
96
    
97
    ObjectPropertyConditionSet conditionSet;
97
    ObjectPropertyConditionSet conditionSet;
98
    if (instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal)
98
    if (!(instruction[8].u.putByIdFlags & PutByIdIsDirect)) {
99
        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line)) {
100
        conditionSet =
99
        conditionSet =
101
            generateConditionsForPropertySetterMissConcurrently(
100
            generateConditionsForPropertySetterMissConcurrently(
102
                *profiledBlock->vm(), profiledBlock->globalObject(), structure, uid);
101
                *profiledBlock->vm(), profiledBlock->globalObject(), structure, uid);
- Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h +3 lines
Lines 36-41 Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h_sec1
36
#include "JSCell.h"
36
#include "JSCell.h"
37
#include "JSString.h"
37
#include "JSString.h"
38
#include "ParserModes.h"
38
#include "ParserModes.h"
39
#include "PutByIdFlags.h"
39
#include "RegExp.h"
40
#include "RegExp.h"
40
#include "SpecialPointer.h"
41
#include "SpecialPointer.h"
41
#include "UnlinkedFunctionExecutable.h"
42
#include "UnlinkedFunctionExecutable.h"
Lines 97-106 struct UnlinkedInstruction { Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h_sec2
97
    UnlinkedInstruction() { u.operand = 0; }
98
    UnlinkedInstruction() { u.operand = 0; }
98
    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
99
    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
99
    UnlinkedInstruction(int operand) { u.operand = operand; }
100
    UnlinkedInstruction(int operand) { u.operand = operand; }
101
    UnlinkedInstruction(PutByIdFlags flags) { u.putByIdFlags = flags; }
100
    union {
102
    union {
101
        OpcodeID opcode;
103
        OpcodeID opcode;
102
        int32_t operand;
104
        int32_t operand;
103
        unsigned index;
105
        unsigned index;
106
        PutByIdFlags putByIdFlags;
104
    } u;
107
    } u;
105
};
108
};
106
109
- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp -10 / +10 lines
Lines 2103-2113 RegisterID* BytecodeGenerator::emitPutBy Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp_sec1
2103
    instructions().append(base->index());
2103
    instructions().append(base->index());
2104
    instructions().append(propertyIndex);
2104
    instructions().append(propertyIndex);
2105
    instructions().append(value->index());
2105
    instructions().append(value->index());
2106
    instructions().append(0);
2106
    instructions().append(0); // old structure
2107
    instructions().append(0);
2107
    instructions().append(0); // offset
2108
    instructions().append(0);
2108
    instructions().append(0); // new structure
2109
    instructions().append(0);
2109
    instructions().append(0); // structure chain
2110
    instructions().append(0);
2110
    instructions().append(PutByIdNone); // is not direct
2111
2111
2112
    return value;
2112
    return value;
2113
}
2113
}
Lines 2125-2135 RegisterID* BytecodeGenerator::emitDirec Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp_sec2
2125
    instructions().append(base->index());
2125
    instructions().append(base->index());
2126
    instructions().append(propertyIndex);
2126
    instructions().append(propertyIndex);
2127
    instructions().append(value->index());
2127
    instructions().append(value->index());
2128
    instructions().append(0);
2128
    instructions().append(0); // old structure
2129
    instructions().append(0);
2129
    instructions().append(0); // offset
2130
    instructions().append(0);
2130
    instructions().append(0); // new structure
2131
    instructions().append(0);
2131
    instructions().append(0); // structure chain (unused if direct)
2132
    instructions().append(putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto);
2132
    instructions().append((putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone);
2133
    return value;
2133
    return value;
2134
}
2134
}
2135
2135
- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h -16 / +22 lines
Lines 1837-1860 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec1
1837
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
1837
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
1838
                // something more subtle?
1838
                // something more subtle?
1839
                AbstractValue result;
1839
                AbstractValue result;
1840
                for (unsigned i = status.numVariants(); i--;) {
1840
                if (m_state.structureClobberState() == StructuresAreWatched) {
1841
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1841
                    for (unsigned i = status.numVariants(); i--;) {
1842
                    // have more work to do here.
1842
                        // This thing won't give us a variant that involves prototypes. If it
1843
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1843
                        // did, we'd have more work to do here.
1844
                        DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1844
                    
1845
                    
1845
                    JSValue constantResult =
1846
                        JSValue constantResult =
1846
                        m_graph.tryGetConstantProperty(value, status[i].offset());
1847
                            m_graph.tryGetConstantProperty(value, status[i].offset());
1847
                    if (!constantResult) {
1848
                        if (!constantResult) {
1848
                        result.makeHeapTop();
1849
                            result.makeHeapTop();
1849
                        break;
1850
                            break;
1850
                    }
1851
                        }
1851
                    
1852
                    
1852
                    AbstractValue thisResult;
1853
                        AbstractValue thisResult;
1853
                    thisResult.set(
1854
                        thisResult.set(
1854
                        m_graph, *m_graph.freeze(constantResult),
1855
                            m_graph, *m_graph.freeze(constantResult),
1855
                        m_state.structureClobberState());
1856
                            m_state.structureClobberState());
1856
                    result.merge(thisResult);
1857
                        result.merge(thisResult);
1857
                }
1858
                    }
1859
                } else
1860
                    result.makeHeapTop();
1858
                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
1861
                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
1859
                    m_state.setFoundConstants(true);
1862
                    m_state.setFoundConstants(true);
1860
                forNode(node) = result;
1863
                forNode(node) = result;
Lines 2134-2139 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec2
2134
                result.makeHeapTop();
2137
                result.makeHeapTop();
2135
                continue;
2138
                continue;
2136
            }
2139
            }
2140
2141
            // We can fold constants here regardless of the structure clobber state because this
2142
            // node will still return the constant even if some watchpoints fired.
2137
            
2143
            
2138
            AbstractValue thisResult;
2144
            AbstractValue thisResult;
2139
            thisResult.set(
2145
            thisResult.set(
- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp -8 / +3 lines
Lines 44-49 Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec1
44
#include "JSCInlines.h"
44
#include "JSCInlines.h"
45
#include "JSModuleEnvironment.h"
45
#include "JSModuleEnvironment.h"
46
#include "PreciseJumpTargets.h"
46
#include "PreciseJumpTargets.h"
47
#include "PutByIdFlags.h"
47
#include "PutByIdStatus.h"
48
#include "PutByIdStatus.h"
48
#include "StackAlignment.h"
49
#include "StackAlignment.h"
49
#include "StringConstructor.h"
50
#include "StringConstructor.h"
Lines 3513-3519 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec2
3513
        }
3514
        }
3514
            
3515
            
3515
        case op_get_by_id:
3516
        case op_get_by_id:
3516
        case op_get_by_id_out_of_line:
3517
        case op_get_array_length: {
3517
        case op_get_array_length: {
3518
            SpeculatedType prediction = getPrediction();
3518
            SpeculatedType prediction = getPrediction();
3519
            
3519
            
Lines 3531-3546 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec3
3531
3531
3532
            NEXT_OPCODE(op_get_by_id);
3532
            NEXT_OPCODE(op_get_by_id);
3533
        }
3533
        }
3534
        case op_put_by_id:
3534
        case op_put_by_id: {
3535
        case op_put_by_id_out_of_line:
3536
        case op_put_by_id_transition_direct:
3537
        case op_put_by_id_transition_normal:
3538
        case op_put_by_id_transition_direct_out_of_line:
3539
        case op_put_by_id_transition_normal_out_of_line: {
3540
            Node* value = get(VirtualRegister(currentInstruction[3].u.operand));
3535
            Node* value = get(VirtualRegister(currentInstruction[3].u.operand));
3541
            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
3536
            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
3542
            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
3537
            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
3543
            bool direct = currentInstruction[8].u.operand;
3538
            bool direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
3544
3539
3545
            PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
3540
            PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
3546
                m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,
3541
                m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,
- Source/JavaScriptCore/dfg/DFGCapabilities.cpp -6 lines
Lines 152-165 CapabilityLevel capabilityLevel(OpcodeID Source/JavaScriptCore/dfg/DFGCapabilities.cpp_sec1
152
    case op_put_by_val:
152
    case op_put_by_val:
153
    case op_put_by_val_direct:
153
    case op_put_by_val_direct:
154
    case op_get_by_id:
154
    case op_get_by_id:
155
    case op_get_by_id_out_of_line:
156
    case op_get_array_length:
155
    case op_get_array_length:
157
    case op_put_by_id:
156
    case op_put_by_id:
158
    case op_put_by_id_out_of_line:
159
    case op_put_by_id_transition_direct:
160
    case op_put_by_id_transition_direct_out_of_line:
161
    case op_put_by_id_transition_normal:
162
    case op_put_by_id_transition_normal_out_of_line:
163
    case op_jmp:
157
    case op_jmp:
164
    case op_jtrue:
158
    case op_jtrue:
165
    case op_jfalse:
159
    case op_jfalse:
- Source/JavaScriptCore/jit/JIT.cpp -12 lines
Lines 217-223 void JIT::privateCompileMainPass() Source/JavaScriptCore/jit/JIT.cpp_sec1
217
        DEFINE_OP(op_load_arrowfunction_this)
217
        DEFINE_OP(op_load_arrowfunction_this)
218
        DEFINE_OP(op_eq)
218
        DEFINE_OP(op_eq)
219
        DEFINE_OP(op_eq_null)
219
        DEFINE_OP(op_eq_null)
220
        case op_get_by_id_out_of_line:
221
        case op_get_array_length:
220
        case op_get_array_length:
222
        DEFINE_OP(op_get_by_id)
221
        DEFINE_OP(op_get_by_id)
223
        DEFINE_OP(op_get_by_val)
222
        DEFINE_OP(op_get_by_val)
Lines 269-279 void JIT::privateCompileMainPass() Source/JavaScriptCore/jit/JIT.cpp_sec2
269
        DEFINE_OP(op_push_with_scope)
268
        DEFINE_OP(op_push_with_scope)
270
        DEFINE_OP(op_create_lexical_environment)
269
        DEFINE_OP(op_create_lexical_environment)
271
        DEFINE_OP(op_get_parent_scope)
270
        DEFINE_OP(op_get_parent_scope)
272
        case op_put_by_id_out_of_line:
273
        case op_put_by_id_transition_direct:
274
        case op_put_by_id_transition_normal:
275
        case op_put_by_id_transition_direct_out_of_line:
276
        case op_put_by_id_transition_normal_out_of_line:
277
        DEFINE_OP(op_put_by_id)
271
        DEFINE_OP(op_put_by_id)
278
        DEFINE_OP(op_put_by_index)
272
        DEFINE_OP(op_put_by_index)
279
        case op_put_by_val_direct:
273
        case op_put_by_val_direct:
Lines 386-392 void JIT::privateCompileSlowCases() Source/JavaScriptCore/jit/JIT.cpp_sec3
386
        DEFINE_SLOWCASE_OP(op_create_this)
380
        DEFINE_SLOWCASE_OP(op_create_this)
387
        DEFINE_SLOWCASE_OP(op_div)
381
        DEFINE_SLOWCASE_OP(op_div)
388
        DEFINE_SLOWCASE_OP(op_eq)
382
        DEFINE_SLOWCASE_OP(op_eq)
389
        case op_get_by_id_out_of_line:
390
        case op_get_array_length:
383
        case op_get_array_length:
391
        DEFINE_SLOWCASE_OP(op_get_by_id)
384
        DEFINE_SLOWCASE_OP(op_get_by_id)
392
        DEFINE_SLOWCASE_OP(op_get_by_val)
385
        DEFINE_SLOWCASE_OP(op_get_by_val)
Lines 413-423 void JIT::privateCompileSlowCases() Source/JavaScriptCore/jit/JIT.cpp_sec4
413
        DEFINE_SLOWCASE_OP(op_nstricteq)
406
        DEFINE_SLOWCASE_OP(op_nstricteq)
414
        DEFINE_SLOWCASE_OP(op_dec)
407
        DEFINE_SLOWCASE_OP(op_dec)
415
        DEFINE_SLOWCASE_OP(op_inc)
408
        DEFINE_SLOWCASE_OP(op_inc)
416
        case op_put_by_id_out_of_line:
417
        case op_put_by_id_transition_direct:
418
        case op_put_by_id_transition_normal:
419
        case op_put_by_id_transition_direct_out_of_line:
420
        case op_put_by_id_transition_normal_out_of_line:
421
        DEFINE_SLOWCASE_OP(op_put_by_id)
409
        DEFINE_SLOWCASE_OP(op_put_by_id)
422
        case op_put_by_val_direct:
410
        case op_put_by_val_direct:
423
        DEFINE_SLOWCASE_OP(op_put_by_val)
411
        DEFINE_SLOWCASE_OP(op_put_by_val)
- Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp -1 / +1 lines
Lines 623-629 void JIT::emit_op_put_by_id(Instruction* Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp_sec1
623
    
623
    
624
    int base = currentInstruction[1].u.operand;
624
    int base = currentInstruction[1].u.operand;
625
    int value = currentInstruction[3].u.operand;
625
    int value = currentInstruction[3].u.operand;
626
    int direct = currentInstruction[8].u.operand;
626
    int direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
627
    
627
    
628
    emitWriteBarrier(base, value, ShouldFilterBase);
628
    emitWriteBarrier(base, value, ShouldFilterBase);
629
629
- Source/JavaScriptCore/jit/JITPropertyAccess.cpp -1 / +1 lines
Lines 607-613 void JIT::emit_op_put_by_id(Instruction* Source/JavaScriptCore/jit/JITPropertyAccess.cpp_sec1
607
{
607
{
608
    int baseVReg = currentInstruction[1].u.operand;
608
    int baseVReg = currentInstruction[1].u.operand;
609
    int valueVReg = currentInstruction[3].u.operand;
609
    int valueVReg = currentInstruction[3].u.operand;
610
    unsigned direct = currentInstruction[8].u.operand;
610
    unsigned direct = currentInstruction[8].u.putByIdFlags & PutByIdIsDirect;
611
611
612
    emitWriteBarrier(baseVReg, valueVReg, ShouldFilterBase);
612
    emitWriteBarrier(baseVReg, valueVReg, ShouldFilterBase);
613
613
- Source/JavaScriptCore/llint/LLIntSlowPaths.cpp -46 / +27 lines
Lines 570-589 LLINT_SLOW_PATH_DECL(slow_path_get_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec1
570
        JSCell* baseCell = baseValue.asCell();
570
        JSCell* baseCell = baseValue.asCell();
571
        Structure* structure = baseCell->structure();
571
        Structure* structure = baseCell->structure();
572
        
572
        
573
        // Start out by clearing out the old cache.
574
        pc[4].u.pointer = nullptr; // old structure
575
        pc[5].u.pointer = nullptr; // offset
576
        
573
        if (!structure->isUncacheableDictionary()
577
        if (!structure->isUncacheableDictionary()
574
            && !structure->typeInfo().prohibitsPropertyCaching()
578
            && !structure->typeInfo().prohibitsPropertyCaching()
575
            && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) {
579
            && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) {
580
            vm.heap.writeBarrier(codeBlock->ownerExecutable());
581
            
576
            ConcurrentJITLocker locker(codeBlock->m_lock);
582
            ConcurrentJITLocker locker(codeBlock->m_lock);
577
583
578
            pc[4].u.structure.set(
584
            pc[4].u.structureID = structure->id();
579
                vm, codeBlock->ownerExecutable(), structure);
585
            pc[5].u.operand = slot.cachedOffset();
580
            if (isInlineOffset(slot.cachedOffset())) {
581
                pc[0].u.opcode = LLInt::getOpcode(op_get_by_id);
582
                pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
583
            } else {
584
                pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_out_of_line);
585
                pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
586
            }
587
        }
586
        }
588
    }
587
    }
589
588
Lines 618-624 LLINT_SLOW_PATH_DECL(slow_path_put_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec2
618
    
617
    
619
    JSValue baseValue = LLINT_OP_C(1).jsValue();
618
    JSValue baseValue = LLINT_OP_C(1).jsValue();
620
    PutPropertySlot slot(baseValue, codeBlock->isStrictMode(), codeBlock->putByIdContext());
619
    PutPropertySlot slot(baseValue, codeBlock->isStrictMode(), codeBlock->putByIdContext());
621
    if (pc[8].u.operand)
620
    if (pc[8].u.putByIdFlags & PutByIdIsDirect)
622
        asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
621
        asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
623
    else
622
    else
624
        baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
623
        baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
Lines 627-632 LLINT_SLOW_PATH_DECL(slow_path_put_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec3
627
    if (!LLINT_ALWAYS_ACCESS_SLOW
626
    if (!LLINT_ALWAYS_ACCESS_SLOW
628
        && baseValue.isCell()
627
        && baseValue.isCell()
629
        && slot.isCacheablePut()) {
628
        && slot.isCacheablePut()) {
629
630
        // Start out by clearing out the old cache.
631
        pc[4].u.pointer = nullptr; // old structure
632
        pc[5].u.pointer = nullptr; // offset
633
        pc[6].u.pointer = nullptr; // new structure
634
        pc[7].u.pointer = nullptr; // structure chain
630
        
635
        
631
        JSCell* baseCell = baseValue.asCell();
636
        JSCell* baseCell = baseValue.asCell();
632
        Structure* structure = baseCell->structure();
637
        Structure* structure = baseCell->structure();
Lines 634-639 LLINT_SLOW_PATH_DECL(slow_path_put_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec4
634
        if (!structure->isUncacheableDictionary()
639
        if (!structure->isUncacheableDictionary()
635
            && !structure->typeInfo().prohibitsPropertyCaching()
640
            && !structure->typeInfo().prohibitsPropertyCaching()
636
            && baseCell == slot.base()) {
641
            && baseCell == slot.base()) {
642
643
            vm.heap.writeBarrier(codeBlock->ownerExecutable());
637
            
644
            
638
            if (slot.type() == PutPropertySlot::NewProperty) {
645
            if (slot.type() == PutPropertySlot::NewProperty) {
639
                GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap);
646
                GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap);
Lines 641-689 LLINT_SLOW_PATH_DECL(slow_path_put_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec5
641
                if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) {
648
                if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) {
642
                    ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
649
                    ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
643
                    
650
                    
644
                    // This is needed because some of the methods we call
645
                    // below may GC.
646
                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
647
648
                    if (normalizePrototypeChain(exec, structure) != InvalidPrototypeChain) {
651
                    if (normalizePrototypeChain(exec, structure) != InvalidPrototypeChain) {
649
                        ASSERT(structure->previousID()->isObject());
652
                        ASSERT(structure->previousID()->isObject());
650
                        pc[4].u.structure.set(
653
                        pc[4].u.structureID = structure->previousID()->id();
651
                            vm, codeBlock->ownerExecutable(), structure->previousID());
654
                        pc[5].u.operand = slot.cachedOffset();
652
                        if (isInlineOffset(slot.cachedOffset()))
655
                        pc[6].u.structureID = structure->id();
653
                            pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
656
                        if (!(pc[8].u.putByIdFlags & PutByIdIsDirect)) {
654
                        else
657
                            StructureChain* chain = structure->prototypeChain(exec);
655
                            pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
658
                            ASSERT(chain);
656
                        pc[6].u.structure.set(
659
                            pc[7].u.structureChain.set(
657
                            vm, codeBlock->ownerExecutable(), structure);
660
                                vm, codeBlock->ownerExecutable(), chain);
658
                        StructureChain* chain = structure->prototypeChain(exec);
659
                        ASSERT(chain);
660
                        pc[7].u.structureChain.set(
661
                            vm, codeBlock->ownerExecutable(), chain);
662
                    
663
                        if (pc[8].u.operand) {
664
                            if (isInlineOffset(slot.cachedOffset()))
665
                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct);
666
                            else
667
                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line);
668
                        } else {
669
                            if (isInlineOffset(slot.cachedOffset()))
670
                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal);
671
                            else
672
                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line);
673
                        }
661
                        }
674
                    }
662
                    }
675
                }
663
                }
676
            } else {
664
            } else {
677
                structure->didCachePropertyReplacement(vm, slot.cachedOffset());
665
                structure->didCachePropertyReplacement(vm, slot.cachedOffset());
678
                pc[4].u.structure.set(
666
                pc[4].u.structureID = structure->id();
679
                    vm, codeBlock->ownerExecutable(), structure);
667
                pc[5].u.operand = slot.cachedOffset();
680
                if (isInlineOffset(slot.cachedOffset())) {
681
                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
682
                    pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
683
                } else {
684
                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_out_of_line);
685
                    pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
686
                }
687
            }
668
            }
688
        }
669
        }
689
    }
670
    }
- Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm -109 / +53 lines
Lines 1323-1359 end Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm_sec1
1323
# to take fast path on the new cache. At worst we take slow path, which is what
1323
# to take fast path on the new cache. At worst we take slow path, which is what
1324
# we would have been doing anyway.
1324
# we would have been doing anyway.
1325
1325
1326
macro getById(getPropertyStorage)
1326
_llint_op_get_by_id:
1327
    traceExecution()
1327
    traceExecution()
1328
    loadi 8[PC], t0
1328
    loadi 8[PC], t0
1329
    loadi 16[PC], t1
1329
    loadi 16[PC], t1
1330
    loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
1330
    loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
1331
    loadi 20[PC], t2
1331
    loadi 20[PC], t2
1332
    getPropertyStorage(
1332
    bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
1333
        t3,
1333
    loadPropertyAtVariableOffset(t2, t3, t0, t1)
1334
        t0,
1334
    loadi 4[PC], t2
1335
        macro (propertyStorage, scratch)
1335
    storei t0, TagOffset[cfr, t2, 8]
1336
            bpneq JSCell::m_structureID[t3], t1, .opGetByIdSlow
1336
    storei t1, PayloadOffset[cfr, t2, 8]
1337
            loadi 4[PC], t1
1337
    valueProfile(t0, t1, 32, t2)
1338
            loadi TagOffset[propertyStorage, t2], scratch
1338
    dispatch(9)
1339
            loadi PayloadOffset[propertyStorage, t2], t2
1340
            storei scratch, TagOffset[cfr, t1, 8]
1341
            storei t2, PayloadOffset[cfr, t1, 8]
1342
            valueProfile(scratch, t2, 32, t1)
1343
            dispatch(9)
1344
        end)
1345
1346
    .opGetByIdSlow:
1347
        callSlowPath(_llint_slow_path_get_by_id)
1348
        dispatch(9)
1349
end
1350
1351
_llint_op_get_by_id:
1352
    getById(withInlineStorage)
1353
1354
1339
1355
_llint_op_get_by_id_out_of_line:
1340
.opGetByIdSlow:
1356
    getById(withOutOfLineStorage)
1341
    callSlowPath(_llint_slow_path_get_by_id)
1342
    dispatch(9)
1357
1343
1358
1344
1359
_llint_op_get_array_length:
1345
_llint_op_get_array_length:
Lines 1379-1478 _llint_op_get_array_length: Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm_sec2
1379
    dispatch(9)
1365
    dispatch(9)
1380
1366
1381
1367
1382
macro putById(getPropertyStorage)
1368
_llint_op_put_by_id:
1383
    traceExecution()
1369
    traceExecution()
1384
    writeBarrierOnOperands(1, 3)
1370
    writeBarrierOnOperands(1, 3)
1385
    loadi 4[PC], t3
1371
    loadi 4[PC], t3
1386
    loadi 16[PC], t1
1387
    loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
1372
    loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
1388
    loadi 12[PC], t2
1373
    loadi JSCell::m_structure[t0], t2
1389
    getPropertyStorage(
1390
        t0,
1391
        t3,
1392
        macro (propertyStorage, scratch)
1393
            bpneq JSCell::m_structureID[t0], t1, .opPutByIdSlow
1394
            loadi 20[PC], t1
1395
            loadConstantOrVariable2Reg(t2, scratch, t2)
1396
            storei scratch, TagOffset[propertyStorage, t1]
1397
            storei t2, PayloadOffset[propertyStorage, t1]
1398
            dispatch(9)
1399
        end)
1400
1401
    .opPutByIdSlow:
1402
        callSlowPath(_llint_slow_path_put_by_id)
1403
        dispatch(9)
1404
end
1405
1406
_llint_op_put_by_id:
1407
    putById(withInlineStorage)
1408
1409
1410
_llint_op_put_by_id_out_of_line:
1411
    putById(withOutOfLineStorage)
1412
1413
1414
macro putByIdTransition(additionalChecks, getPropertyStorage)
1415
    traceExecution()
1416
    writeBarrierOnOperand(1)
1417
    loadi 4[PC], t3
1418
    loadi 16[PC], t1
1374
    loadi 16[PC], t1
1419
    loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
1375
    bineq t2, t1, .opPutByIdSlow
1420
    loadi 12[PC], t2
1421
    bpneq JSCell::m_structureID[t0], t1, .opPutByIdSlow
1422
    additionalChecks(t1, t3, .opPutByIdSlow)
1423
    loadi 20[PC], t1
1424
    getPropertyStorage(
1425
        t0,
1426
        t3,
1427
        macro (propertyStorage, scratch)
1428
            addp t1, propertyStorage, t3
1429
            loadConstantOrVariable2Reg(t2, t1, t2)
1430
            storei t1, TagOffset[t3]
1431
            loadi 24[PC], t1
1432
            storei t2, PayloadOffset[t3]
1433
            storep t1, JSCell::m_structureID[t0]
1434
            dispatch(9)
1435
        end)
1436
1437
    .opPutByIdSlow:
1438
        callSlowPath(_llint_slow_path_put_by_id)
1439
        dispatch(9)
1440
end
1441
1442
macro noAdditionalChecks(oldStructure, scratch, slowPath)
1443
end
1444
1445
macro structureChainChecks(oldStructure, scratch, slowPath)
1446
    const protoCell = oldStructure   # Reusing the oldStructure register for the proto
1447
1376
1448
    loadp 28[PC], scratch
1377
    # At this point, we have:
1449
    assert(macro (ok) btpnz scratch, ok end)
1378
    # t1, t2 -> currentStructureID
1450
    loadp StructureChain::m_vector[scratch], scratch
1379
    # t0 -> object base
1451
    assert(macro (ok) btpnz scratch, ok end)
1380
1452
    bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done
1381
    loadi 24[PC], t1
1453
.loop:
1382
1454
    loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell
1383
    btiz t1, .opPutByIdNotTransition
1455
    loadp JSCell::m_structureID[protoCell], oldStructure
1384
1456
    bpneq oldStructure, [scratch], slowPath
1385
    # This is the transition case. t1 holds the new Structure*. t2 holds the old Structure*.
1457
    addp 4, scratch
1386
    # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
1458
    bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop
1387
    # scratch.
1459
.done:
1388
    loadp 28[PC], t3
1460
end
1389
    btpz t3, .opPutByIdTransitionDirect
1461
1390
1462
_llint_op_put_by_id_transition_direct:
1391
    loadp StructureChain::m_vector[t3], t3
1463
    putByIdTransition(noAdditionalChecks, withInlineStorage)
1392
    assert(macro (ok) btpnz t3, ok end)
1393
1394
    loadp Structure::m_prototype[t2], t2
1395
    btpz t2, .opPutByIdTransitionChainDone
1396
.opPutByidTransitionChainLoop:
1397
    loadp [t3], t1
1398
    bpneq t1, JSCell::m_structureID[t2], .opPutByIdSlow
1399
    addp 8, t3
1400
    loadp Structure::m_prototype[t1], t2
1401
    btpnz t2, .opPutByIdTransitionChainLoop
1464
1402
1403
.opPutByIdTransitionChainDone:
1404
    loadi 24, t1
1465
1405
1466
_llint_op_put_by_id_transition_direct_out_of_line:
1406
.opPutByIdTransitionDirect:
1467
    putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
1407
    storei t1, JSCell::m_structure[t0]
1468
1469
1470
_llint_op_put_by_id_transition_normal:
1471
    putByIdTransition(structureChainChecks, withInlineStorage)
1472
1408
1409
.opPutByIdNotTransition:
1410
    # The only thing live right now is t0, which holds the base.
1411
    loadi 12[PC], t1
1412
    loadConstantOrVariable(t1, t2, t3)
1413
    loadi 20[PC], t1
1414
    storePropertyAtVariableOffset(t1, t0, t2, t3)
1415
    dispatch(9)
1473
1416
1474
_llint_op_put_by_id_transition_normal_out_of_line:
1417
.opPutByIdSlow:
1475
    putByIdTransition(structureChainChecks, withOutOfLineStorage)
1418
    callSlowPath(_llint_slow_path_put_by_id)
1419
    dispatch(9)
1476
1420
1477
1421
1478
_llint_op_get_by_val:
1422
_llint_op_get_by_val:
- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm -116 / +67 lines
Lines 468-484 macro valueProfile(value, operand, scrat Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec1
468
    storeq value, ValueProfile::m_buckets[scratch]
468
    storeq value, ValueProfile::m_buckets[scratch]
469
end
469
end
470
470
471
macro loadStructure(cell, structure)
471
macro structureIDToStructureWithScratch(structureID, structure, scratch)
472
end
473
474
macro loadStructureWithScratch(cell, structure, scratch)
475
    loadp CodeBlock[cfr], scratch
472
    loadp CodeBlock[cfr], scratch
476
    loadp CodeBlock::m_vm[scratch], scratch
473
    loadp CodeBlock::m_vm[scratch], scratch
477
    loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
474
    loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
478
    loadi JSCell::m_structureID[cell], structure
475
    loadi structureID, structure
479
    loadp [scratch, structure, 8], structure
476
    loadp [scratch, structure, 8], structure
480
end
477
end
481
478
479
macro loadStructureWithScratch(cell, structure, scratch)
480
    structureIDToStructureWithScratch(JSCell::m_structureID[cell], structure, scratch)
481
end
482
482
macro loadStructureAndClobberFirstArg(cell, structure)
483
macro loadStructureAndClobberFirstArg(cell, structure)
483
    loadi JSCell::m_structureID[cell], structure
484
    loadi JSCell::m_structureID[cell], structure
484
    loadp CodeBlock[cfr], cell
485
    loadp CodeBlock[cfr], cell
Lines 1204-1244 macro storePropertyAtVariableOffset(prop Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec2
1204
    storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1205
    storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1205
end
1206
end
1206
1207
1207
macro getById(getPropertyStorage)
1208
_llint_op_get_by_id:
1208
    traceExecution()
1209
    traceExecution()
1209
    # We only do monomorphic get_by_id caching for now, and we do not modify the
1210
    # opcode. We do, however, allow for the cache to change anytime if fails, since
1211
    # ping-ponging is free. At best we get lucky and the get_by_id will continue
1212
    # to take fast path on the new cache. At worst we take slow path, which is what
1213
    # we would have been doing anyway.
1214
    loadisFromInstruction(2, t0)
1210
    loadisFromInstruction(2, t0)
1215
    loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
1211
    loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
1216
    loadStructureWithScratch(t3, t2, t1)
1212
    loadi JSCell::m_structureID[t3], t1
1217
    loadpFromInstruction(4, t1)
1213
    loadisFromInstruction(4, t2)
1218
    bpneq t2, t1, .opGetByIdSlow
1214
    bineq t2, t1, .opGetByIdSlow
1219
    getPropertyStorage(
1215
    loadisFromInstruction(5, t1)
1220
        t3,
1216
    loadisFromInstruction(1, t2)
1221
        t0,
1217
    loadPropertyAtVariableOffset(t1, t3, t0)
1222
        macro (propertyStorage, scratch)
1218
    storeq t0, [cfr, t2, 8]
1223
            loadisFromInstruction(5, t2)
1219
    valueProfile(t0, 8, t1)
1224
            loadisFromInstruction(1, t1)
1220
    dispatch(9)
1225
            loadq [propertyStorage, t2], scratch
1226
            storeq scratch, [cfr, t1, 8]
1227
            valueProfile(scratch, 8, t1)
1228
            dispatch(9)
1229
        end)
1230
            
1231
    .opGetByIdSlow:
1232
        callSlowPath(_llint_slow_path_get_by_id)
1233
        dispatch(9)
1234
end
1235
1236
_llint_op_get_by_id:
1237
    getById(withInlineStorage)
1238
1239
1221
1240
_llint_op_get_by_id_out_of_line:
1222
.opGetByIdSlow:
1241
    getById(withOutOfLineStorage)
1223
    callSlowPath(_llint_slow_path_get_by_id)
1224
    dispatch(9)
1242
1225
1243
1226
1244
_llint_op_get_array_length:
1227
_llint_op_get_array_length:
Lines 1264-1360 _llint_op_get_array_length: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec3
1264
    dispatch(9)
1247
    dispatch(9)
1265
1248
1266
1249
1267
macro putById(getPropertyStorage)
1250
_llint_op_put_by_id:
1268
    traceExecution()
1251
    traceExecution()
1269
    writeBarrierOnOperands(1, 3)
1252
    writeBarrierOnOperands(1, 3)
1270
    loadisFromInstruction(1, t3)
1253
    loadisFromInstruction(1, t3)
1271
    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1254
    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1272
    loadStructureWithScratch(t0, t2, t1)
1255
    loadi JSCell::m_structureID[t0], t2
1273
    loadpFromInstruction(4, t1)
1256
    loadisFromInstruction(4, t1)
1274
    bpneq t2, t1, .opPutByIdSlow
1257
    bineq t2, t1, .opPutByIdSlow
1275
    getPropertyStorage(
1258
1276
        t0,
1259
    # At this point, we have:
1277
        t3,
1260
    # t1, t2 -> current structure ID
1278
        macro (propertyStorage, scratch)
1261
    # t0 -> object base
1279
            loadisFromInstruction(5, t1)
1280
            loadisFromInstruction(3, t2)
1281
            loadConstantOrVariable(t2, scratch)
1282
            storeq scratch, [propertyStorage, t1]
1283
            dispatch(9)
1284
        end)
1285
end
1286
1287
_llint_op_put_by_id:
1288
    putById(withInlineStorage)
1289
1262
1290
.opPutByIdSlow:
1263
    loadisFromInstruction(6, t1)
1291
    callSlowPath(_llint_slow_path_put_by_id)
1264
    
1292
    dispatch(9)
1265
    btiz t1, .opPutByIdNotTransition
1293
1266
1267
    # This is the transition case. t1 holds the new structureID. t2 holds the old structure ID.
1268
    # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
1269
    # scratch.
1270
    loadpFromInstruction(7, t3)
1271
    btpz t3, .opPutByIdTransitionDirect
1272
1273
    loadp StructureChain::m_vector[t3], t3
1274
    assert(macro (ok) btpnz t3, ok end)
1275
1276
    structureIDToStructureWithScratch(t2, t2, t1)
1277
    loadq Structure::m_prototype[t2], t2
1278
    bqeq t2, ValueNull, .opPutByIdTransitionChainDone
1279
.opPutByIdTransitionChainLoop:
1280
    # At this point, t2 contains a prototye, and [t3] contains the Structure* that we want that
1281
    # prototype to have. We don't want to have to load the Structure* for t2. Instead, we load
1282
    # the Structure* from [t3], and then we compare its id to the id in the header of t2.
1283
    loadp [t3], t1
1284
    loadi JSCell::m_structureID[t2], t2
1285
    # Now, t1 has the Structure* and t2 has the StructureID that we want that Structure* to have.
1286
    bineq t2, Structure::m_blob + StructureIDBlob::u.fields.structureID[t1], .opPutByIdSlow
1287
    addp 8, t3
1288
    loadq Structure::m_prototype[t1], t2
1289
    bqneq t2, ValueNull, .opPutByIdTransitionChainLoop
1294
1290
1295
_llint_op_put_by_id_out_of_line:
1291
.opPutByIdTransitionChainDone:
1296
    putById(withOutOfLineStorage)
1292
    # Reload the new structure, since we clobbered it above.
1293
    loadisFromInstruction(6, t1)
1297
1294
1295
.opPutByIdTransitionDirect:
1296
    storei t1, JSCell::m_structureID[t0]
1298
1297
1299
macro putByIdTransition(additionalChecks, getPropertyStorage)
1298
.opPutByIdNotTransition:
1300
    traceExecution()
1299
    # The only thing live right now is t0, which holds the base.
1301
    writeBarrierOnOperand(1)
1300
    loadisFromInstruction(3, t1)
1302
    loadisFromInstruction(1, t3)
1301
    loadConstantOrVariable(t1, t2)
1303
    loadpFromInstruction(4, t1)
1304
    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1305
    loadStructureWithScratch(t0, t2, t3)
1306
    bpneq t2, t1, .opPutByIdSlow
1307
    additionalChecks(t1, t3, t2)
1308
    loadisFromInstruction(3, t2)
1309
    loadisFromInstruction(5, t1)
1302
    loadisFromInstruction(5, t1)
1310
    getPropertyStorage(
1303
    storePropertyAtVariableOffset(t1, t0, t2)
1311
        t0,
1304
    dispatch(9)
1312
        t3,
1313
        macro (propertyStorage, scratch)
1314
            addp t1, propertyStorage, t3
1315
            loadConstantOrVariable(t2, t1)
1316
            storeq t1, [t3]
1317
            loadpFromInstruction(6, t1)
1318
            loadi Structure::m_blob + StructureIDBlob::u.words.word1[t1], t1
1319
            storei t1, JSCell::m_structureID[t0]
1320
            dispatch(9)
1321
        end)
1322
end
1323
1324
macro noAdditionalChecks(oldStructure, scratch, scratch2)
1325
end
1326
1327
macro structureChainChecks(oldStructure, scratch, scratch2)
1328
    const protoCell = oldStructure    # Reusing the oldStructure register for the proto
1329
    loadpFromInstruction(7, scratch)
1330
    assert(macro (ok) btpnz scratch, ok end)
1331
    loadp StructureChain::m_vector[scratch], scratch
1332
    assert(macro (ok) btpnz scratch, ok end)
1333
    bqeq Structure::m_prototype[oldStructure], ValueNull, .done
1334
.loop:
1335
    loadq Structure::m_prototype[oldStructure], protoCell
1336
    loadStructureAndClobberFirstArg(protoCell, scratch2)
1337
    move scratch2, oldStructure
1338
    bpneq oldStructure, [scratch], .opPutByIdSlow
1339
    addp 8, scratch
1340
    bqneq Structure::m_prototype[oldStructure], ValueNull, .loop
1341
.done:
1342
end
1343
1344
_llint_op_put_by_id_transition_direct:
1345
    putByIdTransition(noAdditionalChecks, withInlineStorage)
1346
1347
1348
_llint_op_put_by_id_transition_direct_out_of_line:
1349
    putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
1350
1351
1352
_llint_op_put_by_id_transition_normal:
1353
    putByIdTransition(structureChainChecks, withInlineStorage)
1354
1355
1305
1356
_llint_op_put_by_id_transition_normal_out_of_line:
1306
.opPutByIdSlow:
1357
    putByIdTransition(structureChainChecks, withOutOfLineStorage)
1307
    callSlowPath(_llint_slow_path_put_by_id)
1308
    dispatch(9)
1358
1309
1359
1310
1360
_llint_op_get_by_val:
1311
_llint_op_get_by_val:

Return to Bug 149106