mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Added end-of-trace detection and make sure trace loops back to the loop header.
This commit is contained in:
parent
2270a14eb0
commit
6d192a7054
@ -2782,17 +2782,9 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
# endif
|
||||
# define ABORT_TRACE(x) \
|
||||
REPORT_ABORT(x); \
|
||||
goto abort_trace;
|
||||
# define ABORT_TRACE_IF_ERROR \
|
||||
JS_BEGIN_MACRO \
|
||||
if (js_GetRecorderError(cx)) { \
|
||||
REPORT_ABORT("recorder error"); \
|
||||
goto abort_trace; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
goto abort_recording;
|
||||
#else
|
||||
# define ABORT_TRACE(x) ((void)0)
|
||||
# define ABORT_TRACE_IF_ERROR ((void)0)
|
||||
#endif
|
||||
|
||||
#if JS_THREADED_INTERP
|
||||
@ -2811,7 +2803,6 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
};
|
||||
|
||||
# define DO_OP() JS_BEGIN_MACRO \
|
||||
ABORT_TRACE_IF_ERROR; \
|
||||
JS_EXTENSION_(goto *jumpTable[op]); \
|
||||
JS_END_MACRO
|
||||
# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
|
||||
@ -2835,7 +2826,6 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
#else /* !JS_THREADED_INTERP */
|
||||
|
||||
# define DO_OP() JS_BEGIN_MACRO \
|
||||
ABORT_TRACE_IF_ERROR; \
|
||||
goto do_op; \
|
||||
JS_END_MACRO
|
||||
# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
|
||||
@ -2937,11 +2927,18 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
if (ENABLE_TRACER && \
|
||||
(JS_TRACE_MONITOR(cx).freq++ & TRACE_TRIGGER_MASK) == 0) { \
|
||||
regs.pc += n; \
|
||||
goto attempt_tracing; \
|
||||
goto attempt_recording; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
# define MONITOR_BRANCH(n) ((void)0)
|
||||
# define MONITOR_BRANCH(n) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (ENABLE_TRACER && \
|
||||
JS_TRACE_MONITOR(cx).status == RECORDING && \
|
||||
JS_TRACE_MONITOR(cx).entryState.pc == (regs.pc + n)) { \
|
||||
goto end_recording; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -7004,8 +7001,18 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
SAVE_STATE(state, JS_NEXT_ERROR);
|
||||
return JS_FALSE;
|
||||
|
||||
abort_trace:
|
||||
js_StopRecorder(cx, regs);
|
||||
abort_recording:
|
||||
#ifdef DEBUG
|
||||
printf("Abort recording.\n");
|
||||
#endif
|
||||
JS_TRACE_MONITOR(cx).status = ABORTED;
|
||||
/* fall through */
|
||||
|
||||
end_recording:
|
||||
#ifdef DEBUG
|
||||
printf("End recording.\n");
|
||||
#endif
|
||||
js_EndRecording(cx, regs);
|
||||
SAVE_STATE(state, JS_NEXT_CONTINUE);
|
||||
return ok;
|
||||
#else
|
||||
@ -7225,10 +7232,13 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
}
|
||||
|
||||
#ifndef jstracer_cpp___
|
||||
attempt_tracing:
|
||||
attempt_recording:
|
||||
{
|
||||
js_StartRecorder(cx, regs);
|
||||
if (js_GetRecorderError(cx)) {
|
||||
#ifdef DEBUG
|
||||
printf("Attempt recording.\n");
|
||||
#endif
|
||||
js_StartRecording(cx, regs);
|
||||
if (JS_TRACE_MONITOR(cx).status != RECORDING) {
|
||||
op = (JSOp) *regs.pc;
|
||||
DO_OP();
|
||||
}
|
||||
|
@ -144,8 +144,48 @@ static struct CallInfo builtins[] = {
|
||||
#undef BUILTIN2
|
||||
#undef BUILTIN3
|
||||
|
||||
struct BoxOpTable {
|
||||
int32_t box;
|
||||
int32_t unbox;
|
||||
};
|
||||
|
||||
static BoxOpTable boxOpTable[] = {
|
||||
{F_UNBOX_BOOLEAN, F_BOX_BOOLEAN},
|
||||
{F_UNBOX_STRING, F_BOX_STRING},
|
||||
{F_UNBOX_OBJECT, F_BOX_OBJECT},
|
||||
{F_UNBOX_INT, F_BOX_INT},
|
||||
{F_UNBOX_DOUBLE, F_BOX_DOUBLE}
|
||||
};
|
||||
|
||||
// This filter eliminates redundant boxing.
|
||||
class BoxFilter: public LirWriter
|
||||
{
|
||||
LInsp check(int32_t fid, LInsp args[], int32_t first, int32_t second) {
|
||||
if (fid == first) {
|
||||
LInsp a = args[0];
|
||||
if (a->isop(LIR_call) && (a->imm8() == second))
|
||||
return a[-1].oprnd1();
|
||||
}
|
||||
return (LInsp)0;
|
||||
}
|
||||
|
||||
public:
|
||||
BoxFilter(LirWriter* out): LirWriter(out)
|
||||
{
|
||||
}
|
||||
|
||||
LInsp insCall(int32_t fid, LInsp args[])
|
||||
{
|
||||
LInsp p;
|
||||
for (uint32 n = 0; n < sizeof(boxOpTable)/sizeof(struct BoxOpTable); ++n)
|
||||
if ((p = check(fid, args, boxOpTable[n].unbox, boxOpTable[n].box)) != 0)
|
||||
return p;
|
||||
return out->insCall(fid, args);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
js_StartRecorder(JSContext* cx, JSFrameRegs& regs)
|
||||
js_StartRecording(JSContext* cx, JSFrameRegs& regs)
|
||||
{
|
||||
struct JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||
|
||||
@ -156,6 +196,8 @@ js_StartRecorder(JSContext* cx, JSFrameRegs& regs)
|
||||
tm->fragmento = fragmento;
|
||||
}
|
||||
|
||||
memcpy(&tm->entryState, ®s, sizeof(regs));
|
||||
|
||||
InterpState state;
|
||||
state.ip = NULL;
|
||||
state.sp = NULL;
|
||||
@ -167,6 +209,7 @@ js_StartRecorder(JSContext* cx, JSFrameRegs& regs)
|
||||
lirbuf->names = new (&gc) LirNameMap(&gc, builtins, tm->fragmento->labels);
|
||||
fragment->lirbuf = lirbuf;
|
||||
LirWriter* lir = new (&gc) LirBufWriter(lirbuf);
|
||||
lir = new (&gc) BoxFilter(lir);
|
||||
lir->ins0(LIR_trace);
|
||||
fragment->param0 = lir->insImm8(LIR_param, Assembler::argRegs[0], 0);
|
||||
fragment->param1 = lir->insImm8(LIR_param, Assembler::argRegs[1], 0);
|
||||
@ -187,24 +230,17 @@ js_StartRecorder(JSContext* cx, JSFrameRegs& regs)
|
||||
|
||||
tm->fragment = fragment;
|
||||
tm->lir = lir;
|
||||
|
||||
tm->status = RECORDING;
|
||||
}
|
||||
|
||||
void
|
||||
js_StopRecorder(JSContext* cx, JSFrameRegs& regs)
|
||||
js_EndRecording(JSContext* cx, JSFrameRegs& regs)
|
||||
{
|
||||
struct JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||
|
||||
SideExit exit;
|
||||
memset(&exit, 0, sizeof(exit));
|
||||
exit.from = tm->fragment;
|
||||
tm->fragment->lastIns = tm->lir->insGuard(LIR_x, NULL, &exit);
|
||||
compile(tm->fragmento->assm(), tm->fragment);
|
||||
if (tm->status == RECORDING) {
|
||||
tm->fragment->lastIns = tm->lir->ins0(LIR_loop);
|
||||
compile(tm->fragmento->assm(), tm->fragment);
|
||||
}
|
||||
tm->status = IDLE;
|
||||
}
|
||||
|
||||
bool
|
||||
js_GetRecorderError(JSContext* cx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,6 +74,10 @@ public:
|
||||
void clear();
|
||||
};
|
||||
|
||||
enum TraceRecorderStatus {
|
||||
IDLE, RECORDING, ABORTED
|
||||
};
|
||||
|
||||
/*
|
||||
* Trace monitor. Every runtime is associated with a trace monitor that keeps
|
||||
* track of loop frequencies for all JavaScript code loaded into that runtime.
|
||||
@ -86,6 +90,8 @@ public:
|
||||
*/
|
||||
struct JSTraceMonitor {
|
||||
int freq;
|
||||
TraceRecorderStatus status;
|
||||
JSFrameRegs entryState;
|
||||
Tracker tracker;
|
||||
nanojit::Fragment* fragment;
|
||||
nanojit::Fragmento* fragmento;
|
||||
@ -96,12 +102,9 @@ struct JSTraceMonitor {
|
||||
#define TRACE_TRIGGER_MASK 0x3f
|
||||
|
||||
extern void
|
||||
js_StartRecorder(JSContext* cx, JSFrameRegs& regs);
|
||||
js_StartRecording(JSContext* cx, JSFrameRegs& regs);
|
||||
|
||||
extern void
|
||||
js_StopRecorder(JSContext* cx, JSFrameRegs& regs);
|
||||
|
||||
extern bool
|
||||
js_GetRecorderError(JSContext* cx);
|
||||
js_EndRecording(JSContext* cx, JSFrameRegs& regs);
|
||||
|
||||
#endif /* jstracer_h___ */
|
||||
|
Loading…
Reference in New Issue
Block a user