mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
[INFER] Don't fold CALLPROP pushed value in SSA analysis, force out entries for popped values when returning from inlined calls, bug 653962.
This commit is contained in:
parent
4995d87bb4
commit
efa5cac9d0
@ -1442,7 +1442,6 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
|||||||
|
|
||||||
case JSOP_FORNAME:
|
case JSOP_FORNAME:
|
||||||
case JSOP_FORGNAME:
|
case JSOP_FORGNAME:
|
||||||
case JSOP_CALLPROP:
|
|
||||||
stack[stackDepth - 1] = code->poppedValues[0];
|
stack[stackDepth - 1] = code->poppedValues[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1826,6 +1825,21 @@ CrossScriptSSA::foldValue(const CrossSSAValue &cv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case JSOP_CALLPROP: {
|
||||||
|
/*
|
||||||
|
* The second value pushed by CALLPROP is the same as its popped
|
||||||
|
* value. We don't do this folding during the SSA analysis itself
|
||||||
|
* as we still need to distinguish the two values during type
|
||||||
|
* inference --- any popped null or undefined value will throw an
|
||||||
|
* exception, and not actually end up in the pushed set.
|
||||||
|
*/
|
||||||
|
if (v.pushedIndex() == 1) {
|
||||||
|
ScriptAnalysis *analysis = frame.script->analysis(cx);
|
||||||
|
return foldValue(CrossSSAValue(cv.frame, analysis->poppedValue(pc, 0)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,19 +657,25 @@ FrameState::syncForAllocation(RegisterAllocation *alloc, bool inlineReturn, Uses
|
|||||||
* call returns.
|
* call returns.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FrameEntry *topEntry;
|
FrameEntry *topEntry = NULL;
|
||||||
if (inlineReturn)
|
if (inlineReturn)
|
||||||
topEntry = a->parent->sp - (GET_ARGC(a->parent->PC) + 2);
|
topEntry = a->parent->sp - (GET_ARGC(a->parent->PC) + 2);
|
||||||
else
|
|
||||||
topEntry = a->sp - uses.nuses;
|
|
||||||
|
|
||||||
for (uint32 i = tracker.nentries - 1; i < tracker.nentries; i--) {
|
for (uint32 i = tracker.nentries - 1; i < tracker.nentries; i--) {
|
||||||
FrameEntry *fe = tracker[i];
|
FrameEntry *fe = tracker[i];
|
||||||
|
|
||||||
if (deadEntry(fe))
|
if (deadEntry(fe, uses.nuses))
|
||||||
continue;
|
continue;
|
||||||
if (!isTemporary(fe) && fe >= topEntry) {
|
if (topEntry && fe >= topEntry && !isTemporary(fe)) {
|
||||||
/* No need to sync, this will get popped before branching. */
|
/*
|
||||||
|
* The return value has already been stored, so there is no need to
|
||||||
|
* keep any of the entries for this frame or for values popped once
|
||||||
|
* the call returns intact. Forcibly evict any registers for these,
|
||||||
|
* so that we don't emit sync code for them if we need a register
|
||||||
|
* in syncFe below.
|
||||||
|
*/
|
||||||
|
forgetAllRegs(fe);
|
||||||
|
fe->resetSynced();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user