Bug 623050 - Move tracerState to compartment (r=gal)

This commit is contained in:
Bill McCloskey 2011-01-12 16:56:23 -08:00
Родитель aa680e0883
Коммит 4354ff8bc1
14 изменённых файлов: 209 добавлений и 192 удалений

Просмотреть файл

@ -2060,7 +2060,7 @@ js_ArrayCompPush_tn(JSContext *cx, JSObject *obj, ValueArgType v)
return JS_FALSE;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_ArrayCompPush_tn, CONTEXT, OBJECT,
VALUE, 0, nanojit::ACCSET_STORE_ANY)

Просмотреть файл

@ -163,7 +163,7 @@ struct ClosureVarInfo;
* OBJECT_RETRY_NULL: NULL
*
* _RETRY function calls are faster than _FAIL calls. Each _RETRY call
* saves two writes to cx->bailExit and a read from state->builtinStatus.
* saves two writes to tm->bailExit and a read from state->builtinStatus.
*
* - All other traceable natives are infallible (e.g. Date.now, Math.log).
*

Просмотреть файл

@ -1333,7 +1333,7 @@ js_ReportOutOfMemory(JSContext *cx)
* If we are in a builtin called directly from trace, don't report an
* error. We will retry in the interpreter instead.
*/
if (JS_ON_TRACE(cx) && !cx->bailExit)
if (JS_ON_TRACE(cx) && !JS_TRACE_MONITOR(cx).bailExit)
return;
#endif
@ -1921,8 +1921,8 @@ js_GetCurrentBytecodePC(JSContext* cx)
#ifdef JS_TRACER
if (JS_ON_TRACE(cx)) {
pc = cx->bailExit->pc;
imacpc = cx->bailExit->imacpc;
pc = JS_TRACE_MONITOR(cx).bailExit->pc;
imacpc = JS_TRACE_MONITOR(cx).bailExit->imacpc;
} else
#endif
{
@ -1947,7 +1947,7 @@ js_CurrentPCIsInImacro(JSContext *cx)
#ifdef JS_TRACER
VOUCH_DOES_NOT_REQUIRE_STACK();
if (JS_ON_TRACE(cx))
return cx->bailExit->imacpc != NULL;
return JS_TRACE_MONITOR(cx).bailExit->imacpc != NULL;
return cx->fp()->hasImacropc();
#else
return false;

Просмотреть файл

@ -179,69 +179,6 @@ class ContextAllocPolicy
void reportAllocOverflow() const;
};
/* Holds the execution state during trace execution. */
struct TracerState
{
JSContext* cx; // current VM context handle
double* stackBase; // native stack base
double* sp; // native stack pointer, stack[0] is spbase[0]
double* eos; // first unusable word after the native stack / begin of globals
FrameInfo** callstackBase; // call stack base
void* sor; // start of rp stack
FrameInfo** rp; // call stack pointer
void* eor; // first unusable word after the call stack
VMSideExit* lastTreeExitGuard; // guard we exited on during a tree call
VMSideExit* lastTreeCallGuard; // guard we want to grow from if the tree
// call exit guard mismatched
void* rpAtLastTreeCall; // value of rp at innermost tree call guard
VMSideExit* outermostTreeExitGuard; // the last side exit returned by js_CallTree
TreeFragment* outermostTree; // the outermost tree we initially invoked
uintN* inlineCallCountp; // inline call count counter
VMSideExit** innermostNestedGuardp;
VMSideExit* innermost;
uint64 startTime;
TracerState* prev;
// 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;
// Used to communicate the location of the return value in case of a deep bail.
double* deepBailSp;
// Used when calling natives from trace to root the vp vector.
uintN nativeVpLen;
js::Value* nativeVp;
TracerState(JSContext *cx, TraceMonitor *tm, TreeFragment *ti,
uintN &inlineCallCountp, VMSideExit** innermostNestedGuardp);
~TracerState();
};
/*
* Storage for the execution state and store during trace execution. Generated
* code depends on the fact that the globals begin |MAX_NATIVE_STACK_SLOTS|
* doubles after the stack begins. Thus, on trace, |TracerState::eos| holds a
* pointer to the first global.
*/
struct TraceNativeStorage
{
double stack_global_buf[MAX_NATIVE_STACK_SLOTS + GLOBAL_SLOTS_BUFFER_SIZE];
FrameInfo *callstack_buf[MAX_CALL_STACK_ENTRIES];
double *stack() { return stack_global_buf; }
double *global() { return stack_global_buf + MAX_NATIVE_STACK_SLOTS; }
FrameInfo **callstack() { return callstack_buf; }
};
/* Holds data to track a single globa. */
struct GlobalState {
JSObject* globalObj;
uint32 globalShape;
SlotList* globalSlots;
};
/*
* A StackSegment (referred to as just a 'segment') contains a prev-linked set
* of stack frames and the slots associated with each frame. A segment and its
@ -2015,14 +1952,6 @@ struct JSContext
js::Value iterValue;
#ifdef JS_TRACER
/*
* State for the current tree execution. bailExit is valid if the tree has
* called back into native code via a _FAIL builtin and has not yet bailed,
* else garbage (NULL in debug builds).
*/
js::TracerState *tracerState;
js::VMSideExit *bailExit;
/*
* True if traces may be executed. Invariant: The value of traceJitenabled
* is always equal to the expression in updateJITEnabled below.

Просмотреть файл

@ -792,7 +792,7 @@ CanLeaveTrace(JSContext *cx)
{
JS_ASSERT(JS_ON_TRACE(cx));
#ifdef JS_TRACER
return cx->bailExit != NULL;
return JS_TRACE_MONITOR(cx).bailExit != NULL;
#else
return JS_FALSE;
#endif

Просмотреть файл

@ -80,6 +80,69 @@ typedef HashSet<JSScript *,
DefaultHasher<JSScript *>,
SystemAllocPolicy> TracedScriptSet;
/* Holds the execution state during trace execution. */
struct TracerState
{
JSContext* cx; // current VM context handle
double* stackBase; // native stack base
double* sp; // native stack pointer, stack[0] is spbase[0]
double* eos; // first unusable word after the native stack / begin of globals
FrameInfo** callstackBase; // call stack base
void* sor; // start of rp stack
FrameInfo** rp; // call stack pointer
void* eor; // first unusable word after the call stack
VMSideExit* lastTreeExitGuard; // guard we exited on during a tree call
VMSideExit* lastTreeCallGuard; // guard we want to grow from if the tree
// call exit guard mismatched
void* rpAtLastTreeCall; // value of rp at innermost tree call guard
VMSideExit* outermostTreeExitGuard; // the last side exit returned by js_CallTree
TreeFragment* outermostTree; // the outermost tree we initially invoked
uintN* inlineCallCountp; // inline call count counter
VMSideExit** innermostNestedGuardp;
VMSideExit* innermost;
uint64 startTime;
TracerState* prev;
// 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;
// Used to communicate the location of the return value in case of a deep bail.
double* deepBailSp;
// Used when calling natives from trace to root the vp vector.
uintN nativeVpLen;
js::Value* nativeVp;
TracerState(JSContext *cx, TraceMonitor *tm, TreeFragment *ti,
uintN &inlineCallCountp, VMSideExit** innermostNestedGuardp);
~TracerState();
};
/*
* Storage for the execution state and store during trace execution. Generated
* code depends on the fact that the globals begin |MAX_NATIVE_STACK_SLOTS|
* doubles after the stack begins. Thus, on trace, |TracerState::eos| holds a
* pointer to the first global.
*/
struct TraceNativeStorage
{
double stack_global_buf[MAX_NATIVE_STACK_SLOTS + GLOBAL_SLOTS_BUFFER_SIZE];
FrameInfo *callstack_buf[MAX_CALL_STACK_ENTRIES];
double *stack() { return stack_global_buf; }
double *global() { return stack_global_buf + MAX_NATIVE_STACK_SLOTS; }
FrameInfo **callstack() { return callstack_buf; }
};
/* Holds data to track a single globa. */
struct GlobalState {
JSObject* globalObj;
uint32 globalShape;
SlotList* globalSlots;
};
/*
* Trace monitor. Every JSCompartment has an associated trace monitor
* that keeps track of loop frequencies for all JavaScript code loaded
@ -98,6 +161,14 @@ struct TraceMonitor {
*/
JSContext *tracecx;
/*
* State for the current tree execution. bailExit is valid if the tree has
* called back into native code via a _FAIL builtin and has not yet bailed,
* else garbage (NULL in debug builds).
*/
js::TracerState *tracerState;
js::VMSideExit *bailExit;
/* Counts the number of iterations run by the currently executing trace. */
unsigned iterationCounter;
@ -203,6 +274,9 @@ struct TraceMonitor {
/* Sweep any cache entry pointing to dead GC things. */
void sweep(JSContext *cx);
/* Mark any tracer stacks that are active. */
void mark(JSTracer *trc);
bool outOfMemory() const;
};

