From c79c0bfeef4620e7ea78f0082d4e2d22ef323c5f Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Tue, 10 Jun 2008 22:20:05 -0700 Subject: [PATCH] Added code to switch to the tracer and back. Incomplete and for review only. --- js/src/jsinterp.cpp | 101 +++++++++++++++++++++++---------------- js/src/jsinterp.h | 3 ++ js/src/jsinterpinlines.h | 7 --- js/src/jstracerinlines.h | 6 ++- 4 files changed, 66 insertions(+), 51 deletions(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 3f951f4a969..2455145722a 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -2692,6 +2692,28 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) JSVersion currentVersion, originalVersion; void *mark; JSFrameRegs regs; + +#define SAVE_STATE(s) \ + s->fp = fp; \ + s->script = script; \ + s->inlineCallCount = inlineCallCount; \ + s->atoms = atoms; \ + s->currentVersion = currentVersion; \ + s->originalVersion = originalVersion; \ + s->mark = mark; \ + s->regs = regs; + +#define RESTORE_STATE(s) \ + rt = cx->runtime; \ + fp = s->fp; \ + script = s->script; \ + inlineCallCount = s->inlineCallCount; \ + atoms = s->atoms; \ + currentVersion = s->currentVersion; \ + originalVersion = s->originalVersion; \ + mark = s->mark; \ + regs = s->regs; + JSObject *obj, *obj2, *parent; JSBool ok, cond; jsint len; @@ -2817,17 +2839,8 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) LOAD_INTERRUPT_HANDLER(cx); - rt = cx->runtime; - if (state) { - fp = state->fp; - script = state->script; - inlineCallCount = state->inlineCallCount; - atoms = state->atoms; - currentVersion = state->currentVersion; - originalVersion = state->originalVersion; - mark = state->mark; - regs = state->regs; + RESTORE_STATE(state); op = (JSOp) *regs.pc; DO_OP(); } @@ -2871,24 +2884,27 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) #define LOAD_FUNCTION(PCOFF) \ JS_GET_SCRIPT_FUNCTION(script, GET_FULL_INDEX(PCOFF), fun) -#ifndef MONITOR_BRANCH -#define MONITOR_BRANCH \ - if ((JS_TRACE_MONITOR(cx).freq++ & TRACE_TRIGGER_MASK) == 0) \ - trace_start(cx, regs.pc); -#endif - +#define BRANCH(n) \ + JS_BEGIN_MACRO \ + if (len <= 0) { \ + if ((JS_TRACE_MONITOR(cx).freq++ & TRACE_TRIGGER_MASK) == 0) { \ + regs.pc += len; \ + goto attempt_tracing; \ + } \ + CHECK_BRANCH; \ + } \ + DO_NEXT_OP(n); \ + JS_END_MACRO + /* * Prepare to call a user-supplied branch handler, and abort the script * if it returns false. */ -#define CHECK_BRANCH(len) \ +#define CHECK_BRANCH \ JS_BEGIN_MACRO \ - if (len <= 0) { \ - MONITOR_BRANCH; \ - if ((cx->operationCount -= JSOW_SCRIPT_JUMP) <= 0) { \ - if (!js_ResetOperationCount(cx)) \ - goto error; \ - } \ + if ((cx->operationCount -= JSOW_SCRIPT_JUMP) <= 0) { \ + if (!js_ResetOperationCount(cx)) \ + goto error; \ } \ JS_END_MACRO @@ -3104,7 +3120,7 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) END_CASE(JSOP_LEAVEWITH) BEGIN_CASE(JSOP_RETURN) - CHECK_BRANCH(-1); + CHECK_BRANCH; POP_STACK(fp->rval); /* FALL THROUGH */ @@ -3204,15 +3220,13 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) /* FALL THROUGH */ TRACE_CASE(JSOP_GOTO) len = GET_JUMP_OFFSET(regs.pc); - CHECK_BRANCH(len); - END_VARLEN_CASE + BRANCH(len); TRACE_CASE(JSOP_IFEQ) POP_BOOLEAN(cx, rval, cond); if (!guard_boolean_is_true(cond)) { len = GET_JUMP_OFFSET(regs.pc); - CHECK_BRANCH(len); - DO_NEXT_OP(len); + BRANCH(len); } END_CASE(JSOP_IFEQ) @@ -3220,8 +3234,7 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) POP_BOOLEAN(cx, rval, cond); if (guard_boolean_is_true(cond)) { len = GET_JUMP_OFFSET(regs.pc); - CHECK_BRANCH(len); - DO_NEXT_OP(len); + BRANCH(len); } END_CASE(JSOP_IFNE) @@ -3248,15 +3261,13 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) /* FALL THROUGH */ TRACE_CASE(JSOP_GOTOX) len = GET_JUMPX_OFFSET(regs.pc); - CHECK_BRANCH(len); - END_VARLEN_CASE + BRANCH(len); TRACE_CASE(JSOP_IFEQX) POP_BOOLEAN(cx, rval, cond); if (!guard_boolean_is_true(cond)) { len = GET_JUMPX_OFFSET(regs.pc); - CHECK_BRANCH(len); - DO_NEXT_OP(len); + BRANCH(len); } END_CASE(JSOP_IFEQX) @@ -3264,8 +3275,7 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) POP_BOOLEAN(cx, rval, cond); if (guard_boolean_is_true(cond)) { len = GET_JUMPX_OFFSET(regs.pc); - CHECK_BRANCH(len); - DO_NEXT_OP(len); + BRANCH(len); } END_CASE(JSOP_IFNEX) @@ -3812,8 +3822,7 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) ADJUST_STACK(-1); if (cond) { len = GET_JUMP_OFFSET(regs.pc); - CHECK_BRANCH(len); - DO_NEXT_OP(len); + BRANCH(len); } PUSH_STACK(lval); END_CASE(JSOP_CASE) @@ -3823,8 +3832,7 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) ADJUST_STACK(-1); if (cond) { len = GET_JUMPX_OFFSET(regs.pc); - CHECK_BRANCH(len); - DO_NEXT_OP(len); + BRANCH(len); } PUSH_STACK(lval); END_CASE(JSOP_CASEX) @@ -6627,8 +6635,7 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) ADJUST_STACK(-1); len = GET_JUMP_OFFSET(regs.pc); JS_ASSERT(len < 0); - CHECK_BRANCH(len); - DO_NEXT_OP(len); + BRANCH(len); } ADJUST_STACK(-1); END_CASE(JSOP_ENDFILTER); @@ -7153,6 +7160,16 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) js_ReportIsNotDefined(cx, printable); goto error; } + + attempt_tracing: + { + JSInterpreterState s; + SAVE_STATE(&s); + js_TracingInterpret(cx, &s); + RESTORE_STATE(&s); + op = (JSOp) *regs.pc; + DO_OP(); + } } #endif /* !defined jsinvoke_cpp___ */ diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index b3210974df4..60c3924abaf 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -471,6 +471,9 @@ js_InvokeConstructor(JSContext *cx, uintN argc, jsval *vp); extern JSBool js_Interpret(JSContext *cx, JSInterpreterState *state); +extern JSBool +js_TracingInterpret(JSContext *cx, JSInterpreterState *state); + #define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */ extern JSBool diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index bc5db4c9be5..0b61d84d497 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -457,18 +457,11 @@ PRIMITIVE(guard_both_jsvals_are_string)(jsval& a, jsval& b) static inline void PRIMITIVE(trace_start)(JSContext* cx, jsbytecode* pc) { - //jsval args[] = { native_pointer_to_jsval(pc) }; - //js_CallRecorder(cx, "start", 1, args); } -/* - * Unsupported opcodes trigger a trace stop condition and cause the trace - * recorder to abandon the current trace. - */ static inline void PRIMITIVE(trace_stop)(JSContext* cx, const char* op) { - /* If we are not tracing, this is a no-op. */ } #endif /* jsinterpinlines_h___ */ diff --git a/js/src/jstracerinlines.h b/js/src/jstracerinlines.h index 620e4e5be11..70d7bc8c7f7 100644 --- a/js/src/jstracerinlines.h +++ b/js/src/jstracerinlines.h @@ -414,9 +414,11 @@ guard_both_jsvals_are_string(jsval& a, jsval& b) return interp_guard_both_jsvals_are_string(a, b); } -static inline void -trace_start(JSContext* cx, jsbytecode* pc) +static inline void +trace_start(JSContext* cx, jsbytecode* pc) { + jsval args[] = { native_pointer_to_jsval(pc) }; + js_CallRecorder(cx, "start", 1, args); } static inline void