зеркало из https://github.com/mozilla/pjs.git
Lazily import stack and global slots (bug 515749, original patch and r=gal).
This commit is contained in:
Родитель
0943c5f15b
Коммит
1c37017028
|
@ -600,7 +600,7 @@ TraceRecorder::downRecursion()
|
|||
lirbuf->rp = lir->ins2(LIR_piadd, lirbuf->rp, lir->insImmWord(sizeof(FrameInfo*)));
|
||||
lir->insStorei(lirbuf->rp, lirbuf->state, offsetof(InterpState, rp));
|
||||
--callDepth;
|
||||
clearFrameSlotsFromCache();
|
||||
clearFrameSlotsFromTracker(nativeFrameTracker);
|
||||
|
||||
/*
|
||||
* If the callee and caller have identical call sites, this is a down-
|
||||
|
|
|
@ -2235,6 +2235,15 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void
|
||||
TypeMap::set(unsigned stackSlots, unsigned ngslots,
|
||||
const JSTraceType* stackTypeMap, const JSTraceType* globalTypeMap)
|
||||
{
|
||||
setLength(ngslots + stackSlots);
|
||||
memcpy(data(), stackTypeMap, stackSlots * sizeof(JSTraceType));
|
||||
memcpy(data() + stackSlots, globalTypeMap, ngslots * sizeof(JSTraceType));
|
||||
}
|
||||
|
||||
/*
|
||||
* Capture the type map for the selected slots of the global object and currently pending
|
||||
* stack frames.
|
||||
|
@ -2373,6 +2382,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag
|
|||
eos_ins(NULL),
|
||||
eor_ins(NULL),
|
||||
loopLabel(NULL),
|
||||
importTypeMap(&tempAlloc()),
|
||||
lirbuf(new (tempAlloc()) LirBuffer(tempAlloc())),
|
||||
mark(*traceMonitor->traceAlloc),
|
||||
numSideExitsBefore(tree->sideExits.length()),
|
||||
|
@ -2688,14 +2698,20 @@ TraceRecorder::p2i(nanojit::LIns* ins)
|
|||
#endif
|
||||
}
|
||||
|
||||
ptrdiff_t
|
||||
TraceRecorder::nativeGlobalSlot(jsval* p) const
|
||||
{
|
||||
JS_ASSERT(isGlobal(p));
|
||||
if (size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS)
|
||||
return ptrdiff_t(p - globalObj->fslots);
|
||||
return ptrdiff_t((p - globalObj->dslots) + JS_INITIAL_NSLOTS);
|
||||
}
|
||||
|
||||
/* Determine the offset in the native global frame for a jsval we track. */
|
||||
ptrdiff_t
|
||||
TraceRecorder::nativeGlobalOffset(jsval* p) const
|
||||
{
|
||||
JS_ASSERT(isGlobal(p));
|
||||
if (size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS)
|
||||
return size_t(p - globalObj->fslots) * sizeof(double);
|
||||
return ((p - globalObj->dslots) + JS_INITIAL_NSLOTS) * sizeof(double);
|
||||
return nativeGlobalSlot(p) * sizeof(double);
|
||||
}
|
||||
|
||||
/* Determine whether a value is a global stack slot. */
|
||||
|
@ -2730,6 +2746,13 @@ TraceRecorder::nativeStackOffset(jsval* p) const
|
|||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK ptrdiff_t
|
||||
TraceRecorder::nativeStackSlot(jsval* p) const
|
||||
{
|
||||
return nativeStackOffset(p) / sizeof(double);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the offset, from InterpState:sp, for the given jsval. Shorthand for:
|
||||
* -TreeFragment::nativeStackBase + nativeStackOffset(p).
|
||||
|
@ -2828,9 +2851,10 @@ ValueToNative(JSContext* cx, jsval v, JSTraceType type, double* slot)
|
|||
#endif
|
||||
return;
|
||||
}
|
||||
default:
|
||||
JS_NOT_REACHED("unexpected type");
|
||||
break;
|
||||
}
|
||||
|
||||
JS_NOT_REACHED("unexpected type");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3001,6 +3025,9 @@ js_NativeToValue(JSContext* cx, jsval& v, JSTraceType type, double* slot)
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
JS_NOT_REACHED("unexpected type");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -3628,38 +3655,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class ImportUnboxedStackSlotVisitor : public SlotVisitorBase
|
||||
{
|
||||
TraceRecorder &mRecorder;
|
||||
LIns *mBase;
|
||||
ptrdiff_t mStackOffset;
|
||||
JSTraceType *mTypemap;
|
||||
JSStackFrame *mFp;
|
||||
public:
|
||||
ImportUnboxedStackSlotVisitor(TraceRecorder &recorder,
|
||||
LIns *base,
|
||||
ptrdiff_t stackOffset,
|
||||
JSTraceType *typemap) :
|
||||
mRecorder(recorder),
|
||||
mBase(base),
|
||||
mStackOffset(stackOffset),
|
||||
mTypemap(typemap)
|
||||
{}
|
||||
|
||||
JS_REQUIRES_STACK JS_ALWAYS_INLINE bool
|
||||
visitStackSlots(jsval *vp, size_t count, JSStackFrame* fp) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
if (*mTypemap != TT_JSVAL) {
|
||||
mRecorder.import(mBase, mStackOffset, vp++, *mTypemap,
|
||||
stackSlotKind(), i, fp);
|
||||
}
|
||||
mTypemap++;
|
||||
mStackOffset += sizeof(double);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
JS_REQUIRES_STACK void
|
||||
TraceRecorder::import(TreeFragment* tree, LIns* sp, unsigned stackSlots, unsigned ngslots,
|
||||
unsigned callDepth, JSTraceType* typeMap)
|
||||
|
@ -3692,26 +3687,24 @@ TraceRecorder::import(TreeFragment* tree, LIns* sp, unsigned stackSlots, unsigne
|
|||
(JSTraceType*)alloca(sizeof(JSTraceType) * length));
|
||||
}
|
||||
JS_ASSERT(ngslots == tree->nGlobalTypes());
|
||||
ptrdiff_t offset = -tree->nativeStackBase;
|
||||
|
||||
/*
|
||||
* Check whether there are any values on the stack we have to unbox and do
|
||||
* that first before we waste any time fetching the state from the stack.
|
||||
*/
|
||||
if (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) {
|
||||
ImportBoxedStackSlotVisitor boxedStackVisitor(*this, sp, offset, typeMap);
|
||||
ImportBoxedStackSlotVisitor boxedStackVisitor(*this, sp, -tree->nativeStackBase, typeMap);
|
||||
VisitStackSlots(boxedStackVisitor, cx, callDepth);
|
||||
}
|
||||
|
||||
ImportGlobalSlotVisitor globalVisitor(*this, eos_ins, globalTypeMap);
|
||||
VisitGlobalSlots(globalVisitor, cx, globalObj, ngslots,
|
||||
tree->globalSlots->data());
|
||||
|
||||
if (!anchor || anchor->exitType != RECURSIVE_SLURP_FAIL_EXIT) {
|
||||
ImportUnboxedStackSlotVisitor unboxedStackVisitor(*this, sp, offset,
|
||||
typeMap);
|
||||
VisitStackSlots(unboxedStackVisitor, cx, callDepth);
|
||||
}
|
||||
/*
|
||||
* Remember the import type map so we can lazily import later whatever
|
||||
* we need.
|
||||
*/
|
||||
importTypeMap.set(importStackSlots = stackSlots,
|
||||
importGlobalSlots = ngslots,
|
||||
typeMap, globalTypeMap);
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK bool
|
||||
|
@ -3738,13 +3731,41 @@ TraceRecorder::isValidSlot(JSScope* scope, JSScopeProperty* sprop)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Lazily import a global slot if we don't already have it in the tracker. */
|
||||
JS_REQUIRES_STACK void
|
||||
TraceRecorder::importGlobalSlot(unsigned slot)
|
||||
{
|
||||
JS_ASSERT(slot == uint16(slot));
|
||||
JS_ASSERT(STOBJ_NSLOTS(globalObj) <= MAX_GLOBAL_SLOTS);
|
||||
|
||||
jsval* vp = &STOBJ_GET_SLOT(globalObj, slot);
|
||||
JS_ASSERT(!known(vp));
|
||||
|
||||
/* Add the slot to the list of interned global slots. */
|
||||
JSTraceType type;
|
||||
int index = tree->globalSlots->offsetOf(slot);
|
||||
if (index == -1) {
|
||||
type = getCoercedType(*vp);
|
||||
if (type == TT_INT32 && oracle.isGlobalSlotUndemotable(cx, slot))
|
||||
type = TT_DOUBLE;
|
||||
index = (int)tree->globalSlots->length();
|
||||
tree->globalSlots->add(slot);
|
||||
tree->typeMap.add(type);
|
||||
SpecializeTreesToMissingGlobals(cx, globalObj, tree);
|
||||
JS_ASSERT(tree->nGlobalTypes() == tree->globalSlots->length());
|
||||
} else {
|
||||
type = importTypeMap[importStackSlots + index];
|
||||
JS_ASSERT(type != TT_IGNORE);
|
||||
}
|
||||
import(eos_ins, slot * sizeof(double), vp, type, "global", index, NULL);
|
||||
}
|
||||
|
||||
/* Lazily import a global slot if we don't already have it in the tracker. */
|
||||
JS_REQUIRES_STACK bool
|
||||
TraceRecorder::lazilyImportGlobalSlot(unsigned slot)
|
||||
{
|
||||
if (slot != uint16(slot)) /* we use a table of 16-bit ints, bail out if that's not enough */
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If the global object grows too large, alloca in ExecuteTree might fail,
|
||||
* so abort tracing on global objects with unreasonably many slots.
|
||||
|
@ -3754,17 +3775,7 @@ TraceRecorder::lazilyImportGlobalSlot(unsigned slot)
|
|||
jsval* vp = &STOBJ_GET_SLOT(globalObj, slot);
|
||||
if (known(vp))
|
||||
return true; /* we already have it */
|
||||
unsigned index = tree->globalSlots->length();
|
||||
|
||||
/* Add the slot to the list of interned global slots. */
|
||||
JS_ASSERT(tree->nGlobalTypes() == tree->globalSlots->length());
|
||||
tree->globalSlots->add(slot);
|
||||
JSTraceType type = getCoercedType(*vp);
|
||||
if (type == TT_INT32 && oracle.isGlobalSlotUndemotable(cx, slot))
|
||||
type = TT_DOUBLE;
|
||||
tree->typeMap.add(type);
|
||||
import(eos_ins, slot*sizeof(double), vp, type, "global", index, NULL);
|
||||
SpecializeTreesToMissingGlobals(cx, globalObj, tree);
|
||||
importGlobalSlot(slot);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3787,7 +3798,6 @@ JS_REQUIRES_STACK void
|
|||
TraceRecorder::set(jsval* p, LIns* i, bool initializing, bool demote)
|
||||
{
|
||||
JS_ASSERT(i != NULL);
|
||||
JS_ASSERT(initializing || known(p));
|
||||
checkForGlobalObjectReallocation();
|
||||
tracker.set(p, i);
|
||||
|
||||
|
@ -3829,8 +3839,22 @@ TraceRecorder::set(jsval* p, LIns* i, bool initializing, bool demote)
|
|||
JS_REQUIRES_STACK LIns*
|
||||
TraceRecorder::get(jsval* p)
|
||||
{
|
||||
JS_ASSERT(known(p));
|
||||
checkForGlobalObjectReallocation();
|
||||
LIns* x = tracker.get(p);
|
||||
if (x)
|
||||
return x;
|
||||
if (isGlobal(p)) {
|
||||
unsigned slot = nativeGlobalSlot(p);
|
||||
JS_ASSERT(tree->globalSlots->offsetOf(slot) != -1);
|
||||
importGlobalSlot(slot);
|
||||
} else {
|
||||
unsigned slot = nativeStackSlot(p);
|
||||
JSTraceType type = importTypeMap[slot];
|
||||
JS_ASSERT(type != TT_IGNORE);
|
||||
import(lirbuf->sp, -tree->nativeStackBase + slot * sizeof(jsdouble),
|
||||
p, type, "stack", slot, cx->fp);
|
||||
}
|
||||
JS_ASSERT(known(p));
|
||||
return tracker.get(p);
|
||||
}
|
||||
|
||||
|
@ -4003,9 +4027,17 @@ JS_REQUIRES_STACK JSTraceType
|
|||
TraceRecorder::determineSlotType(jsval* vp)
|
||||
{
|
||||
JSTraceType m;
|
||||
LIns* i = get(vp);
|
||||
if (isNumber(*vp)) {
|
||||
m = isPromoteInt(i) ? TT_INT32 : TT_DOUBLE;
|
||||
LIns* i = tracker.get(vp);
|
||||
if (i) {
|
||||
m = isPromoteInt(i) ? TT_INT32 : TT_DOUBLE;
|
||||
} else if (isGlobal(vp)) {
|
||||
int offset = tree->globalSlots->offsetOf(nativeGlobalSlot(vp));
|
||||
JS_ASSERT(offset != -1);
|
||||
m = importTypeMap[importStackSlots + offset];
|
||||
} else {
|
||||
m = importTypeMap[nativeStackSlot(vp)];
|
||||
}
|
||||
} else if (JSVAL_IS_OBJECT(*vp)) {
|
||||
if (JSVAL_IS_NULL(*vp))
|
||||
m = TT_NULL;
|
||||
|
@ -4513,7 +4545,21 @@ class SlotMap : public SlotVisitorBase
|
|||
JS_REQUIRES_STACK JS_ALWAYS_INLINE void
|
||||
addSlot(jsval* vp)
|
||||
{
|
||||
slots.add(SlotInfo(vp, isPromoteInt(mRecorder.get(vp))));
|
||||
bool promoteInt = false;
|
||||
if (isNumber(*vp)) {
|
||||
if (LIns* i = mRecorder.tracker.get(vp)) {
|
||||
promoteInt = isPromoteInt(i);
|
||||
} else if (mRecorder.isGlobal(vp)) {
|
||||
int offset = mRecorder.tree->globalSlots->offsetOf(mRecorder.nativeGlobalSlot(vp));
|
||||
JS_ASSERT(offset != -1);
|
||||
promoteInt = mRecorder.importTypeMap[mRecorder.importStackSlots + offset] ==
|
||||
TT_INT32;
|
||||
} else {
|
||||
promoteInt = mRecorder.importTypeMap[mRecorder.nativeStackSlot(vp)] ==
|
||||
TT_INT32;
|
||||
}
|
||||
}
|
||||
slots.add(SlotInfo(vp, promoteInt));
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK JS_ALWAYS_INLINE void
|
||||
|
@ -5156,16 +5202,66 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit, LIns* inner_s
|
|||
JS_ASSERT(map[i] != TT_JSVAL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flush values from the tracker which could have been invalidated by the
|
||||
* inner tree. This means variables local to this frame and global slots.
|
||||
* It's safe to keep the offset cache around, we just want to force reloads.
|
||||
*/
|
||||
clearFrameSlotsFromTracker(tracker);
|
||||
SlotList& gslots = *tree->globalSlots;
|
||||
for (unsigned i = 0; i < gslots.length(); i++) {
|
||||
unsigned slot = gslots[i];
|
||||
jsval* vp = &STOBJ_GET_SLOT(globalObj, slot);
|
||||
tracker.set(vp, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin the complicated process of building a usable typemap by looking
|
||||
* at all stack slots.
|
||||
*/
|
||||
TypeMap stackTypeMap(NULL);
|
||||
stackTypeMap.setLength(NativeStackSlots(cx, callDepth));
|
||||
CaptureTypesVisitor visitor(cx, stackTypeMap.data());
|
||||
VisitStackSlots(visitor, cx, callDepth);
|
||||
JS_ASSERT(stackTypeMap.length() >= exit->numStackSlots);
|
||||
|
||||
/*
|
||||
* The import map layout looks like:
|
||||
* -------------
|
||||
* Initial Frame (callDepth=0)
|
||||
* ...
|
||||
* ...
|
||||
* ...
|
||||
* Current Frame (callDepth=N)
|
||||
* -------------
|
||||
*
|
||||
* Anything in between the innermost and outermost frames must be in the
|
||||
* tracker at this point, so it's kind of pointless to make sure it's
|
||||
* in the typemap. It'd be a pain to have separate typemaps for each
|
||||
* "hole" though, so make one big one knowing that the holes won't be
|
||||
* read.
|
||||
*
|
||||
* NOTE: It's important that setLength() doesn't mess up stuff below the
|
||||
* current frame. It has to shrink safely.
|
||||
*/
|
||||
importTypeMap.setLength(stackTypeMap.length());
|
||||
unsigned startOfInnerFrame = stackTypeMap.length() - exit->numStackSlots;
|
||||
#ifdef DEBUG
|
||||
for (unsigned i = importStackSlots; i < startOfInnerFrame; i++)
|
||||
stackTypeMap[i] = TT_IGNORE;
|
||||
#endif
|
||||
for (unsigned i = 0; i < exit->numStackSlots; i++)
|
||||
importTypeMap[startOfInnerFrame + i] = exit->stackTypeMap()[i];
|
||||
|
||||
/*
|
||||
* Bug 502604 - It is illegal to extend from the outer typemap without
|
||||
* first extending from the inner. Make a new typemap here.
|
||||
*/
|
||||
TypeMap fullMap(NULL);
|
||||
fullMap.add(exit->stackTypeMap(), exit->numStackSlots);
|
||||
BuildGlobalTypeMapFromInnerTree(fullMap, exit);
|
||||
BuildGlobalTypeMapFromInnerTree(importTypeMap, exit);
|
||||
|
||||
import(inner, inner_sp_ins, exit->numStackSlots, fullMap.length() - exit->numStackSlots,
|
||||
exit->calldepth, fullMap.data());
|
||||
importStackSlots = stackTypeMap.length();
|
||||
importGlobalSlots = importTypeMap.length() - importStackSlots;
|
||||
JS_ASSERT(importGlobalSlots == tree->globalSlots->length());
|
||||
|
||||
/* Restore sp and rp to their original values (we still have them in a register). */
|
||||
if (callDepth > 0) {
|
||||
|
@ -9646,7 +9742,7 @@ TraceRecorder::guardNotGlobalObject(JSObject* obj, LIns* obj_ins)
|
|||
}
|
||||
|
||||
JS_REQUIRES_STACK void
|
||||
TraceRecorder::clearFrameSlotsFromCache()
|
||||
TraceRecorder::clearFrameSlotsFromTracker(Tracker& which)
|
||||
{
|
||||
/*
|
||||
* Clear out all slots of this frame in the nativeFrameTracker. Different
|
||||
|
@ -9668,13 +9764,13 @@ TraceRecorder::clearFrameSlotsFromCache()
|
|||
vp = &fp->argv[-2];
|
||||
vpstop = &fp->argv[argSlots(fp)];
|
||||
while (vp < vpstop)
|
||||
nativeFrameTracker.set(vp++, (LIns*)0);
|
||||
nativeFrameTracker.set(&fp->argsobj, (LIns*)0);
|
||||
which.set(vp++, (LIns*)0);
|
||||
which.set(&fp->argsobj, (LIns*)0);
|
||||
}
|
||||
vp = &fp->slots[0];
|
||||
vpstop = &fp->slots[fp->script->nslots];
|
||||
while (vp < vpstop)
|
||||
nativeFrameTracker.set(vp++, (LIns*)0);
|
||||
which.set(vp++, (LIns*)0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -9908,7 +10004,7 @@ TraceRecorder::record_JSOP_RETURN()
|
|||
debug_only_printf(LC_TMTracer,
|
||||
"returning from %s\n",
|
||||
js_AtomToPrintableString(cx, cx->fp->fun->atom));
|
||||
clearFrameSlotsFromCache();
|
||||
clearFrameSlotsFromTracker(nativeFrameTracker);
|
||||
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
@ -14259,7 +14355,7 @@ TraceRecorder::record_JSOP_STOP()
|
|||
} else {
|
||||
rval_ins = INS_CONST(JSVAL_TO_SPECIAL(JSVAL_VOID));
|
||||
}
|
||||
clearFrameSlotsFromCache();
|
||||
clearFrameSlotsFromTracker(nativeFrameTracker);
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,6 +156,16 @@ public:
|
|||
T* data() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
int offsetOf(T slot) {
|
||||
T* p = _data;
|
||||
unsigned n = 0;
|
||||
for (n = 0; n < _len; ++n)
|
||||
if (*p++ == slot)
|
||||
return n;
|
||||
return -1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -337,7 +347,8 @@ enum JSTraceType_
|
|||
TT_STRING = 4, /* pointer to JSString */
|
||||
TT_NULL = 5, /* null */
|
||||
TT_PSEUDOBOOLEAN = 6, /* true, false, or undefined (0, 1, or 2) */
|
||||
TT_FUNCTION = 7 /* pointer to JSObject whose class is js_FunctionClass */
|
||||
TT_FUNCTION = 7, /* pointer to JSObject whose class is js_FunctionClass */
|
||||
TT_IGNORE = 8
|
||||
}
|
||||
#if defined(__GNUC__) && defined(USE_TRACE_TYPE_ENUM)
|
||||
__attribute__((packed))
|
||||
|
@ -362,6 +373,8 @@ typedef Queue<uint16> SlotList;
|
|||
class TypeMap : public Queue<JSTraceType> {
|
||||
public:
|
||||
TypeMap(nanojit::Allocator* alloc) : Queue<JSTraceType>(alloc) {}
|
||||
void set(unsigned stackSlots, unsigned ngslots,
|
||||
const JSTraceType* stackTypeMap, const JSTraceType* globalTypeMap);
|
||||
JS_REQUIRES_STACK void captureTypes(JSContext* cx, JSObject* globalObj, SlotList& slots, unsigned callDepth);
|
||||
JS_REQUIRES_STACK void captureMissingGlobalTypes(JSContext* cx, JSObject* globalObj, SlotList& slots,
|
||||
unsigned stackSlots);
|
||||
|
@ -941,6 +954,11 @@ class TraceRecorder
|
|||
nanojit::LIns* const eor_ins;
|
||||
nanojit::LIns* const loopLabel;
|
||||
|
||||
/* Lazy slot import state. */
|
||||
unsigned importStackSlots;
|
||||
unsigned importGlobalSlots;
|
||||
TypeMap importTypeMap;
|
||||
|
||||
/*
|
||||
* The LirBuffer used to supply memory to our LirWriter pipeline. Also contains the most recent
|
||||
* instruction for {sp, rp, state}. Also contains names for debug JIT spew. Should be split.
|
||||
|
@ -1040,8 +1058,10 @@ class TraceRecorder
|
|||
JS_REQUIRES_STACK nanojit::GuardRecord* createGuardRecord(VMSideExit* exit);
|
||||
|
||||
bool isGlobal(jsval* p) const;
|
||||
ptrdiff_t nativeGlobalSlot(jsval *p) const;
|
||||
ptrdiff_t nativeGlobalOffset(jsval* p) const;
|
||||
JS_REQUIRES_STACK ptrdiff_t nativeStackOffset(jsval* p) const;
|
||||
JS_REQUIRES_STACK ptrdiff_t nativeStackSlot(jsval* p) const;
|
||||
JS_REQUIRES_STACK ptrdiff_t nativespOffset(jsval* p) const;
|
||||
JS_REQUIRES_STACK void import(nanojit::LIns* base, ptrdiff_t offset, jsval* p, JSTraceType t,
|
||||
const char *prefix, uintN index, JSStackFrame *fp);
|
||||
|
@ -1051,6 +1071,7 @@ class TraceRecorder
|
|||
|
||||
JS_REQUIRES_STACK bool isValidSlot(JSScope* scope, JSScopeProperty* sprop);
|
||||
JS_REQUIRES_STACK bool lazilyImportGlobalSlot(unsigned slot);
|
||||
JS_REQUIRES_STACK void importGlobalSlot(unsigned slot);
|
||||
|
||||
JS_REQUIRES_STACK void guard(bool expected, nanojit::LIns* cond, ExitType exitType);
|
||||
JS_REQUIRES_STACK void guard(bool expected, nanojit::LIns* cond, VMSideExit* exit);
|
||||
|
@ -1266,7 +1287,7 @@ class TraceRecorder
|
|||
ExitType exitType);
|
||||
JS_REQUIRES_STACK RecordingStatus guardNotGlobalObject(JSObject* obj,
|
||||
nanojit::LIns* obj_ins);
|
||||
void clearFrameSlotsFromCache();
|
||||
void clearFrameSlotsFromTracker(Tracker& which);
|
||||
JS_REQUIRES_STACK void putArguments();
|
||||
JS_REQUIRES_STACK RecordingStatus guardCallee(jsval& callee);
|
||||
JS_REQUIRES_STACK JSStackFrame *guardArguments(JSObject *obj, nanojit::LIns* obj_ins,
|
||||
|
|
Загрузка…
Ссылка в новой задаче