mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge.
This commit is contained in:
commit
7515a0583e
@ -97,7 +97,7 @@ static struct {
|
||||
recorderStarted, recorderAborted, traceCompleted, sideExitIntoInterpreter,
|
||||
typeMapMismatchAtEntry, returnToDifferentLoopHeader, traceTriggered,
|
||||
globalShapeMismatchAtEntry, treesTrashed, slotPromoted,
|
||||
unstableLoopVariable;
|
||||
unstableLoopVariable, breakLoopExits;
|
||||
} stat = { 0LL, };
|
||||
#define AUDIT(x) (stat.x++)
|
||||
#else
|
||||
@ -756,9 +756,9 @@ bool
|
||||
TraceRecorder::trackLoopEdges()
|
||||
{
|
||||
jsbytecode* pc = cx->fp->regs->pc;
|
||||
if (loopEdgeList.contains(pc))
|
||||
if (inlinedLoopEdges.contains(pc))
|
||||
return false;
|
||||
loopEdgeList.add(pc);
|
||||
inlinedLoopEdges.add(pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1283,16 +1283,6 @@ js_IsLoopExit(JSContext* cx, JSScript* script, jsbytecode* header, jsbytecode* p
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Determine whether a bytecode location (pc) is a break statement. */
|
||||
bool
|
||||
js_isBreak(JSContext* cx, JSScript* script, jsbytecode* pc)
|
||||
{
|
||||
jssrcnote* sn;
|
||||
return (((*pc == JSOP_GOTO) || (*pc == JSOP_GOTOX)) &&
|
||||
((sn = js_GetSrcNote(cx->fp->script, pc)) != NULL) &&
|
||||
SN_TYPE(sn) == SRC_BREAK);
|
||||
}
|
||||
|
||||
struct FrameInfo {
|
||||
JSObject* callee; // callee function object
|
||||
jsbytecode* callpc; // pc of JSOP_CALL in caller script
|
||||
@ -1536,6 +1526,7 @@ TraceRecorder::compile(Fragmento* fragmento)
|
||||
fragmento->labels->add(fragment, sizeof(Fragment), 0, label);
|
||||
free(label);
|
||||
#endif
|
||||
AUDIT(traceCompleted);
|
||||
}
|
||||
|
||||
/* Complete and compile a trace and link it to the existing tree if appropriate. */
|
||||
@ -1633,6 +1624,35 @@ TraceRecorder::emitTreeCall(Fragment* inner, GuardRecord* lr)
|
||||
((TreeInfo*)inner->vmprivate)->dependentTrees.addUnique(fragment->root);
|
||||
}
|
||||
|
||||
/* Add a if/if-else control-flow merge point to the list of known merge points. */
|
||||
void
|
||||
TraceRecorder::trackCfgMerges(jsbytecode* pc)
|
||||
{
|
||||
/* If we hit the beginning of an if/if-else, then keep track of the merge point after it. */
|
||||
JS_ASSERT((*pc == JSOP_IFEQ) || (*pc == JSOP_IFEQX));
|
||||
jssrcnote* sn = js_GetSrcNote(cx->fp->script, pc);
|
||||
if (sn != NULL) {
|
||||
if (SN_TYPE(sn) == SRC_IF) {
|
||||
cfgMerges.add((*pc == JSOP_IFEQ)
|
||||
? pc + GET_JUMP_OFFSET(pc)
|
||||
: pc + GET_JUMPX_OFFSET(pc));
|
||||
} else if (SN_TYPE(sn) == SRC_IF_ELSE)
|
||||
cfgMerges.add(pc + js_GetSrcNoteOffset(sn, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit code for a fused IFEQ/IFNE. */
|
||||
void
|
||||
TraceRecorder::fuseIf(jsbytecode* pc, bool cond, LIns* x)
|
||||
{
|
||||
if (*pc == JSOP_IFEQ) {
|
||||
guard(cond, x, BRANCH_EXIT);
|
||||
trackCfgMerges(pc);
|
||||
} else if (*pc == JSOP_IFNE) {
|
||||
guard(cond, x, BRANCH_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nanojit::StackFilter::getTop(LInsp guard)
|
||||
{
|
||||
@ -1957,7 +1977,6 @@ js_RecordLoopEdge(JSContext* cx, TraceRecorder* r, jsbytecode* oldpc, uintN& inl
|
||||
js_FlushJITCache(cx);
|
||||
return false; /* done recording */
|
||||
}
|
||||
AUDIT(traceCompleted);
|
||||
r->closeLoop(fragmento);
|
||||
js_DeleteRecorder(cx);
|
||||
return false; /* done recording */
|
||||
@ -2260,15 +2279,19 @@ js_MonitorLoopEdge(JSContext* cx, jsbytecode* oldpc, uintN& inlineCallCount)
|
||||
}
|
||||
|
||||
bool
|
||||
js_MonitorGoto(JSContext* cx)
|
||||
js_MonitorRecording(JSContext* cx)
|
||||
{
|
||||
jsbytecode* pc = cx->fp->regs->pc;
|
||||
/* If we hit a break, end the loop and generate an always taken loop exit guard. For other
|
||||
downward gotos (like if/else) continue recording. */
|
||||
if (js_isBreak(cx, cx->fp->script, cx->fp->regs->pc)) {
|
||||
AUDIT(traceCompleted);
|
||||
JS_TRACE_MONITOR(cx).recorder->endLoop(JS_TRACE_MONITOR(cx).fragmento);
|
||||
js_DeleteRecorder(cx);
|
||||
return false; /* done recording */
|
||||
if ((*pc == JSOP_GOTO) || (*pc == JSOP_GOTOX)) {
|
||||
jssrcnote* sn = js_GetSrcNote(cx->fp->script, pc);
|
||||
if ((sn != NULL) && (SN_TYPE(sn) == SRC_BREAK)) {
|
||||
AUDIT(breakLoopExits);
|
||||
JS_TRACE_MONITOR(cx).recorder->endLoop(JS_TRACE_MONITOR(cx).fragmento);
|
||||
js_DeleteRecorder(cx);
|
||||
return false; /* done recording */
|
||||
}
|
||||
}
|
||||
/* If its not a break, continue recording and follow the trace. */
|
||||
return true;
|
||||
@ -2353,11 +2376,11 @@ js_FinishJIT(JSTraceMonitor *tm)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("recorder: started(%llu), aborted(%llu), completed(%llu), different header(%llu), "
|
||||
"trees trashed(%llu), slot promoted(%llu), "
|
||||
"unstable loop variable(%llu)\n",
|
||||
"trees trashed(%llu), slot promoted(%llu), unstable loop variable(%llu), "
|
||||
"breaks: (%llu)\n",
|
||||
stat.recorderStarted, stat.recorderAborted,
|
||||
stat.traceCompleted, stat.returnToDifferentLoopHeader, stat.treesTrashed,
|
||||
stat.slotPromoted, stat.unstableLoopVariable);
|
||||
stat.slotPromoted, stat.unstableLoopVariable, stat.breakLoopExits);
|
||||
printf("monitor: triggered(%llu), exits(%llu), type mismatch(%llu), "
|
||||
"global mismatch(%llu)\n", stat.traceTriggered, stat.sideExitIntoInterpreter,
|
||||
stat.typeMapMismatchAtEntry, stat.globalShapeMismatchAtEntry);
|
||||
@ -2800,10 +2823,8 @@ TraceRecorder::cmp(LOpcode op, int flags)
|
||||
|
||||
/* The interpreter fuses comparisons and the following branch,
|
||||
so we have to do that here as well. */
|
||||
if (flags & CMP_TRY_BRANCH_AFTER_COND) {
|
||||
if (cx->fp->regs->pc[1] == JSOP_IFEQ || cx->fp->regs->pc[1] == JSOP_IFNE)
|
||||
guard(cond, x, BRANCH_EXIT);
|
||||
}
|
||||
if (flags & CMP_TRY_BRANCH_AFTER_COND)
|
||||
fuseIf(cx->fp->regs->pc + 1, cond, x);
|
||||
|
||||
/* We update the stack after the guard. This is safe since
|
||||
the guard bails out at the comparison and the interpreter
|
||||
@ -3433,6 +3454,7 @@ TraceRecorder::record_JSOP_GOTO()
|
||||
bool
|
||||
TraceRecorder::record_JSOP_IFEQ()
|
||||
{
|
||||
trackCfgMerges(cx->fp->regs->pc);
|
||||
return ifop();
|
||||
}
|
||||
|
||||
@ -5128,8 +5150,7 @@ TraceRecorder::record_JSOP_IN()
|
||||
|
||||
/* The interpreter fuses comparisons and the following branch,
|
||||
so we have to do that here as well. */
|
||||
if (cx->fp->regs->pc[1] == JSOP_IFEQ || cx->fp->regs->pc[1] == JSOP_IFNE)
|
||||
guard(cond, x, BRANCH_EXIT);
|
||||
fuseIf(cx->fp->regs->pc + 1, cond, x);
|
||||
|
||||
/* We update the stack after the guard. This is safe since
|
||||
the guard bails out at the comparison and the interpreter
|
||||
@ -5337,6 +5358,7 @@ TraceRecorder::record_JSOP_GOTOX()
|
||||
bool
|
||||
TraceRecorder::record_JSOP_IFEQX()
|
||||
{
|
||||
trackCfgMerges(cx->fp->regs->pc);
|
||||
return record_JSOP_IFEQ();
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,8 @@ class TraceRecorder {
|
||||
nanojit::SideExit exit;
|
||||
bool trashTree;
|
||||
nanojit::Fragment* whichTreeToTrash;
|
||||
Queue<jsbytecode*> loopEdgeList;
|
||||
Queue<jsbytecode*> inlinedLoopEdges;
|
||||
Queue<jsbytecode*> cfgMerges;
|
||||
|
||||
bool isGlobal(jsval* p) const;
|
||||
ptrdiff_t nativeGlobalOffset(jsval* p) const;
|
||||
@ -323,6 +324,8 @@ class TraceRecorder {
|
||||
bool interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc);
|
||||
bool forInLoop(jsval* vp);
|
||||
|
||||
void trackCfgMerges(jsbytecode* pc);
|
||||
void fuseIf(jsbytecode* pc, bool cond, nanojit::LIns* x);
|
||||
public:
|
||||
TraceRecorder(JSContext* cx, nanojit::GuardRecord*, nanojit::Fragment*, TreeInfo*,
|
||||
unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap,
|
||||
@ -357,22 +360,20 @@ public:
|
||||
#define RECORD(x) \
|
||||
JS_BEGIN_MACRO \
|
||||
TraceRecorder* r = JS_TRACE_MONITOR(cx).recorder; \
|
||||
if (!js_MonitorRecording(cx)) { \
|
||||
ENABLE_TRACER(0); \
|
||||
} else \
|
||||
if (!r->record_##x()) { \
|
||||
js_AbortRecording(cx, NULL, #x); \
|
||||
ENABLE_TRACER(0); \
|
||||
} \
|
||||
jsbytecode* pc = cx->fp->regs->pc; \
|
||||
if (((*pc == JSOP_GOTO) || (*pc == JSOP_GOTOX)) && \
|
||||
!js_MonitorGoto(cx)) { \
|
||||
ENABLE_TRACER(0); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
extern bool
|
||||
js_MonitorLoopEdge(JSContext* cx, jsbytecode* oldpc, uintN& inlineCallCount);
|
||||
|
||||
extern bool
|
||||
js_MonitorGoto(JSContext* cx);
|
||||
js_MonitorRecording(JSContext* cx);
|
||||
|
||||
extern void
|
||||
js_AbortRecording(JSContext* cx, jsbytecode* abortpc, const char* reason);
|
||||
|
Loading…
Reference in New Issue
Block a user