source: webkit/trunk/Source/JavaScriptCore/dfg/DFGStackLayoutPhase.cpp

Last change on this file was 287596, checked in by [email protected], 3 years ago

[JSC] Remove m_calleeSaveRegisters from CodeBlock::JITData and rename it to BaselineJITData
https://bugs.webkit.org/show_bug.cgi?id=234555

Reviewed by Saam Barati.

This patch removes m_calleeSaveRegisters from CodeBlock::JITData, and moving it to each JITCode.
This is reasonable since m_calleeSaveRegisters information belongs to JITCode, not CodeBlock.
And in LLInt, Baseline, and DFG cases, m_calleeSaveRegisters is the same. So we do not have this
field in these JITCode. Only FTL can have m_calleeSaveRegisters.

By removing m_calleeSaveRegisters from CodeBlock::JITData, now it only includes Baseline JIT related
data. So this patch renames CodeBlock::JITData to BaselineJITData.

We also use TrailingArray for BaselineJITData so that we can remove one level indirection when loading
JITConstantPool from JITData.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::setupWithUnlinkedBaselineCode):
(JSC::CodeBlock::~CodeBlock):
(JSC::CodeBlock::propagateTransitions):
(JSC::CodeBlock::finalizeJITInlineCaches):
(JSC::CodeBlock::getICStatusMap):
(JSC::CodeBlock::findStubInfo):
(JSC::CodeBlock::resetBaselineJITData):
(JSC::CodeBlock::stronglyVisitStrongReferences):
(JSC::CodeBlock::calleeSaveSpaceAsVirtualRegisters):
(JSC::CodeBlock::findPC):
(JSC::CodeBlock::ensureJITDataSlow): Deleted.
(JSC::CodeBlock::setCalleeSaveRegisters): Deleted.
(JSC::CodeBlock::resetJITData): Deleted.
(JSC::CodeBlock::calleeSaveRegisters const): Deleted.

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::offsetOfBaselineJITData):
(JSC::CodeBlock::baselineJITData):
(JSC::CodeBlock::calleeSaveSpaceAsVirtualRegisters):
(JSC::CodeBlock::JITData::offsetOfJITConstantPool): Deleted.
(JSC::CodeBlock::ensureJITData): Deleted.
(JSC::CodeBlock::offsetOfJITData): Deleted.
(JSC::CodeBlock::baselineJITConstantPool): Deleted.

  • bytecode/Repatch.cpp:

(JSC::linkPolymorphicCall):

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::emitRestoreCalleeSaves):
(JSC::DFG::JITCompiler::emitSaveCalleeSaves):

  • dfg/DFGOSREntry.cpp:

(JSC::DFG::prepareOSREntry):

  • dfg/DFGOSRExit.cpp:

(JSC::DFG::OSRExit::compileExit):

  • dfg/DFGOSRExitCompilerCommon.cpp:

(JSC::DFG::calleeSaveSlot):
(JSC::DFG::reifyInlinedCallFrames):
(JSC::DFG::adjustAndJumpToTarget):

  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::compileInThreadImpl):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::emitCall):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::emitCall):

  • dfg/DFGStackLayoutPhase.cpp:

(JSC::DFG::StackLayoutPhase::run):

  • ftl/FTLCompile.cpp:

(JSC::FTL::compile):

  • ftl/FTLJITCode.h:

(JSC::FTL::JITCode::calleeSaveRegisters const):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):

  • ftl/FTLOSRExitCompiler.cpp:

(JSC::FTL::compileStub):

  • interpreter/StackVisitor.cpp:

(JSC::StackVisitor::Frame::calleeSaveRegistersForUnwinding):

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::executableFor):
(JSC::AssemblyHelpers::emitSaveOrCopyLLIntBaselineCalleeSavesFor):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::emitSaveThenMaterializeTagRegisters):
(JSC::AssemblyHelpers::emitSaveCalleeSavesFor): Deleted.
(JSC::AssemblyHelpers::emitRestoreCalleeSavesFor): Deleted.
(JSC::AssemblyHelpers::emitSaveCalleeSaves): Deleted.
(JSC::AssemblyHelpers::emitRestoreCalleeSaves): Deleted.

  • jit/BaselineJITCode.h:
  • jit/CallFrameShuffleData.cpp:
  • jit/CallFrameShuffleData.h:
  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::emitMaterializeMetadataAndConstantPoolRegisters):
(JSC::JIT::emitSaveCalleeSaves):
(JSC::JIT::compileAndLinkWithoutFinalizing):

  • jit/JIT.h:
  • jit/JITCode.cpp:

