mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 846539 - Remove jsop_call_inline(). r=djvj
This commit is contained in:
parent
72eca3f9c1
commit
2357f881ce
@ -2895,7 +2895,9 @@ class AutoAccumulateExits
|
||||
MIRGraphExits *prev_;
|
||||
|
||||
public:
|
||||
AutoAccumulateExits(MIRGraph &graph, MIRGraphExits &exits) : graph_(graph) {
|
||||
AutoAccumulateExits(MIRGraph &graph, MIRGraphExits &exits)
|
||||
: graph_(graph)
|
||||
{
|
||||
prev_ = graph_.exitAccumulator();
|
||||
graph_.setExitAccumulator(&exits);
|
||||
}
|
||||
@ -2910,16 +2912,14 @@ IonBuilder::inlineScriptedCall(HandleFunction target, CallInfo &callInfo)
|
||||
AssertCanGC();
|
||||
JS_ASSERT(target->isInterpreted());
|
||||
JS_ASSERT(callInfo.hasCallType());
|
||||
JS_ASSERT(types::IsInlinableCall(pc));
|
||||
|
||||
// Remove the MPassArg if still present.
|
||||
// Remove any MPassArgs.
|
||||
if (callInfo.isWrapped())
|
||||
callInfo.unwrapArgs();
|
||||
|
||||
// Create resumepoint if not provided. This resume point collects outer variables only.
|
||||
// It is used to recover the stack state before the current bytecode.
|
||||
|
||||
// Make sure there is enough place in the slots
|
||||
uint32_t depth = current->stackDepth() + callInfo.argc() + 2;
|
||||
// Ensure sufficient space in the slots: needed for inlining from FUNAPPLY.
|
||||
uint32_t depth = current->stackDepth() + callInfo.numFormals();
|
||||
if (depth > current->nslots()) {
|
||||
if (!current->increaseSlots(depth - current->nslots()))
|
||||
return false;
|
||||
@ -2933,15 +2933,15 @@ IonBuilder::inlineScriptedCall(HandleFunction target, CallInfo &callInfo)
|
||||
callInfo.setThis(thisDefn);
|
||||
}
|
||||
|
||||
// Push formals to capture in the resumepoint
|
||||
// Capture formals in the outer resume point.
|
||||
callInfo.pushFormals(current);
|
||||
|
||||
MResumePoint *resumePoint =
|
||||
MResumePoint *outerResumePoint =
|
||||
MResumePoint::New(current, pc, callerResumePoint_, MResumePoint::Outer);
|
||||
if (!resumePoint)
|
||||
if (!outerResumePoint)
|
||||
return false;
|
||||
|
||||
// Pop formals again, except leave |fun| on stack for duration of call
|
||||
// Pop formals again, except leave |fun| on stack for duration of call.
|
||||
callInfo.popFormals(current);
|
||||
current->push(callInfo.fun());
|
||||
|
||||
@ -2958,7 +2958,7 @@ IonBuilder::inlineScriptedCall(HandleFunction target, CallInfo &callInfo)
|
||||
addTypeBarrier(i, callInfo, oracle.parameterTypeSet(calleeScript, i - 1));
|
||||
}
|
||||
|
||||
// Start inlining
|
||||
// Start inlining.
|
||||
LifoAlloc *alloc = GetIonContext()->temp->lifoAlloc();
|
||||
CompileInfo *info = alloc->new_<CompileInfo>(calleeScript.get(), target,
|
||||
(jsbytecode *)NULL, callInfo.constructing(),
|
||||
@ -2969,11 +2969,9 @@ IonBuilder::inlineScriptedCall(HandleFunction target, CallInfo &callInfo)
|
||||
MIRGraphExits saveExits;
|
||||
AutoAccumulateExits aae(graph(), saveExits);
|
||||
|
||||
IonBuilder inlineBuilder(cx, &temp(), &graph(), &oracle,
|
||||
info, inliningDepth + 1, loopDepth_);
|
||||
|
||||
// Build the graph.
|
||||
if (!inlineBuilder.buildInline(this, resumePoint, callInfo)) {
|
||||
IonBuilder inlineBuilder(cx, &temp(), &graph(), &oracle, info, inliningDepth + 1, loopDepth_);
|
||||
if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
|
||||
JS_ASSERT(calleeScript->hasAnalysis());
|
||||
|
||||
// Inlining the callee failed. Disable inlining the function
|
||||
@ -2984,35 +2982,33 @@ IonBuilder::inlineScriptedCall(HandleFunction target, CallInfo &callInfo)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create bottom block
|
||||
JS_ASSERT(types::IsInlinableCall(pc));
|
||||
// Create return block.
|
||||
jsbytecode *postCall = GetNextPc(pc);
|
||||
MBasicBlock *bottom = newBlock(NULL, postCall);
|
||||
if (!bottom)
|
||||
MBasicBlock *returnBlock = newBlock(NULL, postCall);
|
||||
if (!returnBlock)
|
||||
return false;
|
||||
bottom->setCallerResumePoint(callerResumePoint_);
|
||||
returnBlock->setCallerResumePoint(callerResumePoint_);
|
||||
|
||||
// When profiling add Inline_Exit instruction to indicate end of inlined function.
|
||||
if (instrumentedProfiling())
|
||||
bottom->add(MFunctionBoundary::New(NULL, MFunctionBoundary::Inline_Exit));
|
||||
returnBlock->add(MFunctionBoundary::New(NULL, MFunctionBoundary::Inline_Exit));
|
||||
|
||||
// Inherit the slots from current and pop |fun|.
|
||||
bottom->inheritSlots(current);
|
||||
bottom->pop();
|
||||
returnBlock->inheritSlots(current);
|
||||
returnBlock->pop();
|
||||
|
||||
// Push return value
|
||||
// Accumulate return values.
|
||||
MIRGraphExits &exits = *inlineBuilder.graph().exitAccumulator();
|
||||
MDefinition *retvalDefn = patchInlinedReturns(callInfo, exits, bottom);
|
||||
MDefinition *retvalDefn = patchInlinedReturns(callInfo, exits, returnBlock);
|
||||
if (!retvalDefn)
|
||||
return false;
|
||||
bottom->push(retvalDefn);
|
||||
returnBlock->push(retvalDefn);
|
||||
|
||||
// Initialize entry slots now that the stack has been fixed up.
|
||||
if (!bottom->initEntrySlots())
|
||||
if (!returnBlock->initEntrySlots())
|
||||
return false;
|
||||
|
||||
current = bottom;
|
||||
|
||||
current = returnBlock;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3129,92 +3125,6 @@ IonBuilder::patchInlinedReturns(CallInfo &callInfo, MIRGraphExits &exits, MBasic
|
||||
return phi;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_call_inline(HandleFunction callee, CallInfo &callInfo, MBasicBlock *bottom,
|
||||
Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(callInfo.hasCallType());
|
||||
|
||||
// Push formals to capture them in the inline resume point.
|
||||
int calleePos = -((int) callInfo.argc() + 2);
|
||||
current->peek(calleePos)->setFoldedUnchecked();
|
||||
current->rewriteAtDepth(calleePos, callInfo.fun());
|
||||
|
||||
// This resume point collects outer variables only. It is used to recover
|
||||
// the stack state before the current bytecode.
|
||||
MResumePoint *inlineResumePoint =
|
||||
MResumePoint::New(current, pc, callerResumePoint_, MResumePoint::Outer);
|
||||
if (!inlineResumePoint)
|
||||
return false;
|
||||
|
||||
// Pop formals again (|this| and arguments).
|
||||
// Note that we leave the |fun| on the stack
|
||||
callInfo.popFormals(current);
|
||||
current->push(callInfo.fun());
|
||||
|
||||
// Inlining JSOP_FUNCALL uses inlineScriptedCall
|
||||
JS_ASSERT(callInfo.argc() == GET_ARGC(inlineResumePoint->pc()));
|
||||
|
||||
RootedScript calleeScript(cx, callee->nonLazyScript());
|
||||
TypeInferenceOracle oracle;
|
||||
if (!oracle.init(cx, calleeScript))
|
||||
return false;
|
||||
|
||||
// Add exclude type barriers.
|
||||
if (callInfo.argsBarrier()) {
|
||||
addTypeBarrier(0, callInfo, oracle.thisTypeSet(calleeScript));
|
||||
int32_t max = (callInfo.argc() < callee->nargs) ? callInfo.argc() : callee->nargs;
|
||||
for (int32_t i = 1; i <= max; i++)
|
||||
addTypeBarrier(i, callInfo, oracle.parameterTypeSet(calleeScript, i - 1));
|
||||
}
|
||||
|
||||
LifoAlloc *alloc = GetIonContext()->temp->lifoAlloc();
|
||||
CompileInfo *info = alloc->new_<CompileInfo>(calleeScript.get(), callee,
|
||||
(jsbytecode *)NULL, callInfo.constructing(),
|
||||
this->info().executionMode());
|
||||
if (!info)
|
||||
return false;
|
||||
|
||||
MIRGraphExits saveExits;
|
||||
AutoAccumulateExits aae(graph(), saveExits);
|
||||
|
||||
IonBuilder inlineBuilder(cx, &temp(), &graph(), &oracle,
|
||||
info, inliningDepth + 1, loopDepth_);
|
||||
|
||||
// Create new |this| on the caller-side for inlined constructors.
|
||||
if (callInfo.constructing()) {
|
||||
MDefinition *thisDefn = createThis(callee, callInfo.fun());
|
||||
if (!thisDefn)
|
||||
return false;
|
||||
callInfo.setThis(thisDefn);
|
||||
}
|
||||
|
||||
// Build the graph.
|
||||
if (!inlineBuilder.buildInline(this, inlineResumePoint, callInfo)) {
|
||||
JS_ASSERT(calleeScript->hasAnalysis());
|
||||
|
||||
// Inlining the callee failed. Disable inlining the function
|
||||
if (inlineBuilder.abortReason_ == AbortReason_Disable)
|
||||
calleeScript->analysis()->setIonUninlineable();
|
||||
|
||||
abortReason_ = AbortReason_Inlining;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Replace all MReturns with MGotos, and accumulate them.
|
||||
MIRGraphExits &exits = *inlineBuilder.graph().exitAccumulator();
|
||||
for (MBasicBlock **it = exits.begin(), **end = exits.end(); it != end; ++it) {
|
||||
MDefinition *rdef = patchInlinedReturn(callInfo, *it, bottom);
|
||||
if (!rdef)
|
||||
return false;
|
||||
if (!retvalDefns.append(rdef))
|
||||
return false;
|
||||
}
|
||||
JS_ASSERT(!retvalDefns.empty());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::makeInliningDecision(AutoObjectVector &targets)
|
||||
{
|
||||
@ -3622,23 +3532,33 @@ IonBuilder::inlineScriptedCalls(AutoObjectVector &targets, AutoObjectVector &ori
|
||||
|
||||
// Set the constant function.
|
||||
MConstant *constFun = disp->getFunctionConstant(i);
|
||||
callInfo.fun()->setFoldedUnchecked();
|
||||
callInfo.setFun(constFun);
|
||||
|
||||
// Set the right block active.
|
||||
MBasicBlock *block = disp->getSuccessor(i);
|
||||
graph().moveBlockToEnd(block);
|
||||
current = block;
|
||||
MBasicBlock *inlineBlock = disp->getSuccessor(i);
|
||||
graph().moveBlockToEnd(inlineBlock);
|
||||
|
||||
// Remove formals before inlining.
|
||||
callInfo.popFormals(inlineBlock);
|
||||
|
||||
// Inline call.
|
||||
if (!jsop_call_inline(target, callInfo, inlineBottom, retvalDefns))
|
||||
current = inlineBlock;
|
||||
if (!inlineScriptedCall(target, callInfo))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Regardless of whether inlineBottom != bottom, demarcate these exits
|
||||
// with an Inline_Exit instruction signifying that the inlined functions
|
||||
// on this level have all ceased running.
|
||||
if (instrumentedProfiling())
|
||||
inlineBottom->add(MFunctionBoundary::New(NULL, MFunctionBoundary::Inline_Exit));
|
||||
// Accumulate the return definition.
|
||||
MBasicBlock *returnBlock = current;
|
||||
MDefinition *retvalDefn = returnBlock->peek(-1);
|
||||
if (!retvalDefns.append(retvalDefn))
|
||||
return false;
|
||||
|
||||
// Connect the return block to the bottom.
|
||||
returnBlock->end(MGoto::New(inlineBottom));
|
||||
if (!inlineBottom->addPredecessorWithoutPhis(returnBlock))
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
// In the case where we had to create a new block, all of the returns of
|
||||
// the inline functions need to be merged together with a phi node. This
|
||||
|
@ -459,8 +459,6 @@ class IonBuilder : public MIRGenerator
|
||||
InliningStatus inlineNativeCall(CallInfo &callInfo, JSNative native);
|
||||
|
||||
// Call functions
|
||||
bool jsop_call_inline(HandleFunction callee, CallInfo &callInfo, MBasicBlock *bottom,
|
||||
Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns);
|
||||
bool inlineScriptedCalls(AutoObjectVector &targets, AutoObjectVector &originals,
|
||||
CallInfo &callInfo);
|
||||
bool inlineScriptedCall(HandleFunction target, CallInfo &callInfo);
|
||||
@ -659,7 +657,7 @@ class CallInfo
|
||||
}
|
||||
|
||||
void popFormals(MBasicBlock *current) {
|
||||
current->popn(argc() + 2);
|
||||
current->popn(numFormals());
|
||||
}
|
||||
|
||||
void pushFormals(MBasicBlock *current) {
|
||||
@ -680,9 +678,12 @@ class CallInfo
|
||||
return types_;
|
||||
}
|
||||
|
||||
uint32_t argc() {
|
||||
uint32_t argc() const {
|
||||
return args_.length();
|
||||
}
|
||||
uint32_t numFormals() const {
|
||||
return argc() + 2;
|
||||
}
|
||||
|
||||
void setArgs(Vector<MDefinition *> *args) {
|
||||
JS_ASSERT(args_.length() == 0);
|
||||
|
Loading…
Reference in New Issue
Block a user