|
Lines 205-212
public:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
|
| 205 |
#endif // FTL_USE_B3 |
205 |
#endif // FTL_USE_B3 |
| 206 |
|
206 |
|
| 207 |
auto preOrder = m_graph.blocksInPreOrder(); |
207 |
auto preOrder = m_graph.blocksInPreOrder(); |
| 208 |
|
208 |
|
| 209 |
// If we have any CallVarargs then we need to have a spill slot for it. |
209 |
#if !FTL_USES_B3 |
| 210 |
bool hasVarargs = false; |
210 |
bool hasVarargs = false; |
| 211 |
size_t maxNumberOfCatchSpills = 0; |
211 |
size_t maxNumberOfCatchSpills = 0; |
| 212 |
for (DFG::BasicBlock* block : preOrder) { |
212 |
for (DFG::BasicBlock* block : preOrder) { |
|
Lines 270-279
public:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
|
| 270 |
} |
270 |
} |
| 271 |
} |
271 |
} |
| 272 |
|
272 |
|
| 273 |
#if FTL_USES_B3 |
273 |
// B3 doesn't need the varargs spill slot because we just use call arg area size as a way to |
| 274 |
UNUSED_PARAM(hasVarargs); |
274 |
// request spill slots. |
| 275 |
// FIXME |
|
|
| 276 |
#else |
| 277 |
if (hasVarargs) { |
275 |
if (hasVarargs) { |
| 278 |
LValue varargsSpillSlots = m_out.alloca( |
276 |
LValue varargsSpillSlots = m_out.alloca( |
| 279 |
arrayType(m_out.int64, JSCallVarargs::numSpillSlotsNeeded())); |
277 |
arrayType(m_out.int64, JSCallVarargs::numSpillSlotsNeeded())); |
|
Lines 284-289
public:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
|
| 284 |
m_out.int32Zero, varargsSpillSlots); |
282 |
m_out.int32Zero, varargsSpillSlots); |
| 285 |
} |
283 |
} |
| 286 |
|
284 |
|
|
|
285 |
// B3 doesn't need the exception spill slot because we just use the |
| 287 |
if (m_graph.m_hasExceptionHandlers && maxNumberOfCatchSpills) { |
286 |
if (m_graph.m_hasExceptionHandlers && maxNumberOfCatchSpills) { |
| 288 |
RegisterSet volatileRegisters = RegisterSet::volatileRegistersForJSCall(); |
287 |
RegisterSet volatileRegisters = RegisterSet::volatileRegistersForJSCall(); |
| 289 |
maxNumberOfCatchSpills = std::min(volatileRegisters.numberOfSetRegisters(), maxNumberOfCatchSpills); |
288 |
maxNumberOfCatchSpills = std::min(volatileRegisters.numberOfSetRegisters(), maxNumberOfCatchSpills); |
|
Lines 296-302
public:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
|
| 296 |
m_out.constInt64(m_ftlState.exceptionHandlingSpillSlotStackmapID), |
295 |
m_out.constInt64(m_ftlState.exceptionHandlingSpillSlotStackmapID), |
| 297 |
m_out.int32Zero, exceptionHandlingVolatileRegistersSpillSlots); |
296 |
m_out.int32Zero, exceptionHandlingVolatileRegistersSpillSlots); |
| 298 |
} |
297 |
} |
| 299 |
#endif |
298 |
#endif // !FTL_USES_B3 |
| 300 |
|
299 |
|
| 301 |
// We should not create any alloca's after this point, since they will cease to |
300 |
// We should not create any alloca's after this point, since they will cease to |
| 302 |
// be mem2reg candidates. |
301 |
// be mem2reg candidates. |
|
Lines 5069-5089
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
|
| 5069 |
|
5068 |
|
| 5070 |
void compileCallOrConstructVarargs() |
5069 |
void compileCallOrConstructVarargs() |
| 5071 |
{ |
5070 |
{ |
| 5072 |
#if FTL_USES_B3 |
5071 |
Node* node = m_node; |
| 5073 |
if (verboseCompilationEnabled() || !verboseCompilationEnabled()) |
|
|
| 5074 |
CRASH(); |
| 5075 |
#else |
| 5076 |
LValue jsCallee = lowJSValue(m_node->child1()); |
5072 |
LValue jsCallee = lowJSValue(m_node->child1()); |
| 5077 |
LValue thisArg = lowJSValue(m_node->child3()); |
5073 |
LValue thisArg = lowJSValue(m_node->child3()); |
| 5078 |
|
5074 |
|
| 5079 |
LValue jsArguments = nullptr; |
5075 |
LValue jsArguments = nullptr; |
| 5080 |
|
5076 |
|
| 5081 |
switch (m_node->op()) { |
5077 |
switch (node->op()) { |
| 5082 |
case CallVarargs: |
5078 |
case CallVarargs: |
| 5083 |
case TailCallVarargs: |
5079 |
case TailCallVarargs: |
| 5084 |
case TailCallVarargsInlinedCaller: |
5080 |
case TailCallVarargsInlinedCaller: |
| 5085 |
case ConstructVarargs: |
5081 |
case ConstructVarargs: |
| 5086 |
jsArguments = lowJSValue(m_node->child2()); |
5082 |
jsArguments = lowJSValue(node->child2()); |
| 5087 |
break; |
5083 |
break; |
| 5088 |
case CallForwardVarargs: |
5084 |
case CallForwardVarargs: |
| 5089 |
case TailCallForwardVarargs: |
5085 |
case TailCallForwardVarargs: |
|
Lines 5091-5100
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
|
| 5091 |
case ConstructForwardVarargs: |
5087 |
case ConstructForwardVarargs: |
| 5092 |
break; |
5088 |
break; |
| 5093 |
default: |
5089 |
default: |
| 5094 |
DFG_CRASH(m_graph, m_node, "bad node type"); |
5090 |
DFG_CRASH(m_graph, node, "bad node type"); |
| 5095 |
break; |
5091 |
break; |
| 5096 |
} |
5092 |
} |
| 5097 |
|
5093 |
|
|
|
5094 |
#if FTL_USES_B3 |
| 5095 |
// FIXME: Need a story for exceptions. |
| 5096 |
// https://bugs.webkit.org/show_bug.cgi?id=151686 |
| 5097 |
|
| 5098 |
PatckpointValue* patchpoint = m_out.patchpoint(Int64); |
| 5099 |
patchpoint->append(jsCallee, ValueRep::SomeRegister); |
| 5100 |
if (jsArguments) |
| 5101 |
patchpoint->append(jsArguments, ValueRep::SomeRegister); |
| 5102 |
patchpoint->append(thisArg, ValueRep::SomeRegister); |
| 5103 |
|
| 5104 |
patchpoint->clobber(RegisterSet::macroScratchRegisters()); |
| 5105 |
parchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall()); |
| 5106 |
patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR); |
| 5107 |
|
| 5108 |
// This is the minimum amount of call arg area stack space that all JS->JS calls always have. |
| 5109 |
unsigned minimumJSCallAreaSize = |
| 5110 |
sizeof(CallerFrameAndPC) + |
| 5111 |
WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(EncodedJSValue)); |
| 5112 |
|
| 5113 |
// This is the number of spill slots we will want. |
| 5114 |
unsigned spillAreaSize = 3 * sizeof(EncodedJSValue); |
| 5115 |
|
| 5116 |
CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite(); |
| 5117 |
State* state = &m_ftlState; |
| 5118 |
patchpoint->setGenerator( |
| 5119 |
[=] (CCallHelpers& jit, const StackmapGenerationParams& params) { |
| 5120 |
AllowMacroScratchRegisterUsage allowScratch(jit); |
| 5121 |
CallSiteIndex callSiteIndex = |
| 5122 |
state->jitCode->common.addUniqueCallSiteIndex(codeOrigin); |
| 5123 |
|
| 5124 |
// FIXME: We would ask the OSR exit descriptor to prepare and then we would modify |
| 5125 |
// the OSRExit data structure inside the OSRExitHandle to link it up to this call. |
| 5126 |
// Also, the exception checks JumpList should be linked to somewhere. |
| 5127 |
// https://bugs.webkit.org/show_bug.cgi?id=151686 |
| 5128 |
CCallHelpers::JumpList exceptions; |
| 5129 |
|
| 5130 |
jit.store32( |
| 5131 |
CCallHelpers::TrustedImm32(callSiteIndex.bits()), |
| 5132 |
CCallHelpers::tagFor(VirtualRegister(JSStack::ArgumentCount))); |
| 5133 |
|
| 5134 |
CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo(); |
| 5135 |
CallVarargsData* data = node->callVarargsData(); |
| 5136 |
|
| 5137 |
unsigned argIndex = 1; |
| 5138 |
GPRReg calleeGPR = params[argIndex++].gpr(); |
| 5139 |
GPRReg argumentsGPR = InvalidGPRReg; |
| 5140 |
bool forwarding = false; |
| 5141 |
if (jsArguments) |
| 5142 |
argumentsGPR = params[argIndex++].gpr(); |
| 5143 |
else |
| 5144 |
forwarding = true; |
| 5145 |
GPRReg thisGPR = params[argIndex++].gpr(); |
| 5146 |
|
| 5147 |
// Get some scratch registers. |
| 5148 |
RegisterSet usedRegisters; |
| 5149 |
usedRegisters.merge(RegisterSet::stackRegisters()); |
| 5150 |
usedRegisters.merge(RegisterSet::reservedHardwareRegisters()); |
| 5151 |
usedRegisters.merge(RegisterSet::calleeSaveRegisters()); |
| 5152 |
usedRegisters.set(calleeGPR); |
| 5153 |
if (argumentsGPR != InvalidGPRReg) |
| 5154 |
usedRegisters.set(argumentsGPR); |
| 5155 |
usedRegisters.set(thisGPR); |
| 5156 |
ScratchRegisterAllocator allocator(usedRegisters); |
| 5157 |
GPRReg scratchGPR1 = allocator.allocateScratchGPR(); |
| 5158 |
GPRReg scratchGPR2 = allocator.allocateScratchGPR(); |
| 5159 |
GPRReg scratchGPR3 = allocator.allocateScratchGPR(); |
| 5160 |
RELEASE_ASSERT(!allocator.numberOfReusedRegisters()); |
| 5161 |
|
| 5162 |
auto computeUsedStack = [&] (GPRReg targetGPR, unsigned extra) { |
| 5163 |
if (isARM64()) { |
| 5164 |
// Have to do this the weird way because %sp on ARM64 means zero when used in |
| 5165 |
// a subtraction. |
| 5166 |
jit.move(CCallHelpers::stackPointerRegister, targetGPR); |
| 5167 |
jit.negPtr(targetGPR); |
| 5168 |
jit.addPtr(GPRInfo::callFrameRegister, targetGPR); |
| 5169 |
} else { |
| 5170 |
jit.move(GPRInfo::callFrameRegister, targetGPR); |
| 5171 |
jit.subPtr(CCallHelpers::stackPointerRegister, targetGPR); |
| 5172 |
} |
| 5173 |
if (extra) |
| 5174 |
jit.subPtr(CCallHelpers::TrustedImm32(extra), targetGPR); |
| 5175 |
jit.urshiftPtr(CCallHelpers::Imm32(3), targetGPR); |
| 5176 |
}; |
| 5177 |
|
| 5178 |
auto callWithExceptionCheck = [&] (void* callee) { |
| 5179 |
jit.move(CCallHelpers::TrustedImmPtr(callee), GPRInfo::nonPreservedNonArgumentGPR); |
| 5180 |
jit.call(GPRInfo::nonPreservedNonArgumentGPR); |
| 5181 |
exceptions.append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth)); |
| 5182 |
}; |
| 5183 |
|
| 5184 |
unsigned originalStackHeight = params.proc().frameSize(); |
| 5185 |
|
| 5186 |
unsigned extraStack = sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)); |
| 5187 |
}); |
| 5188 |
#else |
| 5098 |
unsigned stackmapID = m_stackmapIDs++; |
5189 |
unsigned stackmapID = m_stackmapIDs++; |
| 5099 |
|
5190 |
|
| 5100 |
StackmapArgumentList arguments; |
5191 |
StackmapArgumentList arguments; |
|
Lines 5108-5122
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
|
| 5108 |
|
5199 |
|
| 5109 |
arguments.insert(0, m_out.constInt32(2 + !!jsArguments)); |
5200 |
arguments.insert(0, m_out.constInt32(2 + !!jsArguments)); |
| 5110 |
arguments.insert(0, constNull(m_out.ref8)); |
5201 |
arguments.insert(0, constNull(m_out.ref8)); |
| 5111 |
arguments.insert(0, m_out.constInt32(sizeOfICFor(m_node))); |
5202 |
arguments.insert(0, m_out.constInt32(sizeOfICFor(node))); |
| 5112 |
arguments.insert(0, m_out.constInt64(stackmapID)); |
5203 |
arguments.insert(0, m_out.constInt64(stackmapID)); |
| 5113 |
|
5204 |
|
| 5114 |
LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments); |
5205 |
LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments); |
| 5115 |
setInstructionCallingConvention(call, LLVMCCallConv); |
5206 |
setInstructionCallingConvention(call, LLVMCCallConv); |
| 5116 |
|
5207 |
|
| 5117 |
m_ftlState.jsCallVarargses.append(JSCallVarargs(stackmapID, m_node, codeOriginDescriptionOfCallSite())); |
5208 |
m_ftlState.jsCallVarargses.append(JSCallVarargs(stackmapID, node, codeOriginDescriptionOfCallSite())); |
| 5118 |
|
5209 |
|
| 5119 |
switch (m_node->op()) { |
5210 |
switch (node->op()) { |
| 5120 |
case TailCallVarargs: |
5211 |
case TailCallVarargs: |
| 5121 |
case TailCallForwardVarargs: |
5212 |
case TailCallForwardVarargs: |
| 5122 |
m_out.unreachable(); |
5213 |
m_out.unreachable(); |