(JSC::JITCode::calleeSaveRegisters const):

  • jit/JITCode.h:
  • jit/JITInlines.h:

(JSC::JIT::loadConstant):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_catch):

  • jit/RegisterAtOffsetList.cpp:

(JSC::RegisterAtOffsetList::dfgCalleeSaveRegisters):

  • jit/RegisterAtOffsetList.h:
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LowLevelInterpreter.asm:
  • tools/VMInspector.cpp:

(JSC::VMInspector::dumpRegisters):

File size: 10.3 KB
Line 
1/*
2 * Copyright (C) 2013-2019 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 "DFGStackLayoutPhase.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "DFGGraph.h"
32#include "DFGPhase.h"
33#include "DFGValueSource.h"
34#include "JSCJSValueInlines.h"
35
36namespace JSC { namespace DFG {
37
38class StackLayoutPhase : public Phase {
39 static constexpr bool verbose = false;
40
41public:
42 StackLayoutPhase(Graph& graph)
43 : Phase(graph, "stack layout")
44 {
45 }
46
47 bool run()
48 {
49 // This enumerates the locals that we actually care about and packs them. So for example
50 // if we use local 1, 3, 4, 5, 7, then we remap them: 1->0, 3->1, 4->2, 5->3, 7->4. We
51 // treat a variable as being "used" if there exists an access to it (SetLocal, GetLocal,
52 // Flush, PhantomLocal).
53
54 Operands<bool> usedOperands(0, graph().m_localVars, graph().m_tmps, false);
55
56 // Collect those variables that are used from IR.
57 bool hasNodesThatNeedFixup = false;
58 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
59 BasicBlock* block = m_graph.block(blockIndex);
60 if (!block)
61 continue;
62 for (unsigned nodeIndex = block->size(); nodeIndex--;) {
63 Node* node = block->at(nodeIndex);
64 switch (node->op()) {
65 case GetLocal:
66 case SetLocal:
67 case Flush:
68 case PhantomLocal: {
69 VariableAccessData* variable = node->variableAccessData();
70 if (variable->operand().isArgument())
71 break;
72 usedOperands.setOperand(variable->operand(), true);
73 break;
74 }
75
76 case LoadVarargs:
77 case ForwardVarargs: {
78 LoadVarargsData* data = node->loadVarargsData();
79 usedOperands.setOperand(data->count, true);
80 if (data->start.isLocal()) {
81 // This part really relies on the contiguity of stack layout
82 // assignments.
83 ASSERT(VirtualRegister(data->start.offset() + data->limit - 1).isLocal());
84 for (unsigned i = data->limit; i--;)
85 usedOperands.setOperand(VirtualRegister(data->start.offset() + i), true);
86 } // the else case shouldn't happen.
87 hasNodesThatNeedFixup = true;
88 break;
89 }
90
91 case PutStack:
92 case GetStack: {
93 StackAccessData* stack = node->stackAccessData();
94 if (stack->operand.isArgument())
95 break;
96 usedOperands.setOperand(stack->operand, true);
97 break;
98 }
99
100 default:
101 break;
102 }
103 }
104 }
105
106 for (InlineCallFrameSet::iterator iter = m_graph.m_plan.inlineCallFrames()->begin(); !!iter; ++iter) {
107 InlineCallFrame* inlineCallFrame = *iter;
108
109 if (inlineCallFrame->isVarargs()) {
110 usedOperands.setOperand(VirtualRegister(
111 CallFrameSlot::argumentCountIncludingThis + inlineCallFrame->stackOffset), true);
112 }
113
114 for (unsigned argument = inlineCallFrame->m_argumentsWithFixup.size(); argument--;) {
115 usedOperands.setOperand(VirtualRegister(
116 virtualRegisterForArgumentIncludingThis(argument).offset() +
117 inlineCallFrame->stackOffset), true);
118 }
119 }
120
121 Vector<unsigned> allocation(usedOperands.size());
122 m_graph.m_nextMachineLocal = CodeBlock::calleeSaveSpaceAsVirtualRegisters(RegisterAtOffsetList::dfgCalleeSaveRegisters());
123 for (unsigned i = 0; i < usedOperands.size(); ++i) {
124 if (!usedOperands.getForOperandIndex(i)) {
125 allocation[i] = UINT_MAX;
126 continue;
127 }
128
129 allocation[i] = m_graph.m_nextMachineLocal++;
130 }
131
132 for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
133 VariableAccessData* variable = &m_graph.m_variableAccessData[i];
134 if (!variable->isRoot())
135 continue;
136
137 if (variable->operand().isArgument()) {
138 variable->machineLocal() = variable->operand().virtualRegister();
139 continue;
140 }
141
142 Operand operand = variable->operand();
143 size_t index = usedOperands.operandIndex(operand);
144 if (index >= allocation.size())
145 continue;
146
147 if (allocation[index] == UINT_MAX)
148 continue;
149
150 variable->machineLocal() = assign(usedOperands, allocation, variable->operand());
151 }
152
153 for (StackAccessData* data : m_graph.m_stackAccessData) {
154 if (data->operand.isArgument()) {
155 data->machineLocal = data->operand.virtualRegister();
156 continue;
157 }
158
159 if (data->operand.isLocal()) {
160 if (static_cast<size_t>(data->operand.toLocal()) >= allocation.size())
161 continue;
162 if (allocation[data->operand.toLocal()] == UINT_MAX)
163 continue;
164 }
165
166 data->machineLocal = assign(usedOperands, allocation, data->operand);
167 }
168
169 if (!m_graph.needsScopeRegister())
170 codeBlock()->setScopeRegister(VirtualRegister());
171 else
172 codeBlock()->setScopeRegister(assign(usedOperands, allocation, codeBlock()->scopeRegister()));
173
174 for (unsigned i = m_graph.m_inlineVariableData.size(); i--;) {
175 InlineVariableData data = m_graph.m_inlineVariableData[i];
176 InlineCallFrame* inlineCallFrame = data.inlineCallFrame;
177
178 if (inlineCallFrame->isVarargs())
179 inlineCallFrame->argumentCountRegister = assign(usedOperands, allocation, VirtualRegister(inlineCallFrame->stackOffset + CallFrameSlot::argumentCountIncludingThis));
180
181 for (unsigned argument = inlineCallFrame->m_argumentsWithFixup.size(); argument--;) {
182 ArgumentPosition& position = m_graph.m_argumentPositions[
183 data.argumentPositionStart + argument];
184 VariableAccessData* variable = position.someVariable();
185 ValueSource source;
186 if (!variable)
187 source = ValueSource(SourceIsDead);
188 else {
189 source = ValueSource::forFlushFormat(
190 variable->machineLocal(), variable->flushFormat());
191 }
192 inlineCallFrame->m_argumentsWithFixup[argument] = source.valueRecovery();
193 }
194
195 RELEASE_ASSERT(inlineCallFrame->isClosureCall == !!data.calleeVariable);
196 if (inlineCallFrame->isClosureCall) {
197 VariableAccessData* variable = data.calleeVariable->find();
198 ValueSource source = ValueSource::forFlushFormat(
199 variable->machineLocal(),
200 variable->flushFormat());
201 inlineCallFrame->calleeRecovery = source.valueRecovery();
202 } else
203 RELEASE_ASSERT(inlineCallFrame->calleeRecovery.isConstant());
204 }
205
206 // Fix Varargs' variable references.
207 if (hasNodesThatNeedFixup) {
208 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
209 BasicBlock* block = m_graph.block(blockIndex);
210 if (!block)
211 continue;
212 for (unsigned nodeIndex = block->size(); nodeIndex--;) {
213 Node* node = block->at(nodeIndex);
214 switch (node->op()) {
215 case LoadVarargs:
216 case ForwardVarargs: {
217 LoadVarargsData* data = node->loadVarargsData();
218 data->machineCount = assign(usedOperands, allocation, data->count);
219 data->machineStart = assign(usedOperands, allocation, data->start);
220 break;
221 }
222
223 default:
224 break;
225 }
226 }
227 }
228 }
229
230 return true;
231 }
232
233private:
234 VirtualRegister assign(const Operands<bool>& usedOperands, const Vector<unsigned>& allocation, Operand operand)
235 {
236 if (operand.isArgument())
237 return operand.virtualRegister();
238
239 size_t operandIndex = usedOperands.operandIndex(operand);
240 unsigned myAllocation = allocation[operandIndex];
241 if (myAllocation == UINT_MAX)
242 return VirtualRegister();
243 return virtualRegisterForLocal(myAllocation);
244 }
245};
246
247bool performStackLayout(Graph& graph)
248{
249 return runPhase<StackLayoutPhase>(graph);
250}
251
252} } // namespace JSC::DFG
253
254#endif // ENABLE(DFG_JIT)
255
Note: See TracBrowser for help on using the repository browser.