зеркало из https://github.com/mozilla/gecko-dev.git
Bug 487676 - Nesting deep-aborting trace calls don't work. r=gal.
--HG-- extra : rebase_source : 436164485bd5e981e5ae8997eed2c371f3ecd77b
This commit is contained in:
Родитель
4d0e6ab006
Коммит
99d96af6fb
|
@ -1690,7 +1690,7 @@ Array_p_join(JSContext* cx, JSObject* obj, JSString *str)
|
|||
{
|
||||
JSAutoTempValueRooter tvr(cx);
|
||||
if (!array_join_sub(cx, obj, TO_STRING, str, tvr.addr())) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return NULL;
|
||||
}
|
||||
return JSVAL_TO_STRING(tvr.value());
|
||||
|
@ -1701,7 +1701,7 @@ Array_p_toString(JSContext* cx, JSObject* obj)
|
|||
{
|
||||
JSAutoTempValueRooter tvr(cx);
|
||||
if (!array_join_sub(cx, obj, TO_STRING, NULL, tvr.addr())) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return NULL;
|
||||
}
|
||||
return JSVAL_TO_STRING(tvr.value());
|
||||
|
@ -2317,7 +2317,7 @@ Array_p_push1(JSContext* cx, JSObject* obj, jsval v)
|
|||
: array_push_slowly(cx, obj, 1, tvr.addr(), tvr.addr())) {
|
||||
return tvr.value();
|
||||
}
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return JSVAL_VOID;
|
||||
}
|
||||
#endif
|
||||
|
@ -2389,7 +2389,7 @@ Array_p_pop(JSContext* cx, JSObject* obj)
|
|||
: array_pop_slowly(cx, obj, tvr.addr())) {
|
||||
return tvr.value();
|
||||
}
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return JSVAL_VOID;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -63,6 +63,12 @@ using namespace nanojit;
|
|||
|
||||
extern jsdouble js_NaN;
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_SetTraceableNativeFailed(JSContext *cx)
|
||||
{
|
||||
js_SetBuiltinError(cx);
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
|
||||
* Do not use bool FASTCALL, use JSBool only!
|
||||
|
|
|
@ -131,7 +131,7 @@ struct JSTraceableNative {
|
|||
* interpreter at the next opcode.
|
||||
*
|
||||
* _FAIL builtins indicate failure or bailing off trace by setting bits in
|
||||
* cx->builtinStatus.
|
||||
* cx->interpState->builtinStatus.
|
||||
*
|
||||
* - If a traceable native's return type contains _RETRY, it can either
|
||||
* succeed, fail with a JS exception, or tell the caller to bail off trace
|
||||
|
@ -154,7 +154,7 @@ struct JSTraceableNative {
|
|||
* JSVAL_RETRY: JSVAL_ERROR_COOKIE
|
||||
*
|
||||
* _RETRY function calls are faster than _FAIL calls. Each _RETRY call
|
||||
* saves a write to cx->bailExit and a read from cx->builtinStatus.
|
||||
* saves two writes to cx->bailExit and a read from state->builtinStatus.
|
||||
*
|
||||
* - All other traceable natives are infallible (e.g. Date.now, Math.log).
|
||||
*
|
||||
|
@ -397,6 +397,10 @@ js_Int32ToId(JSContext* cx, int32 index, jsid* id)
|
|||
return js_ValueToStringId(cx, STRING_TO_JSVAL(str), id);
|
||||
}
|
||||
|
||||
/* Extern version of js_SetBuiltinError. */
|
||||
extern JS_FRIEND_API(void)
|
||||
js_SetTraceableNativeFailed(JSContext *cx);
|
||||
|
||||
#else
|
||||
|
||||
#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold)
|
||||
|
|
|
@ -300,14 +300,6 @@ typedef enum JSRuntimeState {
|
|||
JSRTS_LANDING
|
||||
} JSRuntimeState;
|
||||
|
||||
#ifdef JS_TRACER
|
||||
typedef enum JSBuiltinStatus {
|
||||
JSBUILTIN_OK = 0,
|
||||
JSBUILTIN_BAILED = 1,
|
||||
JSBUILTIN_ERROR = 2
|
||||
} JSBuiltinStatus;
|
||||
#endif
|
||||
|
||||
typedef enum JSBuiltinFunctionId {
|
||||
JSBUILTIN_ObjectToIterator,
|
||||
JSBUILTIN_CallIteratorNext,
|
||||
|
@ -1008,13 +1000,6 @@ struct JSContext {
|
|||
*/
|
||||
InterpState *interpState;
|
||||
VMSideExit *bailExit;
|
||||
|
||||
/*
|
||||
* Used by _FAIL builtins; see jsbuiltins.h. The builtin sets the
|
||||
* JSBUILTIN_BAILED bit if it bails off trace and the JSBUILTIN_ERROR bit
|
||||
* if an error or exception occurred. Cleared on side exit.
|
||||
*/
|
||||
uint32 builtinStatus;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -1697,7 +1697,7 @@ Object_p_hasOwnProperty(JSContext* cx, JSObject* obj, JSString *str)
|
|||
|
||||
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(str), &id) ||
|
||||
!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &v)) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
}
|
||||
|
||||
|
@ -1742,7 +1742,7 @@ Object_p_propertyIsEnumerable(JSContext* cx, JSObject* obj, JSString *str)
|
|||
jsval v;
|
||||
|
||||
if (!js_PropertyIsEnumerable(cx, obj, id, &v)) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
}
|
||||
|
||||
|
|
|
@ -3971,7 +3971,6 @@ js_ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount,
|
|||
VMSideExit** innermostNestedGuardp)
|
||||
{
|
||||
JS_ASSERT(f->root == f && f->code() && f->vmprivate);
|
||||
JS_ASSERT(cx->builtinStatus == 0);
|
||||
|
||||
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||
JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
|
||||
|
@ -3999,6 +3998,7 @@ js_ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount,
|
|||
state->lastTreeExitGuard = NULL;
|
||||
state->lastTreeCallGuard = NULL;
|
||||
state->rpAtLastTreeCall = NULL;
|
||||
state->builtinStatus = 0;
|
||||
|
||||
/* Setup the native global frame. */
|
||||
double* global = (double*)(state+1);
|
||||
|
@ -4120,8 +4120,7 @@ LeaveTree(InterpState& state, VMSideExit* lr)
|
|||
JS_ASSERT(state.lastTreeExitGuard->exitType != NESTED_EXIT);
|
||||
}
|
||||
|
||||
int32_t bs = cx->builtinStatus;
|
||||
cx->builtinStatus = 0;
|
||||
int32_t bs = state.builtinStatus;
|
||||
bool bailed = innermost->exitType == STATUS_EXIT && (bs & JSBUILTIN_BAILED);
|
||||
if (bailed) {
|
||||
/*
|
||||
|
@ -4135,7 +4134,7 @@ LeaveTree(InterpState& state, VMSideExit* lr)
|
|||
/*
|
||||
* The native succeeded (no exception or error). After it returned, the
|
||||
* trace stored the return value (at the top of the native stack) and
|
||||
* then immediately flunked the guard on cx->builtinStatus.
|
||||
* then immediately flunked the guard on state->builtinStatus.
|
||||
*
|
||||
* Now LeaveTree has been called again from the tail of
|
||||
* js_ExecuteTree. We are about to return to the interpreter. Adjust
|
||||
|
@ -4943,7 +4942,7 @@ js_DeepBail(JSContext *cx)
|
|||
JS_TRACE_MONITOR(cx).prohibitRecording = true;
|
||||
LeaveTree(*cx->interpState, cx->bailExit);
|
||||
cx->bailExit = NULL;
|
||||
cx->builtinStatus |= JSBUILTIN_BAILED;
|
||||
cx->interpState->builtinStatus |= JSBUILTIN_BAILED;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK jsval&
|
||||
|
@ -7460,7 +7459,7 @@ GetProperty_tn(JSContext *cx, jsbytecode *pc, JSObject *obj, JSString *name)
|
|||
|
||||
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(name), idr.addr()) ||
|
||||
!OBJ_GET_PROPERTY(cx, obj, idr.id(), tvr.addr())) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
*tvr.addr() = JSVAL_ERROR_COOKIE;
|
||||
}
|
||||
return tvr.value();
|
||||
|
@ -7489,11 +7488,11 @@ GetElement_tn(JSContext* cx, jsbytecode *pc, JSObject* obj, int32 index)
|
|||
JSAutoTempIdRooter idr(cx);
|
||||
|
||||
if (!js_Int32ToId(cx, index, idr.addr())) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return JSVAL_ERROR_COOKIE;
|
||||
}
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, idr.id(), tvr.addr())) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
*tvr.addr() = JSVAL_ERROR_COOKIE;
|
||||
}
|
||||
return tvr.value();
|
||||
|
@ -7604,7 +7603,7 @@ SetProperty_tn(JSContext* cx, JSObject* obj, JSString* idstr, jsval v)
|
|||
|
||||
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), idr.addr()) ||
|
||||
!OBJ_SET_PROPERTY(cx, obj, idr.id(), tvr.addr())) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
}
|
||||
return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID);
|
||||
}
|
||||
|
@ -7635,7 +7634,7 @@ SetElement_tn(JSContext* cx, JSObject* obj, int32 index, jsval v)
|
|||
|
||||
if (!js_Int32ToId(cx, index, idr.addr()) ||
|
||||
!OBJ_SET_PROPERTY(cx, obj, idr.id(), tvr.addr())) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
}
|
||||
return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID);
|
||||
}
|
||||
|
@ -8045,7 +8044,7 @@ TraceRecorder::record_FastNativeCallComplete()
|
|||
// Keep cx->bailExit null when it's invalid.
|
||||
lir->insStorei(INS_CONSTPTR(NULL), cx_ins, (int) offsetof(JSContext, bailExit));
|
||||
|
||||
LIns* status = lir->insLoad(LIR_ld, cx_ins, (int) offsetof(JSContext, builtinStatus));
|
||||
LIns* status = lir->insLoad(LIR_ld, lirbuf->state, (int) offsetof(InterpState, builtinStatus));
|
||||
if (pendingTraceableNative == generatedTraceableNative) {
|
||||
LIns* ok_ins = v_ins;
|
||||
|
||||
|
@ -8083,7 +8082,7 @@ TraceRecorder::record_FastNativeCallComplete()
|
|||
lir->ins2i(LIR_and, ok_ins, 1),
|
||||
1),
|
||||
1));
|
||||
lir->insStorei(status, cx_ins, (int) offsetof(JSContext, builtinStatus));
|
||||
lir->insStorei(status, lirbuf->state, (int) offsetof(InterpState, builtinStatus));
|
||||
}
|
||||
guard(true,
|
||||
lir->ins_eq0(status),
|
||||
|
@ -9758,7 +9757,7 @@ ObjectToIterator_tn(JSContext* cx, jsbytecode* pc, JSObject *obj, int32 flags)
|
|||
JSBool ok = js_ValueToIterator(cx, flags, &v);
|
||||
|
||||
if (!ok) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return NULL;
|
||||
}
|
||||
return JSVAL_TO_OBJECT(v);
|
||||
|
@ -9777,7 +9776,7 @@ CallIteratorNext_tn(JSContext* cx, jsbytecode* pc, JSObject* iterobj)
|
|||
JSBool ok = js_CallIteratorNext(cx, iterobj, tvr.addr());
|
||||
|
||||
if (!ok) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
js_SetBuiltinError(cx);
|
||||
return JSVAL_ERROR_COOKIE;
|
||||
}
|
||||
return tvr.value();
|
||||
|
|
|
@ -341,6 +341,11 @@ public:
|
|||
# define EXECUTE_TREE_TIMER
|
||||
#endif
|
||||
|
||||
typedef enum JSBuiltinStatus {
|
||||
JSBUILTIN_BAILED = 1,
|
||||
JSBUILTIN_ERROR = 2
|
||||
} JSBuiltinStatus;
|
||||
|
||||
struct InterpState
|
||||
{
|
||||
double *sp; // native stack pointer, stack[0] is spbase[0]
|
||||
|
@ -356,7 +361,7 @@ struct InterpState
|
|||
double* stackBase; // native stack base
|
||||
FrameInfo** callstackBase; // call stack base
|
||||
uintN* inlineCallCountp; // inline call count counter
|
||||
VMSideExit** innermostNestedGuardp;
|
||||
VMSideExit** innermostNestedGuardp;
|
||||
void* stackMark;
|
||||
VMSideExit* innermost;
|
||||
#ifdef EXECUTE_TREE_TIMER
|
||||
|
@ -365,8 +370,21 @@ struct InterpState
|
|||
#ifdef DEBUG
|
||||
bool jsframe_pop_blocks_set_on_entry;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Used by _FAIL builtins; see jsbuiltins.h. The builtin sets the
|
||||
* JSBUILTIN_BAILED bit if it bails off trace and the JSBUILTIN_ERROR bit
|
||||
* if an error or exception occurred.
|
||||
*/
|
||||
uint32 builtinStatus;
|
||||
};
|
||||
|
||||
static JS_INLINE void
|
||||
js_SetBuiltinError(JSContext *cx)
|
||||
{
|
||||
cx->interpState->builtinStatus |= JSBUILTIN_ERROR;
|
||||
}
|
||||
|
||||
enum JSMonitorRecordingStatus {
|
||||
JSMRS_CONTINUE,
|
||||
JSMRS_STOP,
|
||||
|
|
|
@ -871,7 +871,7 @@ def getTraceInfoDefaultReturn(type):
|
|||
def getFailureString(retval, indent):
|
||||
assert indent > 0
|
||||
ret = " " * (4 * indent)
|
||||
ret += "cx->builtinStatus |= JSBUILTIN_ERROR;\n"
|
||||
ret += "js_SetTraceableNativeFailed(cx);\n"
|
||||
ret += " " * (4 * indent)
|
||||
ret += "return %s;\n" % retval
|
||||
ret += " " * (4 * (indent - 1))
|
||||
|
|
Загрузка…
Ссылка в новой задаче