зеркало из https://github.com/mozilla/pjs.git
Bug 623050 - Move tracerState to compartment (r=gal)
This commit is contained in:
Родитель
aa680e0883
Коммит
4354ff8bc1
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче