Use an error property in the recorder instead of a return value to indicate errors and make sure DO_OP aborts the trace once we go into the error state in the tracer.

This commit is contained in:
Andreas Gal 2008-06-11 17:59:28 -07:00
parent 2a34b19f23
commit bb1b206714
4 changed files with 42 additions and 25 deletions

View File

@ -2771,9 +2771,16 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
#endif
#ifdef jstracer_cpp___
# define ABORT_TRACE goto abort_trace
# define ABORT_TRACE \
goto abort_trace;
# define ABORT_TRACE_IF_ERROR \
JS_BEGIN_MACRO \
if (js_GetRecorderError(cx)) \
goto abort_trace; \
JS_END_MACRO
#else
# define ABORT_TRACE
# define ABORT_TRACE ((void*)0)
# define ABORT_TRACE_IF_ERROR ((void*)0)
#endif
#if JS_THREADED_INTERP
@ -2791,7 +2798,10 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
# undef OPDEF
};
# define DO_OP() JS_EXTENSION_(goto *jumpTable[op])
# 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 \
METER_OP_PAIR(op, regs.pc[n]); \
op = (JSOp) *(regs.pc += (n)); \
@ -2812,7 +2822,10 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
#else /* !JS_THREADED_INTERP */
# define DO_OP() goto do_op
# define DO_OP() JS_BEGIN_MACRO \
ABORT_TRACE_IF_ERROR; \
goto do_op; \
JS_END_MACRO
# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
JS_ASSERT((n) == len); \
goto advance_pc; \
@ -2865,6 +2878,9 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
fp = cx->fp;
script = fp->script;
JS_ASSERT(script->length != 0);
/* Make sure ok is initialized. */
ok = false;
if (state)
RESTORE_STATE(state);
@ -6972,13 +6988,11 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
error:
#ifdef jstracer_cpp___
ok = JS_FALSE;
SAVE_STATE(state, JS_NEXT_ERROR);
return JS_FALSE;
abort_trace:
js_CallRecorder(cx, "stop", native_pointer_to_jsval(regs.pc));
ok = JS_FALSE;
SAVE_STATE(state, JS_NEXT_CONTINUE);
return ok;
#else
@ -7201,7 +7215,7 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state)
attempt_tracing:
{
js_CallRecorder(cx, "start", native_pointer_to_jsval(regs.pc));
if (JS_TRACE_MONITOR(cx).error) {
if (js_GetRecorderError(cx)) {
op = (JSOp) *regs.pc;
DO_OP();
}

View File

@ -66,8 +66,6 @@ js_CallRecorder(JSContext* cx, const char* fn, uintN argc, jsval* argv)
JSBool ok =
#endif
JS_CallFunctionName(cx, js_GetRecorder(cx), fn, argc, argv, &rval);
if (rval != JSVAL_TRUE)
JS_TRACE_MONITOR(cx).error = true;
JS_ASSERT(ok);
}
@ -84,3 +82,12 @@ js_CallRecorder(JSContext* cx, const char* name, jsval a, jsval b)
jsval args[] = { a, b };
js_CallRecorder(cx, name, 2, args);
}
bool
js_GetRecorderError(JSContext* cx)
{
jsval error;
return (JS_GetProperty(cx, JS_TRACE_MONITOR(cx).recorder,
"error", &error) != true)
|| (error != JSVAL_FALSE);
}

View File

@ -55,7 +55,6 @@
struct JSTraceMonitor {
int freq;
JSObject* recorder;
bool error;
};
#define TRACE_TRIGGER_MASK 0x3f
@ -64,6 +63,8 @@ void js_CallRecorder(JSContext* cx, const char* fn, uintN argc, jsval* argv);
void js_CallRecorder(JSContext* cx, const char* fn, jsval a);
void js_CallRecorder(JSContext* cx, const char* fn, jsval a, jsval b);
bool js_GetRecorderError(JSContext* cx);
/*
* The recorder needs to keep track of native machine addresses. This mapping
* only works for aligned pointers.

View File

@ -39,35 +39,30 @@
({
start: function(pc, sp) {
this.anchorPC = pc;
this.anchorSP = this.SP = sp;
this.code = [];
this.map = {};
print("Recording at @" + pc);
return true;
this.error = false;
this.anchorPC = pc;
this.anchorSP = this.SP = sp;
this.code = [];
this.map = {};
print("Recording at @" + pc);
},
stop: function(pc) {
print("Recording ended at @" + pc);
},
/* track the data flow through locals */
track: function(from, to) {
this.map[to] = this.map[from];
return true;
this.map[to] = this.map[from];
},
/* emit an IR instruction */
emit: function(x, to) {
this.map[to] = this.code.push(x);
return true;
this.map[to] = this.code.push(x);
},
/* register a change in the stack pointer */
setSP: function(sp) {
this.SP = sp;
return true;
this.SP = sp;
},
/* create a constant and assign it to v */
constant: function(v, c) {
this.emit({ op: "constant", value: c });
return true;
this.emit({ op: "constant", value: c });
}
});