Просмотреть файл

@ -1635,15 +1635,6 @@ MarkContext(JSTracer *trc, JSContext *acx)
if (acx->compartment)
acx->compartment->marked = true;
#ifdef JS_TRACER
TracerState* state = acx->tracerState;
while (state) {
if (state->nativeVp)
MarkValueRange(trc, state->nativeVpLen, state->nativeVp, "nativeVp");
state = state->prev;
}
#endif
}
JS_REQUIRES_STACK void
@ -1732,6 +1723,11 @@ MarkRuntime(JSTracer *trc)
while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter))
MarkContext(trc, acx);
#ifdef JS_TRACER
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
(*c)->traceMonitor.mark(trc);
#endif
for (ThreadDataIter i(rt); !i.empty(); i.popFront())
i.threadData()->mark(trc);

Просмотреть файл

@ -3057,7 +3057,7 @@ js_InferFlags(JSContext *cx, uintN defaultFlags)
{
#ifdef JS_TRACER
if (JS_ON_TRACE(cx))
return cx->bailExit->lookupFlags;
return JS_TRACE_MONITOR(cx).bailExit->lookupFlags;
#endif
JS_ASSERT_NOT_ON_TRACE(cx);

Просмотреть файл

@ -1310,8 +1310,8 @@ void
JSObject::generateOwnShape(JSContext *cx)
{
#ifdef JS_TRACER
JS_ASSERT_IF(!parent && JS_ON_TRACE(cx), cx->bailExit);
LeaveTraceIfGlobalObject(cx, this);
JS_ASSERT_IF(!parent && JS_ON_TRACE(cx), JS_TRACE_MONITOR(cx).bailExit);
LeaveTraceIfGlobalObject(cx, this);
/*
* If we are recording, here is where we forget already-guarded shapes.

Просмотреть файл

@ -227,34 +227,37 @@ nanojit::LInsPrinter::accNames[] = {
"sp", // (1 << 1) == ACCSET_STACK
"rp", // (1 << 2) == ACCSET_RSTACK
"cx", // (1 << 3) == ACCSET_CX
"eos", // (1 << 4) == ACCSET_EOS
"alloc", // (1 << 5) == ACCSET_ALLOC
"regs", // (1 << 6) == ACCSET_FRAMEREGS
"sf", // (1 << 7) == ACCSET_STACKFRAME
"rt", // (1 << 8) == ACCSET_RUNTIME
"tm", // (1 << 4) == ACCSET_TM
"eos", // (1 << 5) == ACCSET_EOS
"alloc", // (1 << 6) == ACCSET_ALLOC
"regs", // (1 << 7) == ACCSET_FRAMEREGS
"sf", // (1 << 8) == ACCSET_STACKFRAME
"rt", // (1 << 9) == ACCSET_RUNTIME
"objclasp", // (1 << 9) == ACCSET_OBJ_CLASP
"objflags", // (1 << 10) == ACCSET_OBJ_FLAGS
"objshape", // (1 << 11) == ACCSET_OBJ_SHAPE
"objproto", // (1 << 12) == ACCSET_OBJ_PROTO
"objparent", // (1 << 13) == ACCSET_OBJ_PARENT
"objprivate", // (1 << 14) == ACCSET_OBJ_PRIVATE
"objcapacity", // (1 << 15) == ACCSET_OBJ_CAPACITY
"objslots", // (1 << 16) == ACCSET_OBJ_SLOTS
"objclasp", // (1 << 10) == ACCSET_OBJ_CLASP
"objflags", // (1 << 11) == ACCSET_OBJ_FLAGS
"objshape", // (1 << 12) == ACCSET_OBJ_SHAPE
"objproto", // (1 << 13) == ACCSET_OBJ_PROTO
"objparent", // (1 << 14) == ACCSET_OBJ_PARENT
"objprivate", // (1 << 15) == ACCSET_OBJ_PRIVATE
"objcapacity", // (1 << 16) == ACCSET_OBJ_CAPACITY
"objslots", // (1 << 17) == ACCSET_OBJ_SLOTS
"slots", // (1 << 17) == ACCSET_SLOTS
"tarray", // (1 << 18) == ACCSET_TARRAY
"tdata", // (1 << 19) == ACCSET_TARRAY_DATA
"iter", // (1 << 20) == ACCSET_ITER
"iterprops", // (1 << 21) == ACCSET_ITER_PROPS
"str", // (1 << 22) == ACCSET_STRING
"strmchars", // (1 << 23) == ACCSET_STRING_MCHARS
"typemap", // (1 << 24) == ACCSET_TYPEMAP
"fcslots", // (1 << 25) == ACCSET_FCSLOTS
"argsdata", // (1 << 26) == ACCSET_ARGS_DATA
"slots", // (1 << 18) == ACCSET_SLOTS
"tarray", // (1 << 19) == ACCSET_TARRAY
"tdata", // (1 << 20) == ACCSET_TARRAY_DATA
"iter", // (1 << 21) == ACCSET_ITER
"iterprops", // (1 << 22) == ACCSET_ITER_PROPS
"str", // (1 << 23) == ACCSET_STRING
"strmchars", // (1 << 24) == ACCSET_STRING_MCHARS
"typemap", // (1 << 25) == ACCSET_TYPEMAP
"fcslots", // (1 << 26) == ACCSET_FCSLOTS
"argsdata", // (1 << 27) == ACCSET_ARGS_DATA
"?!" // this entry should never be used, have it just in case
};
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(nanojit::LInsPrinter::accNames) == TM_NUM_USED_ACCS + 1);
#endif
} /* namespace nanojit */
@ -2863,6 +2866,17 @@ TraceMonitor::sweep(JSContext *cx)
recorder->finishAbort("dead GC things");
}
void
TraceMonitor::mark(JSTracer *trc)
{
TracerState* state = tracerState;
while (state) {
if (state->nativeVp)
MarkValueRange(trc, state->nativeVpLen, state->nativeVp, "nativeVp");
state = state->prev;
}
}
/*
* Box a value from the native stack back into the Value format.
*/
@ -3176,7 +3190,7 @@ template<typename T>
inline JSValueType
GetUpvarOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, double* result)
{
TracerState* state = cx->tracerState;
TracerState* state = JS_TRACE_MONITOR(cx).tracerState;
FrameInfo** fip = state->rp + callDepth;
/*
@ -3313,7 +3327,7 @@ GetFromClosure(JSContext* cx, JSObject* call, const ClosureVarInfo* cv, double*
JS_ASSERT(call->isCall());
#ifdef DEBUG
TracerState* state = cx->tracerState;
TracerState* state = JS_TRACE_MONITOR(cx).tracerState;
FrameInfo** fip = state->rp + cv->callDepth;
int32 stackOffset = StackDepthFromCallStack(state, cv->callDepth);
while (--fip > state->callstackBase) {
@ -4425,25 +4439,9 @@ TraceRecorder::copy(VMSideExit* copy)
* executing native code.
*/
static inline bool
ProhibitFlush(JSContext* cx)
ProhibitFlush(TraceMonitor *tm)
{
if (cx->tracerState) // early out if the given is in native code
return true;
JSCList *cl;
#ifdef JS_THREADSAFE
JSThread* thread = cx->thread;
for (cl = thread->contextList.next; cl != &thread->contextList; cl = cl->next)
if (CX_FROM_THREAD_LINKS(cl)->tracerState)
return true;
#else
JSRuntime* rt = cx->runtime;
for (cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next)
if (js_ContextFromLinkField(cl)->tracerState)
return true;
#endif
return false;
return !!tm->tracerState; // don't flush if we're running a trace
}
static void
@ -4461,7 +4459,7 @@ ResetJITImpl(JSContext* cx)
if (tm->profile)
AbortProfiling(cx);
#endif
if (ProhibitFlush(cx)) {
if (ProhibitFlush(tm)) {
debug_only_print0(LC_TMTracer, "Deferring JIT flush due to deep bail.\n");
tm->needFlush = JS_TRUE;
return;
@ -6416,10 +6414,11 @@ TracerState::TracerState(JSContext* cx, TraceMonitor* tm, TreeFragment* f,
builtinStatus(0),
nativeVp(NULL)
{
JS_ASSERT(tm == &JS_TRACE_MONITOR(cx));
JS_ASSERT(!tm->tracecx);
tm->tracecx = cx;
prev = cx->tracerState;
cx->tracerState = this;
prev = tm->tracerState;
tm->tracerState = this;
JS_ASSERT(eos == stackBase + MAX_NATIVE_STACK_SLOTS);
JS_ASSERT(sp < eos);
@ -6446,15 +6445,16 @@ TracerState::~TracerState()
{
JS_ASSERT(!nativeVp);
cx->tracerState = prev;
JS_TRACE_MONITOR(cx).tracecx = NULL;
TraceMonitor *tm = &JS_TRACE_MONITOR(cx);
tm->tracerState = prev;
tm->tracecx = NULL;
}
/* Call |f|, return the exit taken. */
static JS_ALWAYS_INLINE VMSideExit*
ExecuteTrace(JSContext* cx, Fragment* f, TracerState& state)
{
JS_ASSERT(!cx->bailExit);
JS_ASSERT(!JS_TRACE_MONITOR(cx).bailExit);
#ifdef JS_METHODJIT
JS_ASSERT(!TRACE_PROFILER(cx));
#endif
@ -6466,7 +6466,7 @@ ExecuteTrace(JSContext* cx, Fragment* f, TracerState& state)
#else
rec = u.func(&state);
#endif
JS_ASSERT(!cx->bailExit);
JS_ASSERT(!JS_TRACE_MONITOR(cx).bailExit);
return (VMSideExit*)rec->exit;
}
@ -7905,17 +7905,16 @@ DeepBail(JSContext *cx)
* one. (Most callers cannot guarantee that it's cx.)
*/
TraceMonitor *tm = &JS_TRACE_MONITOR(cx);
JSContext *tracecx = tm->tracecx;
/* It's a bug if a non-FAIL_STATUS builtin gets here. */
JS_ASSERT(tracecx->bailExit);
JS_ASSERT(tm->bailExit);
tm->tracecx = NULL;
debug_only_print0(LC_TMTracer, "Deep bail.\n");
LeaveTree(tm, *tracecx->tracerState, tracecx->bailExit);
tracecx->bailExit = NULL;
LeaveTree(tm, *tm->tracerState, tm->bailExit);
tm->bailExit = NULL;
TracerState* state = tracecx->tracerState;
TracerState* state = tm->tracerState;
state->builtinStatus |= BUILTIN_BAILED;
/*
@ -11113,7 +11112,7 @@ TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[],
// pendingSpecializedNative before taking this snapshot.
JS_ASSERT(!pendingSpecializedNative);
// Take snapshot for DeepBail and store it in cx->bailExit.
// Take snapshot for DeepBail and store it in tm->bailExit.
enterDeepBailCall();
}
@ -12002,7 +12001,7 @@ static JSBool FASTCALL
MethodWriteBarrier(JSContext* cx, JSObject* obj, Shape* shape, JSObject* funobj)
{
bool ok = obj->methodWriteBarrier(cx, *shape, ObjectValue(*funobj));
JS_ASSERT(cx->tracerState->builtinStatus == 0);
JS_ASSERT(WasBuiltinSuccessful(cx));
return ok;
}
JS_DEFINE_CALLINFO_4(static, BOOL_RETRY, MethodWriteBarrier, CONTEXT, OBJECT, SHAPE, OBJECT,
@ -12226,9 +12225,9 @@ TraceRecorder::record_SetPropHit(PropertyCacheEntry* entry, const Shape* shape)
JS_REQUIRES_STACK VMSideExit*
TraceRecorder::enterDeepBailCall()
{
// Take snapshot for DeepBail and store it in cx->bailExit.
// Take snapshot for DeepBail and store it in tm->bailExit.
VMSideExit* exit = snapshot(DEEP_BAIL_EXIT);
w.stContextField(w.nameImmpNonGC(exit), bailExit);
w.stTraceMonitorField(w.nameImmpNonGC(exit), bailExit);
// Tell nanojit not to discard or defer stack writes before this call.
w.xbarrier(createGuardRecord(exit));
@ -12241,8 +12240,8 @@ TraceRecorder::enterDeepBailCall()
JS_REQUIRES_STACK void
TraceRecorder::leaveDeepBailCall()
{
// Keep cx->bailExit null when it's invalid.
w.stContextField(w.immpNull(), bailExit);
// Keep tm->bailExit null when it's invalid.
w.stTraceMonitorField(w.immpNull(), bailExit);
}
JS_REQUIRES_STACK void
@ -12339,14 +12338,14 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PIC
bool result = op(cx, obj, obj, id, vp);
if (!result)
SetBuiltinError(cx);
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
/* Try to hit in the cache. */
uint32 slot;
if (picTable->scan(obj->shape(), id, &slot)) {
*vp = obj->getSlot(slot);
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
const Shape *shape;
@ -12366,7 +12365,7 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PIC
picTable->update(obj->shape(), id, shape->slot);
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_5(static, BOOL_FAIL, GetPropertyByName, CONTEXT, OBJECT, STRINGPTR, VALUEPTR,
PICTABLE,
@ -12435,7 +12434,7 @@ GetPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, Value* vp)
SetBuiltinError(cx);
return JS_FALSE;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyByIndex, CONTEXT, OBJECT, INT32, VALUEPTR, 0,
ACCSET_STORE_ANY)
@ -12463,7 +12462,7 @@ GetPropertyById(JSContext* cx, JSObject* obj, jsid id, Value* vp)
SetBuiltinError(cx);
return JS_FALSE;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyById, CONTEXT, OBJECT, JSID, VALUEPTR,
0, ACCSET_STORE_ANY)
@ -12520,7 +12519,7 @@ GetPropertyWithNativeGetter(JSContext* cx, JSObject* obj, Shape* shape, Value* v
SetBuiltinError(cx);
return JS_FALSE;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, GetPropertyWithNativeGetter,
CONTEXT, OBJECT, SHAPE, VALUEPTR, 0, ACCSET_STORE_ANY)
@ -12841,7 +12840,7 @@ SetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, JSB
SetBuiltinError(cx);
return false;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_5(static, BOOL_FAIL, SetPropertyByName,
CONTEXT, OBJECT, STRINGPTR, VALUEPTR, BOOL,
@ -12858,7 +12857,7 @@ InitPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, ValueArgType
SetBuiltinError(cx);
return JS_FALSE;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, InitPropertyByName, CONTEXT, OBJECT, STRINGPTR, VALUE,
0, ACCSET_STORE_ANY)
@ -12897,7 +12896,7 @@ SetPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, Value* vp, JSBool
SetBuiltinError(cx);
return false;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_5(static, BOOL_FAIL, SetPropertyByIndex, CONTEXT, OBJECT, INT32, VALUEPTR, BOOL,
0, ACCSET_STORE_ANY)
@ -12913,7 +12912,7 @@ InitPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, ValueArgType arg)
SetBuiltinError(cx);
return JS_FALSE;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, InitPropertyByIndex, CONTEXT, OBJECT, INT32, VALUE,
0, ACCSET_STORE_ANY)
@ -13618,8 +13617,7 @@ TraceRecorder::record_NativeCallComplete()
*/
if (JSTN_ERRTYPE(pendingSpecializedNative) == FAIL_STATUS) {
/* Keep cx->bailExit null when it's invalid. */
w.stContextField(w.immpNull(), bailExit);
leaveDeepBailCall();
LIns* status = w.ldiStateField(builtinStatus);
if (pendingSpecializedNative == &generatedSpecializedNative) {
@ -14441,7 +14439,7 @@ ObjectToIterator(JSContext* cx, JSObject *obj, int32 flags, Value* vp)
SetBuiltinError(cx);
return false;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, ObjectToIterator, CONTEXT, OBJECT, INT32, VALUEPTR,
0, ACCSET_STORE_ANY)
@ -14487,7 +14485,7 @@ IteratorMore(JSContext *cx, JSObject *iterobj, Value *vp)
SetBuiltinError(cx);
return false;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, IteratorMore, CONTEXT, OBJECT, VALUEPTR,
0, ACCSET_STORE_ANY)
@ -14540,7 +14538,7 @@ CloseIterator(JSContext *cx, JSObject *iterobj)
SetBuiltinError(cx);
return false;
}
return cx->tracerState->builtinStatus == 0;
return WasBuiltinSuccessful(cx);
}
JS_DEFINE_CALLINFO_2(extern, BOOL_FAIL, CloseIterator, CONTEXT, OBJECT, 0, ACCSET_STORE_ANY)

Просмотреть файл

@ -838,7 +838,13 @@ typedef enum BuiltinStatus {
static JS_INLINE void
SetBuiltinError(JSContext *cx)
{
cx->tracerState->builtinStatus |= BUILTIN_ERROR;
JS_TRACE_MONITOR(cx).tracerState->builtinStatus |= BUILTIN_ERROR;
}
static JS_INLINE bool
WasBuiltinSuccessful(JSContext *cx)
{
return JS_TRACE_MONITOR(cx).tracerState->builtinStatus == 0;
}
#ifdef DEBUG_RECORDING_STATUS_NOT_BOOL

Просмотреть файл

@ -1773,9 +1773,9 @@ namespace nanojit
char *formatImmD(RefBuf* buf, double c);
void formatGuard(InsBuf* buf, LIns* ins); // defined by the embedder
void formatGuardXov(InsBuf* buf, LIns* ins); // defined by the embedder
static const char* accNames[]; // defined by the embedder
public:
static const char* accNames[]; // defined by the embedder
LInsPrinter(Allocator& alloc, int embNumUsedAccs)
: alloc(alloc), EMB_NUM_USED_ACCS(embNumUsedAccs)

Просмотреть файл

@ -39,6 +39,7 @@
#include "jsprf.h"
#include "jstl.h"
#include "jscompartment.h"
#include "Writer.h"
#include "nanojit.h"
@ -341,6 +342,11 @@ void ValidateWriter::checkAccSet(LOpcode op, LIns *base, int32_t disp, AccSet ac
match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, cx));
break;
case ACCSET_TM:
// base = immp
ok = base->isImmP() && disp == 0;
break;
case ACCSET_EOS:
// base = ldp.state ...[offsetof(TracerState, eos)]
// ins = {ld,st}X.eos base[...]

Просмотреть файл

@ -102,6 +102,7 @@ enum LC_TMBits {
* - ACCSET_STACK: The stack.
* - ACCSET_RSTACK: The return stack.
* - ACCSET_CX: All JSContext structs.
* - ACCSET_TM: All TraceMonitor structs.
* - ACCSET_EOS: The globals area.
* - ACCSET_ALLOC: All memory blocks allocated with LIR_allocp (in
* other words, this region is the AR space).
@ -131,34 +132,35 @@ static const nanojit::AccSet ACCSET_STATE = (1 << 0);
static const nanojit::AccSet ACCSET_STACK = (1 << 1);
static const nanojit::AccSet ACCSET_RSTACK = (1 << 2);
static const nanojit::AccSet ACCSET_CX = (1 << 3);
static const nanojit::AccSet ACCSET_EOS = (1 << 4);
static const nanojit::AccSet ACCSET_ALLOC = (1 << 5);
static const nanojit::AccSet ACCSET_FRAMEREGS = (1 << 6);
static const nanojit::AccSet ACCSET_STACKFRAME = (1 << 7);
static const nanojit::AccSet ACCSET_RUNTIME = (1 << 8);
static const nanojit::AccSet ACCSET_TM = (1 << 4);
static const nanojit::AccSet ACCSET_EOS = (1 << 5);
static const nanojit::AccSet ACCSET_ALLOC = (1 << 6);
static const nanojit::AccSet ACCSET_FRAMEREGS = (1 << 7);
static const nanojit::AccSet ACCSET_STACKFRAME = (1 << 8);
static const nanojit::AccSet ACCSET_RUNTIME = (1 << 9);
// Nb: JSObject::{lastProp,map,flags} don't have an AccSet because they are never accessed on trace
static const nanojit::AccSet ACCSET_OBJ_CLASP = (1 << 9);
static const nanojit::AccSet ACCSET_OBJ_FLAGS = (1 << 10);
static const nanojit::AccSet ACCSET_OBJ_SHAPE = (1 << 11);
static const nanojit::AccSet ACCSET_OBJ_PROTO = (1 << 12);
static const nanojit::AccSet ACCSET_OBJ_PARENT = (1 << 13);
static const nanojit::AccSet ACCSET_OBJ_PRIVATE = (1 << 14);
static const nanojit::AccSet ACCSET_OBJ_CAPACITY = (1 << 15);
static const nanojit::AccSet ACCSET_OBJ_SLOTS = (1 << 16); // the pointer to the slots
static const nanojit::AccSet ACCSET_OBJ_CLASP = (1 << 10);
static const nanojit::AccSet ACCSET_OBJ_FLAGS = (1 << 11);
static const nanojit::AccSet ACCSET_OBJ_SHAPE = (1 << 12);
static const nanojit::AccSet ACCSET_OBJ_PROTO = (1 << 13);
static const nanojit::AccSet ACCSET_OBJ_PARENT = (1 << 14);
static const nanojit::AccSet ACCSET_OBJ_PRIVATE = (1 << 15);
static const nanojit::AccSet ACCSET_OBJ_CAPACITY = (1 << 16);
static const nanojit::AccSet ACCSET_OBJ_SLOTS = (1 << 17); // the pointer to the slots
static const nanojit::AccSet ACCSET_SLOTS = (1 << 17); // the slots themselves
static const nanojit::AccSet ACCSET_TARRAY = (1 << 18);
static const nanojit::AccSet ACCSET_TARRAY_DATA = (1 << 19);
static const nanojit::AccSet ACCSET_ITER = (1 << 20);
static const nanojit::AccSet ACCSET_ITER_PROPS = (1 << 21);
static const nanojit::AccSet ACCSET_STRING = (1 << 22);
static const nanojit::AccSet ACCSET_STRING_MCHARS = (1 << 23);
static const nanojit::AccSet ACCSET_TYPEMAP = (1 << 24);
static const nanojit::AccSet ACCSET_FCSLOTS = (1 << 25);
static const nanojit::AccSet ACCSET_ARGS_DATA = (1 << 26);
static const nanojit::AccSet ACCSET_SLOTS = (1 << 18); // the slots themselves
static const nanojit::AccSet ACCSET_TARRAY = (1 << 19);
static const nanojit::AccSet ACCSET_TARRAY_DATA = (1 << 20);
static const nanojit::AccSet ACCSET_ITER = (1 << 21);
static const nanojit::AccSet ACCSET_ITER_PROPS = (1 << 22);
static const nanojit::AccSet ACCSET_STRING = (1 << 23);
static const nanojit::AccSet ACCSET_STRING_MCHARS = (1 << 24);
static const nanojit::AccSet ACCSET_TYPEMAP = (1 << 25);
static const nanojit::AccSet ACCSET_FCSLOTS = (1 << 26);
static const nanojit::AccSet ACCSET_ARGS_DATA = (1 << 27);
static const uint8_t TM_NUM_USED_ACCS = 27; // number of access regions used by TraceMonkey
static const uint8_t TM_NUM_USED_ACCS = 28; // number of access regions used by TraceMonkey
/*
* An Address describes everything about a loaded/stored memory location. One
@ -431,6 +433,12 @@ class Writer
#define stContextField(value, fieldname) \
stContextField((value), cx_ins, offsetof(JSContext, fieldname))
nj::LIns *stTraceMonitorField(nj::LIns *value, void *dest, const char *destName) const {
return lir->insStore(value, name(lir->insImmP(dest), destName), 0, ACCSET_TM);
}
#define stTraceMonitorField(value, fieldname) \
stTraceMonitorField(value, &traceMonitor->fieldname, #fieldname)
nj::LIns *ldiAlloc(nj::LIns *alloc) const {
return lir->insLoad(nj::LIR_ldi, alloc, 0, ACCSET_ALLOC);
}