mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Factor out most of the remaining code in js_LoopEdge into js_RecordTree and move the code to attach new branches into js_ExecuteTree.
This commit is contained in:
parent
746cb91802
commit
12f1c06952
@ -1330,8 +1330,112 @@ js_SynthesizeFrame(JSContext* cx, const FrameInfo& fi)
|
||||
return newifp;
|
||||
}
|
||||
|
||||
static GuardRecord*
|
||||
js_ExecuteTree(JSContext* cx, Fragment* f)
|
||||
bool
|
||||
js_RecordTree(JSContext* cx, JSTraceMonitor* tm, Fragment* f)
|
||||
{
|
||||
AUDIT(recorderStarted);
|
||||
f->calldepth = 0;
|
||||
f->root = f;
|
||||
/* allocate space to store the LIR for this tree */
|
||||
if (!f->lirbuf) {
|
||||
f->lirbuf = new (&gc) LirBuffer(tm->fragmento, builtins);
|
||||
#ifdef DEBUG
|
||||
f->lirbuf->names = new (&gc) LirNameMap(&gc, builtins, tm->fragmento->labels);
|
||||
#endif
|
||||
}
|
||||
/* create the tree anchor structure */
|
||||
TreeInfo* ti = (TreeInfo*)f->vmprivate;
|
||||
if (!ti) {
|
||||
/* setup the VM-private treeInfo structure for this fragment */
|
||||
ti = new TreeInfo(); // TODO: deallocate when fragment dies
|
||||
f->vmprivate = ti;
|
||||
|
||||
/* determine the native frame layout at the entry point */
|
||||
unsigned entryNativeStackSlots = nativeStackSlots(0/*callDepth*/, cx->fp);
|
||||
ti->entryNativeStackSlots = entryNativeStackSlots;
|
||||
ti->nativeStackBase = (entryNativeStackSlots -
|
||||
(cx->fp->regs->sp - StackBase(cx->fp))) * sizeof(double);
|
||||
ti->maxNativeStackSlots = entryNativeStackSlots;
|
||||
ti->maxCallDepth = 0;
|
||||
|
||||
/* create the list of global properties we want to intern */
|
||||
ti->globalShape = OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->shape;
|
||||
|
||||
/* remember the coerced type of each active slot in the stack type map */
|
||||
ti->stackTypeMap.setLength(entryNativeStackSlots);
|
||||
uint8* m = ti->stackTypeMap.data();
|
||||
FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0/*callDepth*/,
|
||||
*m++ = getCoercedType(*vp);
|
||||
);
|
||||
}
|
||||
JS_ASSERT(ti->entryNativeStackSlots == nativeStackSlots(0/*callDepth*/, cx->fp));
|
||||
|
||||
/* recording primary trace */
|
||||
return js_StartRecorder(cx, NULL, f, ti->globalSlots.length(),
|
||||
ti->globalTypeMap.data(), ti->stackTypeMap.data());
|
||||
}
|
||||
|
||||
static bool
|
||||
js_AttemptToExtendTree(JSContext* cx, GuardRecord* lr, Fragment* f)
|
||||
{
|
||||
JS_ASSERT(lr->from->root == f);
|
||||
|
||||
debug_only(printf("trying to attach another branch to the tree\n");)
|
||||
|
||||
Fragment* c;
|
||||
if (!(c = lr->target)) {
|
||||
c = JS_TRACE_MONITOR(cx).fragmento->createBranch(lr, lr->exit);
|
||||
c->spawnedFrom = lr->guard;
|
||||
c->parent = f;
|
||||
lr->exit->target = c;
|
||||
lr->target = c;
|
||||
c->root = f;
|
||||
}
|
||||
|
||||
if (++c->hits() >= HOTEXIT) {
|
||||
/* start tracing secondary trace from this point */
|
||||
c->lirbuf = f->lirbuf;
|
||||
SideExit* e = lr->exit;
|
||||
unsigned ngslots = e->numGlobalSlots;
|
||||
uint8* globalTypeMap = e->typeMap;
|
||||
uint8* stackTypeMap = globalTypeMap + ngslots;
|
||||
return js_StartRecorder(cx, lr, c, ngslots, globalTypeMap, stackTypeMap);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
js_ContinueRecording(JSContext* cx, TraceRecorder* r, jsbytecode* oldpc)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
if (OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->title.ownercx != cx) {
|
||||
#ifdef DEBUG
|
||||
printf("Global object not owned by this context.\n");
|
||||
#endif
|
||||
return false; /* we stay away from shared global objects */
|
||||
}
|
||||
#endif
|
||||
if (r->isLoopHeader(cx)) { /* did we hit the start point? */
|
||||
AUDIT(traceCompleted);
|
||||
r->closeLoop(JS_TRACE_MONITOR(cx).fragmento);
|
||||
js_DeleteRecorder(cx);
|
||||
return false; /* done recording */
|
||||
}
|
||||
if (++r->backEdgeCount >= MAX_XJUMPS) {
|
||||
AUDIT(returnToDifferentLoopHeader);
|
||||
debug_only(printf("loop edge %d -> %d, header %d\n",
|
||||
oldpc - cx->fp->script->code,
|
||||
cx->fp->regs->pc - cx->fp->script->code,
|
||||
(jsbytecode*)r->getFragment()->root->ip - cx->fp->script->code));
|
||||
js_AbortRecording(cx, oldpc, "Loop edge does not return to header");
|
||||
return false; /* done recording */
|
||||
}
|
||||
return true; /* keep recording (attempting to unroll inner loop) */
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
js_ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount)
|
||||
{
|
||||
AUDIT(traceTriggered);
|
||||
|
||||
@ -1412,125 +1516,6 @@ js_ExecuteTree(JSContext* cx, Fragment* f)
|
||||
|
||||
AUDIT(sideExitIntoInterpreter);
|
||||
|
||||
return lr;
|
||||
}
|
||||
|
||||
static bool
|
||||
js_AttemptToExtendTree(JSContext* cx, GuardRecord* lr, Fragment* f)
|
||||
{
|
||||
JS_ASSERT(lr->from->root == f);
|
||||
|
||||
debug_only(printf("trying to attach another branch to the tree\n");)
|
||||
|
||||
Fragment* c;
|
||||
if (!(c = lr->target)) {
|
||||
c = JS_TRACE_MONITOR(cx).fragmento->createBranch(lr, lr->exit);
|
||||
c->spawnedFrom = lr->guard;
|
||||
c->parent = f;
|
||||
lr->exit->target = c;
|
||||
lr->target = c;
|
||||
c->root = f;
|
||||
}
|
||||
|
||||
if (++c->hits() >= HOTEXIT) {
|
||||
/* start tracing secondary trace from this point */
|
||||
c->lirbuf = f->lirbuf;
|
||||
SideExit* e = lr->exit;
|
||||
unsigned ngslots = e->numGlobalSlots;
|
||||
uint8* globalTypeMap = e->typeMap;
|
||||
uint8* stackTypeMap = globalTypeMap + ngslots;
|
||||
return js_StartRecorder(cx, lr, c, ngslots, globalTypeMap, stackTypeMap);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
js_ContinueRecording(JSContext* cx, TraceRecorder* r, jsbytecode* oldpc)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
if (OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->title.ownercx != cx) {
|
||||
#ifdef DEBUG
|
||||
printf("Global object not owned by this context.\n");
|
||||
#endif
|
||||
return false; /* we stay away from shared global objects */
|
||||
}
|
||||
#endif
|
||||
if (r->isLoopHeader(cx)) { /* did we hit the start point? */
|
||||
AUDIT(traceCompleted);
|
||||
r->closeLoop(JS_TRACE_MONITOR(cx).fragmento);
|
||||
js_DeleteRecorder(cx);
|
||||
return false; /* done recording */
|
||||
}
|
||||
if (++r->backEdgeCount >= MAX_XJUMPS) {
|
||||
AUDIT(returnToDifferentLoopHeader);
|
||||
debug_only(printf("loop edge %d -> %d, header %d\n",
|
||||
oldpc - cx->fp->script->code,
|
||||
cx->fp->regs->pc - cx->fp->script->code,
|
||||
(jsbytecode*)r->getFragment()->root->ip - cx->fp->script->code));
|
||||
js_AbortRecording(cx, oldpc, "Loop edge does not return to header");
|
||||
return false; /* done recording */
|
||||
}
|
||||
return true; /* keep recording (attempting to unroll inner loop) */
|
||||
}
|
||||
|
||||
bool
|
||||
js_LoopEdge(JSContext* cx, jsbytecode* oldpc, uintN& inlineCallCount)
|
||||
{
|
||||
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||
|
||||
/* is the recorder currently active? */
|
||||
if (tm->recorder)
|
||||
return js_ContinueRecording(cx, tm->recorder, oldpc);
|
||||
|
||||
Fragment* f = tm->fragmento->getLoop(cx->fp->regs->pc);
|
||||
if (!f->code()) {
|
||||
if (++f->hits() >= HOTLOOP) {
|
||||
AUDIT(recorderStarted);
|
||||
f->calldepth = 0;
|
||||
f->root = f;
|
||||
/* allocate space to store the LIR for this tree */
|
||||
if (!f->lirbuf) {
|
||||
f->lirbuf = new (&gc) LirBuffer(tm->fragmento, builtins);
|
||||
#ifdef DEBUG
|
||||
f->lirbuf->names = new (&gc) LirNameMap(&gc, builtins, tm->fragmento->labels);
|
||||
#endif
|
||||
}
|
||||
/* create the tree anchor structure */
|
||||
TreeInfo* ti = (TreeInfo*)f->vmprivate;
|
||||
if (!ti) {
|
||||
/* setup the VM-private treeInfo structure for this fragment */
|
||||
ti = new TreeInfo(); // TODO: deallocate when fragment dies
|
||||
f->vmprivate = ti;
|
||||
|
||||
/* determine the native frame layout at the entry point */
|
||||
unsigned entryNativeStackSlots = nativeStackSlots(0/*callDepth*/, cx->fp);
|
||||
ti->entryNativeStackSlots = entryNativeStackSlots;
|
||||
ti->nativeStackBase = (entryNativeStackSlots -
|
||||
(cx->fp->regs->sp - StackBase(cx->fp))) * sizeof(double);
|
||||
ti->maxNativeStackSlots = entryNativeStackSlots;
|
||||
ti->maxCallDepth = 0;
|
||||
|
||||
/* create the list of global properties we want to intern */
|
||||
ti->globalShape = OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->shape;
|
||||
|
||||
/* remember the coerced type of each active slot in the stack type map */
|
||||
ti->stackTypeMap.setLength(entryNativeStackSlots);
|
||||
uint8* m = ti->stackTypeMap.data();
|
||||
FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0/*callDepth*/,
|
||||
*m++ = getCoercedType(*vp);
|
||||
);
|
||||
}
|
||||
JS_ASSERT(ti->entryNativeStackSlots == nativeStackSlots(0/*callDepth*/, cx->fp));
|
||||
|
||||
/* recording primary trace */
|
||||
return js_StartRecorder(cx, NULL, f, ti->globalSlots.length(),
|
||||
ti->globalTypeMap.data(), ti->stackTypeMap.data());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
GuardRecord* lr = js_ExecuteTree(cx, f);
|
||||
|
||||
if (!lr) /* did the tree actually execute? */
|
||||
return false;
|
||||
|
||||
@ -1550,6 +1535,25 @@ js_LoopEdge(JSContext* cx, jsbytecode* oldpc, uintN& inlineCallCount)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
js_LoopEdge(JSContext* cx, jsbytecode* oldpc, uintN& inlineCallCount)
|
||||
{
|
||||
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||
|
||||
/* is the recorder currently active? */
|
||||
if (tm->recorder)
|
||||
return js_ContinueRecording(cx, tm->recorder, oldpc);
|
||||
|
||||
Fragment* f = tm->fragmento->getLoop(cx->fp->regs->pc);
|
||||
if (!f->code()) {
|
||||
if (++f->hits() >= HOTLOOP)
|
||||
return js_RecordTree(cx, tm, f);
|
||||
return false;
|
||||
}
|
||||
|
||||
return js_ExecuteTree(cx, f, inlineCallCount);
|
||||
}
|
||||
|
||||
void
|
||||
js_AbortRecording(JSContext* cx, jsbytecode* abortpc, const char* reason)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user