mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Allocate recorder dynamically to avoid having a vtable in the struct holding the reference. Emit writebacks for every update to the tracker, not just stack writes.
This commit is contained in:
parent
407b9cdf75
commit
5b4f0aaeaa
@ -2934,8 +2934,8 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
# 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)) { \
|
||||
JS_TRACE_MONITOR(cx).recorder != NULL && \
|
||||
JS_TRACE_MONITOR(cx).recorder->entryState.pc == (regs.pc + n)) { \
|
||||
goto end_recording; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
@ -7005,7 +7005,8 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
#ifdef DEBUG
|
||||
printf("Abort recording.\n");
|
||||
#endif
|
||||
JS_TRACE_MONITOR(cx).status = ABORTED;
|
||||
delete JS_TRACE_MONITOR(cx).recorder;
|
||||
JS_TRACE_MONITOR(cx).recorder = NULL;
|
||||
/* fall through */
|
||||
|
||||
end_recording:
|
||||
@ -7237,8 +7238,7 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
|
||||
#ifdef DEBUG
|
||||
printf("Attempt recording.\n");
|
||||
#endif
|
||||
js_StartRecording(cx, regs);
|
||||
if (JS_TRACE_MONITOR(cx).status != RECORDING) {
|
||||
if (!js_StartRecording(cx, regs)) {
|
||||
op = (JSOp) *regs.pc;
|
||||
DO_OP();
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ template <typename T> void
|
||||
Tracker<T>::set(const void* v, T i)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
//printf("set %p to %s\n", v, nanojit::lirNames[ins->opcode()]);
|
||||
//printf("set %p to %s\n", v, nanojit::lirNames[i->opcode()]);
|
||||
#endif
|
||||
struct Tracker::Page* p = findPage(v);
|
||||
if (!p)
|
||||
@ -154,11 +154,11 @@ static struct CallInfo builtins[] = {
|
||||
#undef BUILTIN2
|
||||
#undef BUILTIN3
|
||||
|
||||
void
|
||||
bool
|
||||
js_StartRecording(JSContext* cx, JSFrameRegs& regs)
|
||||
{
|
||||
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||
|
||||
|
||||
if (!tm->fragmento) {
|
||||
Fragmento* fragmento = new (&gc) Fragmento(core);
|
||||
#ifdef DEBUG
|
||||
@ -168,7 +168,8 @@ js_StartRecording(JSContext* cx, JSFrameRegs& regs)
|
||||
tm->fragmento = fragmento;
|
||||
}
|
||||
|
||||
memcpy(&tm->entryState, ®s, sizeof(regs));
|
||||
JSTraceRecorder* recorder = new JSTraceRecorder(regs);
|
||||
tm->recorder = recorder;
|
||||
|
||||
InterpState state;
|
||||
state.ip = NULL;
|
||||
@ -188,32 +189,37 @@ js_StartRecording(JSContext* cx, JSFrameRegs& regs)
|
||||
fragment->param1 = lir->insImm8(LIR_param, Assembler::argRegs[1], 0);
|
||||
JSStackFrame* fp = cx->fp;
|
||||
|
||||
tm->tracker.set(cx, fragment->param0);
|
||||
recorder->tracker.set(cx, lir->insLoadi(fragment->param0, 0));
|
||||
recorder->tracker.set(&recorder->entryState.sp, lir->insLoadi(fragment->param0, 4));
|
||||
|
||||
#define LOAD_CONTEXT(p) \
|
||||
tm->tracker.set(p, lir->insLoadi(fragment->param1, STACK_OFFSET(p)))
|
||||
#define LOAD_CONTEXT(p) \
|
||||
recorder->tracker.set(p, \
|
||||
lir->insLoadi(recorder->tracker.get(&recorder->entryState.sp), \
|
||||
STACK_OFFSET(p)))
|
||||
|
||||
unsigned n;
|
||||
for (n = 0; n < fp->argc; ++n)
|
||||
LOAD_CONTEXT(&fp->argv[n]);
|
||||
for (n = 0; n < fp->nvars; ++n)
|
||||
for (n = 0; n < fp->nvars; ++n)
|
||||
LOAD_CONTEXT(&fp->vars[n]);
|
||||
for (n = 0; n < (unsigned)(regs.sp - fp->spbase); ++n)
|
||||
LOAD_CONTEXT(&fp->spbase[n]);
|
||||
|
||||
tm->fragment = fragment;
|
||||
tm->lir = lir;
|
||||
recorder->fragment = fragment;
|
||||
recorder->lir = lir;
|
||||
|
||||
tm->status = RECORDING;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
js_EndRecording(JSContext* cx, JSFrameRegs& regs)
|
||||
{
|
||||
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||
if (tm->status == RECORDING) {
|
||||
tm->fragment->lastIns = tm->lir->ins0(LIR_loop);
|
||||
compile(tm->fragmento->assm(), tm->fragment);
|
||||
if (tm->recorder != NULL) {
|
||||
JSTraceRecorder* recorder = tm->recorder;
|
||||
recorder->fragment->lastIns = recorder->lir->ins0(LIR_loop);
|
||||
compile(tm->fragmento->assm(), recorder->fragment);
|
||||
delete recorder;
|
||||
tm->recorder = NULL;
|
||||
}
|
||||
tm->status = IDLE;
|
||||
}
|
||||
|
@ -75,8 +75,16 @@ public:
|
||||
void clear();
|
||||
};
|
||||
|
||||
enum TraceRecorderStatus {
|
||||
IDLE, RECORDING, ABORTED
|
||||
class JSTraceRecorder {
|
||||
public:
|
||||
struct JSFrameRegs entryState;
|
||||
Tracker<nanojit::LIns*> tracker;
|
||||
nanojit::Fragment* fragment;
|
||||
nanojit::LirWriter* lir;
|
||||
|
||||
JSTraceRecorder(JSFrameRegs& _entryState) {
|
||||
entryState = _entryState;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@ -91,18 +99,14 @@ enum TraceRecorderStatus {
|
||||
*/
|
||||
struct JSTraceMonitor {
|
||||
int freq;
|
||||
TraceRecorderStatus status;
|
||||
JSFrameRegs entryState;
|
||||
Tracker<nanojit::LIns*> tracker;
|
||||
nanojit::Fragment* fragment;
|
||||
nanojit::Fragmento* fragmento;
|
||||
nanojit::LirWriter* lir;
|
||||
JSTraceRecorder* recorder;
|
||||
};
|
||||
|
||||
#define ENABLE_TRACER true
|
||||
#define TRACE_TRIGGER_MASK 0x3f
|
||||
|
||||
extern void
|
||||
extern bool
|
||||
js_StartRecording(JSContext* cx, JSFrameRegs& regs);
|
||||
|
||||
extern void
|
||||
|
@ -45,10 +45,12 @@
|
||||
|
||||
#undef PRIMITIVE
|
||||
|
||||
#define set(v, l) JS_TRACE_MONITOR(cx).tracker.set(v, l)
|
||||
#define get(v) JS_TRACE_MONITOR(cx).tracker.get(v)
|
||||
#define RECORDER(cx) JS_TRACE_MONITOR(cx).recorder
|
||||
#define set(v, l) RECORDER(cx)->tracker.set(v, l); \
|
||||
writeBack(cx, v, l);
|
||||
#define get(v) RECORDER(cx)->tracker.get(v)
|
||||
#define copy(a, v) set(v, get(a))
|
||||
#define L (*JS_TRACE_MONITOR(cx).lir)
|
||||
#define L (*(RECORDER(cx)->lir))
|
||||
#define F(name) F_##name
|
||||
#define G(ok) (ok ? LIR_xf : LIR_xt)
|
||||
#define unary(op, a, v) set(v, L.ins1(op, get(a)))
|
||||
@ -72,13 +74,28 @@
|
||||
set(v, L.insCall(F(n), args)); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define STACK_OFFSET(p) (((char*)(p)) - ((char*)JS_TRACE_MONITOR(cx).entryState.sp))
|
||||
#define STACK_OFFSET(p) (((char*)(p)) - ((char*)(RECORDER(cx)->entryState.sp)))
|
||||
|
||||
static inline void writeBack(JSContext* cx, void* p, LIns* l)
|
||||
{
|
||||
JSStackFrame* fp = cx->fp;
|
||||
int32_t offset;
|
||||
if ((p >= &fp->argv[0] && p < &fp->argv[fp->argc])) {
|
||||
offset = (int32_t)((jsval*)p - fp->argv);
|
||||
} else if (p >= &fp->vars[0] && p < &fp->vars[fp->nvars]) {
|
||||
offset = (int32_t)((jsval*)p - fp->vars) + fp->argc;
|
||||
} else if (p >= &fp->spbase[0] && p < &fp->spbase[fp->script->depth]) {
|
||||
offset = (int32_t)((jsval*)p - fp->spbase) + fp->argc + fp->nvars;
|
||||
} else
|
||||
return;
|
||||
L.insStorei(l, get(&RECORDER(cx)->entryState.sp), offset);
|
||||
}
|
||||
|
||||
static inline SideExit*
|
||||
snapshot(JSContext* cx, JSFrameRegs& regs, SideExit& exit)
|
||||
{
|
||||
memset(&exit, 0, sizeof(exit));
|
||||
exit.from = JS_TRACE_MONITOR(cx).fragment;
|
||||
exit.from = RECORDER(cx)->fragment;
|
||||
return &exit;
|
||||
}
|
||||
|
||||
@ -93,7 +110,6 @@ static inline void
|
||||
prim_push_stack(JSContext* cx, JSFrameRegs& regs, jsval& v)
|
||||
{
|
||||
set(regs.sp, get(&v));
|
||||
L.insStorei(get(&v), JS_TRACE_MONITOR(cx).fragment->param1, STACK_OFFSET(regs.sp));
|
||||
interp_prim_push_stack(cx, regs, v);
|
||||
}
|
||||
|
||||
@ -109,7 +125,6 @@ prim_store_stack(JSContext* cx, JSFrameRegs& regs, int n, jsval& v)
|
||||
{
|
||||
interp_prim_store_stack(cx, regs, n, v);
|
||||
set(®s.sp[n], get(&v));
|
||||
L.insStorei(get(&v), JS_TRACE_MONITOR(cx).fragment->param1, STACK_OFFSET(®s.sp[n]));
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -594,6 +609,7 @@ prim_do_fast_inc_dec(JSContext* cx, jsval& a, jsval incr, jsval& r)
|
||||
set(&r, L.ins2(LIR_add, get(&a), L.insImm(incr/2)));
|
||||
}
|
||||
|
||||
#undef recorder
|
||||
#undef set
|
||||
#undef get
|
||||
#undef copy
|
||||
|
Loading…
Reference in New Issue
Block a user