mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-02 07:05:24 +00:00
Move cx->fp to cx->regs->fp, bug 588978. r=lw
--HG-- extra : rebase_source : 14a90a53ceeb1f65d0ab70eafb5371095535e66f
This commit is contained in:
parent
7357103c6c
commit
5e3903b1fc
@ -359,7 +359,7 @@ MozAxAutoPushJSContext::MozAxAutoPushJSContext(JSContext *cx,
|
||||
// See if there are any scripts on the stack.
|
||||
// If not, we need to add a dummy frame with a principal.
|
||||
PRBool hasScript = PR_FALSE;
|
||||
JSStackFrame* tempFP = cx->fp;
|
||||
JSStackFrame* tempFP = cx->fp();
|
||||
while (tempFP)
|
||||
{
|
||||
if (tempFP->script)
|
||||
|
@ -1822,8 +1822,8 @@ JS_GetGlobalForScopeChain(JSContext *cx)
|
||||
*/
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
|
||||
if (cx->fp)
|
||||
return cx->fp->getScopeChain()->getGlobal();
|
||||
if (cx->hasfp())
|
||||
return cx->fp()->getScopeChain()->getGlobal();
|
||||
|
||||
JSObject *scope = cx->globalObject;
|
||||
if (!scope) {
|
||||
@ -4090,8 +4090,8 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, parent); // XXX no funobj for now
|
||||
if (!parent) {
|
||||
if (cx->fp)
|
||||
parent = js_GetScopeChain(cx, cx->fp);
|
||||
if (cx->hasfp())
|
||||
parent = js_GetScopeChain(cx, cx->fp());
|
||||
if (!parent)
|
||||
parent = cx->globalObject;
|
||||
JS_ASSERT(parent);
|
||||
@ -4298,7 +4298,7 @@ js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
|
||||
if (!ComputeThisFromArgv(cx, argv))
|
||||
return JS_FALSE;
|
||||
js_GetTopStackFrame(cx)->setThisValue(argv[-1]);
|
||||
JS_ASSERT(cx->fp->argv == argv);
|
||||
JS_ASSERT(cx->fp()->argv == argv);
|
||||
|
||||
/* Clear the last parameter in case too few arguments were passed. */
|
||||
argv[--argc].setUndefined();
|
||||
@ -4942,9 +4942,9 @@ JS_IsRunning(JSContext *cx)
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JS_ASSERT_IF(JS_TRACE_MONITOR(cx).tracecx == cx, cx->fp);
|
||||
JS_ASSERT_IF(JS_TRACE_MONITOR(cx).tracecx == cx, cx->hasfp());
|
||||
#endif
|
||||
JSStackFrame *fp = cx->fp;
|
||||
JSStackFrame *fp = cx->maybefp();
|
||||
while (fp && fp->isDummyFrame())
|
||||
fp = fp->down;
|
||||
return fp != NULL;
|
||||
@ -4972,7 +4972,7 @@ JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
JS_ASSERT_NOT_ON_TRACE(cx);
|
||||
JS_ASSERT(!cx->fp);
|
||||
JS_ASSERT(!cx->hasfp());
|
||||
if (!fp)
|
||||
return;
|
||||
cx->restoreSegment();
|
||||
|
@ -335,8 +335,8 @@ JS_DEFINE_CALLINFO_4(extern, OBJECT, js_NewNullClosure, CONTEXT, OBJECT, OBJECT,
|
||||
JS_REQUIRES_STACK JSBool FASTCALL
|
||||
js_PopInterpFrame(JSContext* cx, TracerState* state)
|
||||
{
|
||||
JS_ASSERT(cx->fp && cx->fp->down);
|
||||
JSStackFrame* const fp = cx->fp;
|
||||
JS_ASSERT(cx->hasfp() && cx->fp()->down);
|
||||
JSStackFrame* const fp = cx->fp();
|
||||
|
||||
/*
|
||||
* Mirror frame popping code from inline_return in js_Interpret. There are
|
||||
|
@ -110,10 +110,12 @@ StackSegment::contains(const JSStackFrame *fp) const
|
||||
JSStackFrame *start;
|
||||
JSStackFrame *stop;
|
||||
if (isActive()) {
|
||||
start = cx->fp;
|
||||
JS_ASSERT(cx->hasfp());
|
||||
start = cx->fp();
|
||||
stop = cx->activeSegment()->initialFrame->down;
|
||||
} else {
|
||||
start = suspendedFrame;
|
||||
JS_ASSERT(suspendedRegs && suspendedRegs->fp);
|
||||
start = suspendedRegs->fp;
|
||||
stop = initialFrame->down;
|
||||
}
|
||||
for (JSStackFrame *f = start; f != stop; f = f->down) {
|
||||
@ -313,7 +315,9 @@ StackSpace::pushExecuteFrame(JSContext *cx, ExecuteFrameGuard &fg,
|
||||
StackSegment *seg = fg.seg;
|
||||
seg->setPreviousInMemory(currentSegment);
|
||||
currentSegment = seg;
|
||||
cx->pushSegmentAndFrame(seg, fg.fp, regs);
|
||||
|
||||
regs.fp = fg.fp;
|
||||
cx->pushSegmentAndFrame(seg, regs);
|
||||
seg->setInitialVarObj(initialVarObj);
|
||||
fg.cx = cx;
|
||||
}
|
||||
@ -333,7 +337,7 @@ ExecuteFrameGuard::~ExecuteFrameGuard()
|
||||
if (!pushed())
|
||||
return;
|
||||
JS_ASSERT(cx->activeSegment() == seg);
|
||||
JS_ASSERT(cx->fp == fp);
|
||||
JS_ASSERT(cx->maybefp() == fp);
|
||||
cx->stack().popExecuteFrame(cx);
|
||||
}
|
||||
|
||||
@ -347,14 +351,13 @@ StackSpace::getSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *&seg, JSS
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK void
|
||||
StackSpace::pushSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *seg, JSStackFrame *fp,
|
||||
JSFrameRegs ®s)
|
||||
StackSpace::pushSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *seg, JSFrameRegs ®s)
|
||||
{
|
||||
JS_ASSERT(!fp->hasScript() && FUN_SLOW_NATIVE(fp->getFunction()));
|
||||
fp->down = cx->fp;
|
||||
JS_ASSERT(!regs.fp->hasScript() && FUN_SLOW_NATIVE(regs.fp->getFunction()));
|
||||
regs.fp->down = cx->maybefp();
|
||||
seg->setPreviousInMemory(currentSegment);
|
||||
currentSegment = seg;
|
||||
cx->pushSegmentAndFrame(seg, fp, regs);
|
||||
cx->pushSegmentAndFrame(seg, regs);
|
||||
seg->setInitialVarObj(NULL);
|
||||
}
|
||||
|
||||
@ -363,8 +366,8 @@ StackSpace::popSynthesizedSlowNativeFrame(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(isCurrentAndActive(cx));
|
||||
JS_ASSERT(cx->hasActiveSegment());
|
||||
JS_ASSERT(currentSegment->getInitialFrame() == cx->fp);
|
||||
JS_ASSERT(!cx->fp->hasScript() && FUN_SLOW_NATIVE(cx->fp->getFunction()));
|
||||
JS_ASSERT(currentSegment->getInitialFrame() == cx->fp());
|
||||
JS_ASSERT(!cx->fp()->hasScript() && FUN_SLOW_NATIVE(cx->fp()->getFunction()));
|
||||
cx->popSegmentAndFrame();
|
||||
currentSegment = currentSegment->getPreviousInMemory();
|
||||
}
|
||||
@ -1934,7 +1937,7 @@ js_GetCurrentBytecodePC(JSContext* cx)
|
||||
pc = cx->regs ? cx->regs->pc : NULL;
|
||||
if (!pc)
|
||||
return NULL;
|
||||
imacpc = cx->fp->maybeIMacroPC();
|
||||
imacpc = cx->fp()->maybeIMacroPC();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1952,7 +1955,7 @@ js_CurrentPCIsInImacro(JSContext *cx)
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
if (JS_ON_TRACE(cx))
|
||||
return cx->bailExit->imacpc != NULL;
|
||||
return cx->fp->hasIMacroPC();
|
||||
return cx->fp()->hasIMacroPC();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@ -1997,54 +2000,48 @@ DSTOffsetCache::DSTOffsetCache()
|
||||
JSContext::JSContext(JSRuntime *rt)
|
||||
: runtime(rt),
|
||||
compartment(rt->defaultCompartment),
|
||||
fp(NULL),
|
||||
regs(NULL),
|
||||
regExpStatics(this),
|
||||
busyArrays(this)
|
||||
{}
|
||||
|
||||
void
|
||||
JSContext::pushSegmentAndFrame(js::StackSegment *newseg, JSStackFrame *newfp,
|
||||
JSFrameRegs &newregs)
|
||||
JSContext::pushSegmentAndFrame(js::StackSegment *newseg, JSFrameRegs &newregs)
|
||||
{
|
||||
if (hasActiveSegment()) {
|
||||
JS_ASSERT(fp->savedPC == JSStackFrame::sInvalidPC);
|
||||
fp->savedPC = regs->pc;
|
||||
currentSegment->suspend(fp, regs);
|
||||
JS_ASSERT(regs->fp->savedPC == JSStackFrame::sInvalidPC);
|
||||
regs->fp->savedPC = regs->pc;
|
||||
currentSegment->suspend(regs);
|
||||
}
|
||||
newseg->setPreviousInContext(currentSegment);
|
||||
currentSegment = newseg;
|
||||
#ifdef DEBUG
|
||||
newfp->savedPC = JSStackFrame::sInvalidPC;
|
||||
newregs.fp->savedPC = JSStackFrame::sInvalidPC;
|
||||
#endif
|
||||
setCurrentFrame(newfp);
|
||||
setCurrentRegs(&newregs);
|
||||
newseg->joinContext(this, newfp);
|
||||
newseg->joinContext(this, newregs.fp);
|
||||
}
|
||||
|
||||
void
|
||||
JSContext::popSegmentAndFrame()
|
||||
{
|
||||
JS_ASSERT(currentSegment->maybeContext() == this);
|
||||
JS_ASSERT(currentSegment->getInitialFrame() == fp);
|
||||
JS_ASSERT(fp->savedPC == JSStackFrame::sInvalidPC);
|
||||
JS_ASSERT(currentSegment->getInitialFrame() == regs->fp);
|
||||
JS_ASSERT(regs->fp->savedPC == JSStackFrame::sInvalidPC);
|
||||
currentSegment->leaveContext();
|
||||
currentSegment = currentSegment->getPreviousInContext();
|
||||
if (currentSegment) {
|
||||
if (currentSegment->isSaved()) {
|
||||
setCurrentFrame(NULL);
|
||||
setCurrentRegs(NULL);
|
||||
} else {
|
||||
setCurrentFrame(currentSegment->getSuspendedFrame());
|
||||
setCurrentRegs(currentSegment->getSuspendedRegs());
|
||||
currentSegment->resume();
|
||||
#ifdef DEBUG
|
||||
fp->savedPC = JSStackFrame::sInvalidPC;
|
||||
regs->fp->savedPC = JSStackFrame::sInvalidPC;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(fp->down == NULL);
|
||||
setCurrentFrame(NULL);
|
||||
JS_ASSERT(regs->fp->down == NULL);
|
||||
setCurrentRegs(NULL);
|
||||
}
|
||||
}
|
||||
@ -2053,10 +2050,9 @@ void
|
||||
JSContext::saveActiveSegment()
|
||||
{
|
||||
JS_ASSERT(hasActiveSegment());
|
||||
currentSegment->save(fp, regs);
|
||||
JS_ASSERT(fp->savedPC == JSStackFrame::sInvalidPC);
|
||||
fp->savedPC = regs->pc;
|
||||
setCurrentFrame(NULL);
|
||||
currentSegment->save(regs);
|
||||
JS_ASSERT(regs->fp->savedPC == JSStackFrame::sInvalidPC);
|
||||
regs->fp->savedPC = regs->pc;
|
||||
setCurrentRegs(NULL);
|
||||
}
|
||||
|
||||
@ -2064,11 +2060,10 @@ void
|
||||
JSContext::restoreSegment()
|
||||
{
|
||||
js::StackSegment *ccs = currentSegment;
|
||||
setCurrentFrame(ccs->getSuspendedFrame());
|
||||
setCurrentRegs(ccs->getSuspendedRegs());
|
||||
ccs->restore();
|
||||
#ifdef DEBUG
|
||||
fp->savedPC = JSStackFrame::sInvalidPC;
|
||||
regs->fp->savedPC = JSStackFrame::sInvalidPC;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2099,10 +2094,11 @@ JSContext::containingSegment(const JSStackFrame *target)
|
||||
if (!seg)
|
||||
return NULL;
|
||||
|
||||
/* The active segments's top frame is cx->fp. */
|
||||
if (fp) {
|
||||
/* The active segments's top frame is cx->regs->fp. */
|
||||
if (regs) {
|
||||
JS_ASSERT(regs->fp);
|
||||
JS_ASSERT(activeSegment() == seg);
|
||||
JSStackFrame *f = fp;
|
||||
JSStackFrame *f = regs->fp;
|
||||
JSStackFrame *stop = seg->getInitialFrame()->down;
|
||||
for (; f != stop; f = f->down) {
|
||||
if (f == target)
|
||||
|
130
js/src/jscntxt.h
130
js/src/jscntxt.h
@ -301,16 +301,16 @@ struct GlobalState {
|
||||
* The frames of a non-empty segment must all be in the same context and thus
|
||||
* each non-empty segment is referred to as being "in" a context. Segments in a
|
||||
* context have an additional state of being either "active" or "suspended". A
|
||||
* suspended segment |ss| has a "suspended frame" which is snapshot of |cx->fp|
|
||||
* suspended segment |ss| has a "suspended frame" which is snapshot of |cx->regs|
|
||||
* when the segment was suspended and serves as the current frame of |ss|.
|
||||
* There is at most one active segment in a given context. Segments in a
|
||||
* context execute LIFO and are maintained in a stack. The top of this stack
|
||||
* is the context's "current segment". If a context |cx| has an active segment
|
||||
* |ss|, then:
|
||||
* 1. |ss| is |cx|'s current segment,
|
||||
* 2. |cx->fp != NULL|, and
|
||||
* 3. |ss|'s current frame is |cx->fp|.
|
||||
* Moreover, |cx->fp != NULL| iff |cx| has an active segment.
|
||||
* 2. |cx->regs != NULL|, and
|
||||
* 3. |ss|'s current frame is |cx->regs->fp|.
|
||||
* Moreover, |cx->regs != NULL| iff |cx| has an active segment.
|
||||
*
|
||||
* An empty segment is not associated with any context. Empty segments are
|
||||
* created when there is not an active segment for a context at the top of the
|
||||
@ -341,9 +341,6 @@ class StackSegment
|
||||
/* The first frame executed in this segment. null iff cx is null */
|
||||
JSStackFrame *initialFrame;
|
||||
|
||||
/* If this segment is suspended, the top of the segment. */
|
||||
JSStackFrame *suspendedFrame;
|
||||
|
||||
/* If this segment is suspended, |cx->regs| when it was suspended. */
|
||||
JSFrameRegs *suspendedRegs;
|
||||
|
||||
@ -353,17 +350,22 @@ class StackSegment
|
||||
/* Whether this segment was suspended by JS_SaveFrameChain. */
|
||||
bool saved;
|
||||
|
||||
/* Align at 8 bytes on all platforms. */
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
void *padding;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* To make isActive a single null-ness check, this non-null constant is
|
||||
* assigned to suspendedFrame when !inContext.
|
||||
* assigned to suspendedRegs when !inContext.
|
||||
*/
|
||||
#define NON_NULL_SUSPENDED_FRAME ((JSStackFrame *)0x1)
|
||||
#define NON_NULL_SUSPENDED_REGS ((JSFrameRegs *)0x1)
|
||||
|
||||
public:
|
||||
StackSegment()
|
||||
: cx(NULL), previousInContext(NULL), previousInMemory(NULL),
|
||||
initialFrame(NULL), suspendedFrame(NON_NULL_SUSPENDED_FRAME),
|
||||
suspendedRegs(NULL), initialVarObj(NULL), saved(false)
|
||||
initialFrame(NULL), suspendedRegs(NON_NULL_SUSPENDED_REGS),
|
||||
initialVarObj(NULL), saved(false)
|
||||
{
|
||||
JS_ASSERT(!inContext());
|
||||
}
|
||||
@ -391,20 +393,20 @@ class StackSegment
|
||||
|
||||
bool inContext() const {
|
||||
JS_ASSERT(!!cx == !!initialFrame);
|
||||
JS_ASSERT_IF(!cx, suspendedFrame == NON_NULL_SUSPENDED_FRAME && !saved);
|
||||
JS_ASSERT_IF(!cx, suspendedRegs == NON_NULL_SUSPENDED_REGS && !saved);
|
||||
return cx;
|
||||
}
|
||||
|
||||
bool isActive() const {
|
||||
JS_ASSERT_IF(!suspendedFrame, cx && !saved);
|
||||
JS_ASSERT_IF(!cx, suspendedFrame == NON_NULL_SUSPENDED_FRAME);
|
||||
return !suspendedFrame;
|
||||
JS_ASSERT_IF(!suspendedRegs, cx && !saved);
|
||||
JS_ASSERT_IF(!cx, suspendedRegs == NON_NULL_SUSPENDED_REGS);
|
||||
return !suspendedRegs;
|
||||
}
|
||||
|
||||
bool isSuspended() const {
|
||||
JS_ASSERT_IF(!cx || !suspendedFrame, !saved);
|
||||
JS_ASSERT_IF(!cx, suspendedFrame == NON_NULL_SUSPENDED_FRAME);
|
||||
return cx && suspendedFrame;
|
||||
JS_ASSERT_IF(!cx || !suspendedRegs, !saved);
|
||||
JS_ASSERT_IF(!cx, suspendedRegs == NON_NULL_SUSPENDED_REGS);
|
||||
return cx && suspendedRegs;
|
||||
}
|
||||
|
||||
/* Substate of suspended, queryable in any state. */
|
||||
@ -420,7 +422,7 @@ class StackSegment
|
||||
JS_ASSERT(!inContext());
|
||||
this->cx = cx;
|
||||
initialFrame = f;
|
||||
suspendedFrame = NULL;
|
||||
suspendedRegs = NULL;
|
||||
JS_ASSERT(isActive());
|
||||
}
|
||||
|
||||
@ -428,7 +430,7 @@ class StackSegment
|
||||
JS_ASSERT(isActive());
|
||||
this->cx = NULL;
|
||||
initialFrame = NULL;
|
||||
suspendedFrame = NON_NULL_SUSPENDED_FRAME;
|
||||
suspendedRegs = NON_NULL_SUSPENDED_REGS;
|
||||
JS_ASSERT(!inContext());
|
||||
}
|
||||
|
||||
@ -436,29 +438,28 @@ class StackSegment
|
||||
return cx;
|
||||
}
|
||||
|
||||
#undef NON_NULL_SUSPENDED_FRAME
|
||||
#undef NON_NULL_SUSPENDED_REGS
|
||||
|
||||
/* Transitioning between isActive <--> isSuspended */
|
||||
|
||||
void suspend(JSStackFrame *fp, JSFrameRegs *regs) {
|
||||
void suspend(JSFrameRegs *regs) {
|
||||
JS_ASSERT(isActive());
|
||||
JS_ASSERT(fp && contains(fp));
|
||||
suspendedFrame = fp;
|
||||
JS_ASSERT(isSuspended());
|
||||
JS_ASSERT(regs && regs->fp && contains(regs->fp));
|
||||
suspendedRegs = regs;
|
||||
JS_ASSERT(isSuspended());
|
||||
}
|
||||
|
||||
void resume() {
|
||||
JS_ASSERT(isSuspended());
|
||||
suspendedFrame = NULL;
|
||||
suspendedRegs = NULL;
|
||||
JS_ASSERT(isActive());
|
||||
}
|
||||
|
||||
/* When isSuspended, transitioning isSaved <--> !isSaved */
|
||||
|
||||
void save(JSStackFrame *fp, JSFrameRegs *regs) {
|
||||
void save(JSFrameRegs *regs) {
|
||||
JS_ASSERT(!isSuspended());
|
||||
suspend(fp, regs);
|
||||
suspend(regs);
|
||||
saved = true;
|
||||
JS_ASSERT(isSaved());
|
||||
}
|
||||
@ -477,21 +478,20 @@ class StackSegment
|
||||
return initialFrame;
|
||||
}
|
||||
|
||||
inline JSStackFrame *getCurrentFrame() const;
|
||||
inline JSFrameRegs *getCurrentRegs() const;
|
||||
inline JSStackFrame *getCurrentFrame() const;
|
||||
|
||||
/* Data available when isSuspended. */
|
||||
|
||||
JSStackFrame *getSuspendedFrame() const {
|
||||
JS_ASSERT(isSuspended());
|
||||
return suspendedFrame;
|
||||
}
|
||||
|
||||
JSFrameRegs *getSuspendedRegs() const {
|
||||
JS_ASSERT(isSuspended());
|
||||
return suspendedRegs;
|
||||
}
|
||||
|
||||
JSStackFrame *getSuspendedFrame() const {
|
||||
return suspendedRegs->fp;
|
||||
}
|
||||
|
||||
/* JSContext / js::StackSpace bookkeeping. */
|
||||
|
||||
void setPreviousInContext(StackSegment *seg) {
|
||||
@ -560,14 +560,12 @@ class InvokeFrameGuard
|
||||
{
|
||||
friend class StackSpace;
|
||||
JSContext *cx; /* null implies nothing pushed */
|
||||
JSStackFrame *fp;
|
||||
JSFrameRegs regs;
|
||||
JSFrameRegs *prevRegs;
|
||||
public:
|
||||
InvokeFrameGuard() : cx(NULL), fp(NULL) {}
|
||||
InvokeFrameGuard() : cx(NULL) {}
|
||||
JS_REQUIRES_STACK ~InvokeFrameGuard();
|
||||
bool pushed() const { return cx != NULL; }
|
||||
JSStackFrame *getFrame() { return fp; }
|
||||
JSFrameRegs &getRegs() { return regs; }
|
||||
};
|
||||
|
||||
@ -817,8 +815,7 @@ class StackSpace
|
||||
void getSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *&seg, JSStackFrame *&fp);
|
||||
|
||||
JS_REQUIRES_STACK
|
||||
void pushSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *seg, JSStackFrame *fp,
|
||||
JSFrameRegs ®s);
|
||||
void pushSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *seg, JSFrameRegs ®s);
|
||||
|
||||
JS_REQUIRES_STACK
|
||||
void popSynthesizedSlowNativeFrame(JSContext *cx);
|
||||
@ -1976,26 +1973,32 @@ struct JSContext
|
||||
/* GC heap compartment. */
|
||||
JSCompartment *compartment;
|
||||
|
||||
/* Currently executing frame, set by stack operations. */
|
||||
JS_REQUIRES_STACK
|
||||
JSStackFrame *fp;
|
||||
|
||||
/*
|
||||
* Currently executing frame's regs, set by stack operations.
|
||||
* |fp != NULL| iff |regs != NULL| (although regs->pc can be NULL)
|
||||
*/
|
||||
/* Currently executing frame and regs, set by stack operations. */
|
||||
JS_REQUIRES_STACK
|
||||
JSFrameRegs *regs;
|
||||
|
||||
/* Current frame accessors. */
|
||||
|
||||
JSStackFrame* fp() {
|
||||
JS_ASSERT(regs && regs->fp);
|
||||
return regs->fp;
|
||||
}
|
||||
|
||||
JSStackFrame* maybefp() {
|
||||
JS_ASSERT_IF(regs, regs->fp);
|
||||
return regs ? regs->fp : NULL;
|
||||
}
|
||||
|
||||
bool hasfp() {
|
||||
JS_ASSERT_IF(regs, regs->fp);
|
||||
return !!regs;
|
||||
}
|
||||
|
||||
public:
|
||||
friend class js::StackSpace;
|
||||
friend bool js::Interpret(JSContext *, JSStackFrame *, uintN);
|
||||
|
||||
/* 'fp' and 'regs' must only be changed by calling these functions. */
|
||||
void setCurrentFrame(JSStackFrame *fp) {
|
||||
this->fp = fp;
|
||||
}
|
||||
|
||||
/* 'regs' must only be changed by calling this function. */
|
||||
void setCurrentRegs(JSFrameRegs *regs) {
|
||||
this->regs = regs;
|
||||
}
|
||||
@ -2046,7 +2049,7 @@ struct JSContext
|
||||
public:
|
||||
void assertSegmentsInSync() const {
|
||||
#ifdef DEBUG
|
||||
if (fp) {
|
||||
if (regs) {
|
||||
JS_ASSERT(currentSegment->isActive());
|
||||
if (js::StackSegment *prev = currentSegment->getPreviousInContext())
|
||||
JS_ASSERT(!prev->isActive());
|
||||
@ -2059,7 +2062,7 @@ struct JSContext
|
||||
/* Return whether this context has an active segment. */
|
||||
bool hasActiveSegment() const {
|
||||
assertSegmentsInSync();
|
||||
return !!fp;
|
||||
return !!regs;
|
||||
}
|
||||
|
||||
/* Assuming there is an active segment, return it. */
|
||||
@ -2075,8 +2078,7 @@ struct JSContext
|
||||
}
|
||||
|
||||
/* Add the given segment to the list as the new active segment. */
|
||||
void pushSegmentAndFrame(js::StackSegment *newseg, JSStackFrame *newfp,
|
||||
JSFrameRegs ®s);
|
||||
void pushSegmentAndFrame(js::StackSegment *newseg, JSFrameRegs ®s);
|
||||
|
||||
/* Remove the active segment and make the next segment active. */
|
||||
void popSegmentAndFrame();
|
||||
@ -2097,7 +2099,7 @@ struct JSContext
|
||||
* Search the call stack for the nearest frame with static level targetLevel.
|
||||
*/
|
||||
JSStackFrame *findFrameAtLevel(uintN targetLevel) {
|
||||
JSStackFrame *fp = this->fp;
|
||||
JSStackFrame *fp = this->regs->fp;
|
||||
while (true) {
|
||||
JS_ASSERT(fp && fp->hasScript());
|
||||
if (fp->getScript()->staticLevel == targetLevel)
|
||||
@ -2356,8 +2358,8 @@ struct JSContext
|
||||
|
||||
#ifdef DEBUG
|
||||
void assertValidStackDepth(uintN depth) {
|
||||
JS_ASSERT(0 <= regs->sp - fp->base());
|
||||
JS_ASSERT(depth <= uintptr_t(regs->sp - fp->base()));
|
||||
JS_ASSERT(0 <= regs->sp - regs->fp->base());
|
||||
JS_ASSERT(depth <= uintptr_t(regs->sp - regs->fp->base()));
|
||||
}
|
||||
#else
|
||||
void assertValidStackDepth(uintN /*depth*/) {}
|
||||
@ -2397,8 +2399,8 @@ JSStackFrame::varobj(JSContext *cx) const
|
||||
JS_ALWAYS_INLINE jsbytecode *
|
||||
JSStackFrame::pc(JSContext *cx) const
|
||||
{
|
||||
JS_ASSERT(cx->containingSegment(this) != NULL);
|
||||
return (cx->fp == this) ? cx->regs->pc : savedPC;
|
||||
JS_ASSERT(cx->regs && cx->containingSegment(this) != NULL);
|
||||
return (cx->regs->fp == this) ? cx->regs->pc : savedPC;
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
@ -3279,8 +3281,8 @@ SetPendingException(JSContext *cx, const Value &v);
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* Get the current cx->fp, first lazily instantiating stack frames if needed.
|
||||
* (Do not access cx->fp directly except in JS_REQUIRES_STACK code.)
|
||||
* Get the current frame, first lazily instantiating stack frames if needed.
|
||||
* (Do not access cx->fp() directly except in JS_REQUIRES_STACK code.)
|
||||
*
|
||||
* Defined in jstracer.cpp if JS_TRACER is defined.
|
||||
*/
|
||||
@ -3288,7 +3290,7 @@ static JS_FORCES_STACK JS_INLINE JSStackFrame *
|
||||
js_GetTopStackFrame(JSContext *cx)
|
||||
{
|
||||
js::LeaveTrace(cx);
|
||||
return cx->fp;
|
||||
return cx->maybefp();
|
||||
}
|
||||
|
||||
static JS_INLINE JSBool
|
||||
|
@ -57,13 +57,6 @@ JSContext::ensureGeneratorStackSpace()
|
||||
|
||||
namespace js {
|
||||
|
||||
JS_REQUIRES_STACK JS_ALWAYS_INLINE JSStackFrame *
|
||||
StackSegment::getCurrentFrame() const
|
||||
{
|
||||
JS_ASSERT(inContext());
|
||||
return isActive() ? cx->fp : getSuspendedFrame();
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK JS_ALWAYS_INLINE JSFrameRegs *
|
||||
StackSegment::getCurrentRegs() const
|
||||
{
|
||||
@ -71,6 +64,12 @@ StackSegment::getCurrentRegs() const
|
||||
return isActive() ? cx->regs : getSuspendedRegs();
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK JS_ALWAYS_INLINE JSStackFrame *
|
||||
StackSegment::getCurrentFrame() const
|
||||
{
|
||||
return getCurrentRegs()->fp;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK inline Value *
|
||||
StackSpace::firstUnused() const
|
||||
{
|
||||
@ -83,7 +82,8 @@ StackSpace::firstUnused() const
|
||||
Value *sp = seg->getCurrentRegs()->sp;
|
||||
if (invokeArgEnd > sp) {
|
||||
JS_ASSERT(invokeSegment == currentSegment);
|
||||
JS_ASSERT_IF(seg->maybeContext()->fp, invokeFrame == seg->maybeContext()->fp);
|
||||
JS_ASSERT_IF(seg->maybeContext()->hasfp(),
|
||||
invokeFrame == seg->maybeContext()->fp());
|
||||
return invokeArgEnd;
|
||||
}
|
||||
return sp;
|
||||
@ -219,7 +219,7 @@ StackSpace::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard &ag)
|
||||
ag.prevInvokeSegment = invokeSegment;
|
||||
invokeSegment = currentSegment;
|
||||
ag.prevInvokeFrame = invokeFrame;
|
||||
invokeFrame = cx->fp;
|
||||
invokeFrame = cx->maybefp();
|
||||
#endif
|
||||
|
||||
ag.cx = cx;
|
||||
@ -238,7 +238,7 @@ StackSpace::popInvokeArgs(const InvokeArgsGuard &ag)
|
||||
|
||||
JS_ASSERT(isCurrentAndActive(ag.cx));
|
||||
JS_ASSERT(invokeSegment == currentSegment);
|
||||
JS_ASSERT(invokeFrame == ag.cx->fp);
|
||||
JS_ASSERT(invokeFrame == ag.cx->maybefp());
|
||||
JS_ASSERT(invokeArgEnd == ag.argv() + ag.argc());
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -267,7 +267,7 @@ StackSpace::getInvokeFrame(JSContext *cx, const CallArgs &args,
|
||||
ptrdiff_t nvals = nmissing + VALUES_PER_STACK_FRAME + nfixed;
|
||||
if (!ensureSpace(cx, start, nvals))
|
||||
return false;
|
||||
fg.fp = reinterpret_cast<JSStackFrame *>(start + nmissing);
|
||||
fg.regs.fp = reinterpret_cast<JSStackFrame *>(start + nmissing);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -277,18 +277,17 @@ StackSpace::pushInvokeFrame(JSContext *cx, const CallArgs &args,
|
||||
{
|
||||
JS_ASSERT(firstUnused() == args.argv() + args.argc());
|
||||
|
||||
JSStackFrame *fp = fg.fp;
|
||||
JSStackFrame *down = cx->fp;
|
||||
JSStackFrame *fp = fg.regs.fp;
|
||||
JSStackFrame *down = cx->maybefp();
|
||||
fp->down = down;
|
||||
if (JS_UNLIKELY(!currentSegment->inContext())) {
|
||||
cx->pushSegmentAndFrame(currentSegment, fp, fg.regs);
|
||||
cx->pushSegmentAndFrame(currentSegment, fg.regs);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fp->savedPC = JSStackFrame::sInvalidPC;
|
||||
JS_ASSERT(down->savedPC == JSStackFrame::sInvalidPC);
|
||||
#endif
|
||||
down->savedPC = cx->regs->pc;
|
||||
cx->setCurrentFrame(fp);
|
||||
fg.prevRegs = cx->regs;
|
||||
cx->setCurrentRegs(&fg.regs);
|
||||
}
|
||||
@ -301,18 +300,17 @@ JS_REQUIRES_STACK JS_ALWAYS_INLINE void
|
||||
StackSpace::popInvokeFrame(const InvokeFrameGuard &fg)
|
||||
{
|
||||
JSContext *cx = fg.cx;
|
||||
JSStackFrame *fp = fg.fp;
|
||||
JSStackFrame *fp = fg.regs.fp;
|
||||
|
||||
JS_ASSERT(isCurrentAndActive(cx));
|
||||
if (JS_UNLIKELY(currentSegment->getInitialFrame() == fp)) {
|
||||
cx->popSegmentAndFrame();
|
||||
} else {
|
||||
JS_ASSERT(fp == cx->fp);
|
||||
JS_ASSERT(&fg.regs == cx->regs);
|
||||
cx->setCurrentFrame(fp->down);
|
||||
JS_ASSERT(fp->down == fg.prevRegs->fp);
|
||||
cx->setCurrentRegs(fg.prevRegs);
|
||||
#ifdef DEBUG
|
||||
cx->fp->savedPC = JSStackFrame::sInvalidPC;
|
||||
cx->fp()->savedPC = JSStackFrame::sInvalidPC;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -353,14 +351,13 @@ StackSpace::pushInlineFrame(JSContext *cx, JSStackFrame *fp, jsbytecode *pc,
|
||||
JSStackFrame *newfp)
|
||||
{
|
||||
JS_ASSERT(isCurrentAndActive(cx));
|
||||
JS_ASSERT(cx->fp == fp && cx->regs->pc == pc);
|
||||
JS_ASSERT(cx->regs->fp == fp && cx->regs->pc == pc);
|
||||
|
||||
fp->savedPC = pc;
|
||||
newfp->down = fp;
|
||||
#ifdef DEBUG
|
||||
newfp->savedPC = JSStackFrame::sInvalidPC;
|
||||
#endif
|
||||
cx->setCurrentFrame(newfp);
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK JS_ALWAYS_INLINE void
|
||||
@ -368,16 +365,16 @@ StackSpace::popInlineFrame(JSContext *cx, JSStackFrame *up, JSStackFrame *down)
|
||||
{
|
||||
JS_ASSERT(isCurrentAndActive(cx));
|
||||
JS_ASSERT(cx->hasActiveSegment());
|
||||
JS_ASSERT(cx->fp == up && up->down == down);
|
||||
JS_ASSERT(cx->regs->fp == up && up->down == down);
|
||||
JS_ASSERT(up->savedPC == JSStackFrame::sInvalidPC);
|
||||
JS_ASSERT(!up->hasIMacroPC());
|
||||
|
||||
JSFrameRegs *regs = cx->regs;
|
||||
regs->fp = down;
|
||||
regs->pc = down->savedPC;
|
||||
#ifdef DEBUG
|
||||
down->savedPC = JSStackFrame::sInvalidPC;
|
||||
#endif
|
||||
cx->setCurrentFrame(down);
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK inline
|
||||
@ -388,8 +385,8 @@ FrameRegsIter::FrameRegsIter(JSContext *cx)
|
||||
initSlow();
|
||||
return;
|
||||
}
|
||||
JS_ASSERT(cx->fp);
|
||||
curfp = cx->fp;
|
||||
JS_ASSERT(cx->regs->fp);
|
||||
curfp = cx->regs->fp;
|
||||
cursp = cx->regs->sp;
|
||||
curpc = cx->regs->pc;
|
||||
return;
|
||||
@ -467,7 +464,7 @@ class CompartmentChecker
|
||||
|
||||
public:
|
||||
explicit CompartmentChecker(JSContext *cx) : context(cx), compartment(cx->compartment) {
|
||||
check(cx->fp ? JS_GetGlobalForScopeChain(cx) : cx->globalObject);
|
||||
check(cx->hasfp() ? JS_GetGlobalForScopeChain(cx) : cx->globalObject);
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
}
|
||||
|
||||
|
@ -2830,7 +2830,7 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun)
|
||||
* Flat closures can be partial, they may need to search enclosing scope
|
||||
* objects via JSOP_NAME, etc.
|
||||
*/
|
||||
JSObject *scopeChain = js_GetScopeChain(cx, cx->fp);
|
||||
JSObject *scopeChain = js_GetScopeChain(cx, cx->fp());
|
||||
if (!scopeChain)
|
||||
return NULL;
|
||||
|
||||
@ -2851,11 +2851,11 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun)
|
||||
JSObject *
|
||||
js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
JS_ASSERT(cx->fp->getFunction()->flags & JSFUN_HEAVYWEIGHT);
|
||||
JS_ASSERT(!cx->fp->getFunction()->optimizedClosure());
|
||||
JS_ASSERT(cx->fp()->getFunction()->flags & JSFUN_HEAVYWEIGHT);
|
||||
JS_ASSERT(!cx->fp()->getFunction()->optimizedClosure());
|
||||
JS_ASSERT(FUN_FLAT_CLOSURE(fun));
|
||||
|
||||
return WrapEscapingClosure(cx, cx->fp, fun);
|
||||
return WrapEscapingClosure(cx, cx->fp(), fun);
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
|
@ -527,7 +527,7 @@ InvokeCommon(JSContext *cx, JSFunction *fun, JSScript *script, T native,
|
||||
InvokeFrameGuard frame;
|
||||
if (!cx->stack().getInvokeFrame(cx, args, nmissing, nfixed, frame))
|
||||
return false;
|
||||
JSStackFrame *fp = frame.getFrame();
|
||||
JSStackFrame *fp = frame.getRegs().fp;
|
||||
|
||||
/* Initialize missing missing arguments and new local variables. */
|
||||
Value *missing = args.argv() + args.argc();
|
||||
@ -627,7 +627,7 @@ InvokeCommon(JSContext *cx, JSFunction *fun, JSScript *script, T native,
|
||||
ok = callJSNative(cx, native, thisp, fp->numActualArgs(), fp->argv,
|
||||
fp->addressReturnValue());
|
||||
|
||||
JS_ASSERT(cx->fp == fp);
|
||||
JS_ASSERT(cx->fp() == fp);
|
||||
JS_RUNTIME_METER(cx->runtime, nativeCalls);
|
||||
#ifdef DEBUG_NOT_THROWING
|
||||
if (ok && !alreadyThrowing)
|
||||
@ -667,7 +667,7 @@ DoConstruct(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
static JSBool
|
||||
DoSlowCall(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSStackFrame *fp = cx->fp;
|
||||
JSStackFrame *fp = cx->fp();
|
||||
JSObject *obj = fp->getThisObject(cx);
|
||||
if (!obj)
|
||||
return false;
|
||||
@ -887,12 +887,12 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script,
|
||||
|
||||
/*
|
||||
* We want to call |down->varobj()|, but this requires knowing the
|
||||
* CallStackSegment of |down|. If |down == cx->fp|, the callstack is
|
||||
* CallStackSegment of |down|. If |down == cx->fp()|, the callstack is
|
||||
* simply the context's active callstack, so we can use
|
||||
* |down->varobj(cx)|. When |down != cx->fp|, we need to do a slow
|
||||
* |down->varobj(cx)|. When |down != cx->fp()|, we need to do a slow
|
||||
* linear search. Luckily, this only happens with EvaluateInFrame.
|
||||
*/
|
||||
initialVarObj = (down == cx->fp)
|
||||
initialVarObj = (down == cx->maybefp())
|
||||
? down->varobj(cx)
|
||||
: down->varobj(cx->containingSegment(down));
|
||||
} else {
|
||||
@ -1278,7 +1278,7 @@ ValueToId(JSContext *cx, const Value &v, jsid *idp)
|
||||
JS_STATIC_INTERPRET JS_REQUIRES_STACK JSBool
|
||||
js_EnterWith(JSContext *cx, jsint stackIndex)
|
||||
{
|
||||
JSStackFrame *fp = cx->fp;
|
||||
JSStackFrame *fp = cx->fp();
|
||||
Value *sp = cx->regs->sp;
|
||||
JS_ASSERT(stackIndex < 0);
|
||||
JS_ASSERT(fp->base() <= sp + stackIndex);
|
||||
@ -1315,11 +1315,11 @@ js_LeaveWith(JSContext *cx)
|
||||
{
|
||||
JSObject *withobj;
|
||||
|
||||
withobj = cx->fp->getScopeChain();
|
||||
withobj = cx->fp()->getScopeChain();
|
||||
JS_ASSERT(withobj->getClass() == &js_WithClass);
|
||||
JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp));
|
||||
JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
|
||||
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
|
||||
cx->fp->setScopeChain(withobj->getParent());
|
||||
cx->fp()->setScopeChain(withobj->getParent());
|
||||
withobj->setPrivate(NULL);
|
||||
}
|
||||
|
||||
@ -1330,7 +1330,7 @@ js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth)
|
||||
|
||||
clasp = obj->getClass();
|
||||
if ((clasp == &js_WithClass || clasp == &js_BlockClass) &&
|
||||
obj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp) &&
|
||||
obj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
|
||||
OBJ_BLOCK_DEPTH(cx, obj) >= stackDepth) {
|
||||
return clasp;
|
||||
}
|
||||
@ -1348,9 +1348,9 @@ js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind)
|
||||
Class *clasp;
|
||||
|
||||
JS_ASSERT(stackDepth >= 0);
|
||||
JS_ASSERT(cx->fp->base() + stackDepth <= cx->regs->sp);
|
||||
JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs->sp);
|
||||
|
||||
JSStackFrame *fp = cx->fp;
|
||||
JSStackFrame *fp = cx->fp();
|
||||
for (obj = fp->maybeBlockChain(); obj; obj = obj->getParent()) {
|
||||
JS_ASSERT(obj->getClass() == &js_BlockClass);
|
||||
if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth)
|
||||
@ -1438,7 +1438,7 @@ js_TraceOpcode(JSContext *cx)
|
||||
|
||||
tracefp = (FILE *) cx->tracefp;
|
||||
JS_ASSERT(tracefp);
|
||||
fp = cx->fp;
|
||||
fp = cx->fp();
|
||||
regs = cx->regs;
|
||||
|
||||
/*
|
||||
@ -2249,7 +2249,7 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount)
|
||||
JSRuntime *const rt = cx->runtime;
|
||||
|
||||
/* Set registerized frame pointer and derived script pointer. */
|
||||
JSStackFrame *fp = cx->fp;
|
||||
JSStackFrame *fp = cx->fp();
|
||||
JSScript *script = fp->getScript();
|
||||
JS_ASSERT(!script->isEmpty());
|
||||
JS_ASSERT(script->length > 1);
|
||||
@ -2316,7 +2316,7 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount)
|
||||
|
||||
#define RESTORE_INTERP_VARS() \
|
||||
JS_BEGIN_MACRO \
|
||||
fp = cx->fp; \
|
||||
fp = cx->fp(); \
|
||||
script = fp->getScript(); \
|
||||
atoms = FrameAtomBase(cx, fp); \
|
||||
currentVersion = (JSVersion) script->version; \
|
||||
@ -2792,7 +2792,7 @@ BEGIN_CASE(JSOP_STOP)
|
||||
regs.sp[-1] = fp->getReturnValue();
|
||||
|
||||
/* Sync interpreter registers. */
|
||||
fp = cx->fp;
|
||||
fp = cx->fp();
|
||||
script = fp->getScript();
|
||||
atoms = FrameAtomBase(cx, fp);
|
||||
|
||||
@ -4752,11 +4752,12 @@ BEGIN_CASE(JSOP_APPLY)
|
||||
stack.pushInlineFrame(cx, fp, regs.pc, newfp);
|
||||
|
||||
/* Initializer regs after pushInlineFrame snapshots pc. */
|
||||
regs.fp = newfp;
|
||||
regs.pc = newscript->code;
|
||||
regs.sp = newsp;
|
||||
|
||||
/* Import into locals. */
|
||||
JS_ASSERT(newfp == cx->fp);
|
||||
JS_ASSERT(newfp == cx->fp());
|
||||
fp = newfp;
|
||||
script = newscript;
|
||||
atoms = script->atomMap.vector;
|
||||
|
@ -53,6 +53,7 @@
|
||||
typedef struct JSFrameRegs {
|
||||
js::Value *sp; /* stack pointer */
|
||||
jsbytecode *pc; /* program counter */
|
||||
JSStackFrame *fp; /* active frame */
|
||||
} JSFrameRegs;
|
||||
|
||||
/* JS stack frame flags. */
|
||||
|
@ -1140,7 +1140,7 @@ js_NewGenerator(JSContext *cx)
|
||||
return NULL;
|
||||
|
||||
/* Load and compute stack slot counts. */
|
||||
JSStackFrame *fp = cx->fp;
|
||||
JSStackFrame *fp = cx->fp();
|
||||
uintN argc = fp->numActualArgs();
|
||||
uintN nargs = JS_MAX(argc, fp->numFormalArgs());
|
||||
uintN vplen = 2 + nargs;
|
||||
@ -1276,7 +1276,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
|
||||
* the code before pushExecuteFrame must not reenter the interpreter.
|
||||
*/
|
||||
ExecuteFrameGuard frame;
|
||||
if (!cx->stack().getExecuteFrame(cx, cx->fp, vplen, nfixed, frame)) {
|
||||
if (!cx->stack().getExecuteFrame(cx, cx->maybefp(), vplen, nfixed, frame)) {
|
||||
gen->state = JSGEN_CLOSED;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -2693,10 +2693,10 @@ Detecting(JSContext *cx, jsbytecode *pc)
|
||||
JSOp op;
|
||||
JSAtom *atom;
|
||||
|
||||
script = cx->fp->getScript();
|
||||
script = cx->fp()->getScript();
|
||||
endpc = script->code + script->length;
|
||||
for (;; pc += js_CodeSpec[op].length) {
|
||||
JS_ASSERT_IF(!cx->fp->hasIMacroPC(), script->code <= pc && pc < endpc);
|
||||
JS_ASSERT_IF(!cx->fp()->hasIMacroPC(), script->code <= pc && pc < endpc);
|
||||
|
||||
/* General case: a branch or equality op follows the access. */
|
||||
op = js_GetOpcode(cx, script, pc);
|
||||
@ -2776,7 +2776,8 @@ js_InferFlags(JSContext *cx, uintN defaultFlags)
|
||||
flags |= JSRESOLVE_ASSIGNING;
|
||||
} else if (cs->length >= 0) {
|
||||
pc += cs->length;
|
||||
if (pc < cx->fp->getScript()->code + cx->fp->getScript()->length && Detecting(cx, pc))
|
||||
JSScript *script = cx->fp()->getScript();
|
||||
if (pc < script->code + script->length && Detecting(cx, pc))
|
||||
flags |= JSRESOLVE_DETECTING;
|
||||
}
|
||||
if (format & JOF_DECLARING)
|
||||
@ -2893,7 +2894,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
|
||||
if (!obj)
|
||||
return NULL;
|
||||
obj->init(&js_WithClass, proto, parent,
|
||||
PrivateValue(js_FloatingFrameIfGenerator(cx, cx->fp)));
|
||||
PrivateValue(js_FloatingFrameIfGenerator(cx, cx->fp())));
|
||||
OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
|
||||
obj->map = cx->runtime->emptyWithScope->hold();
|
||||
|
||||
@ -2952,10 +2953,10 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
|
||||
/* Blocks have one fixed slot available for the first local.*/
|
||||
JS_STATIC_ASSERT(JS_INITIAL_NSLOTS == JSSLOT_BLOCK_DEPTH + 2);
|
||||
|
||||
JSStackFrame *const fp = cx->fp;
|
||||
JSStackFrame *const fp = cx->fp();
|
||||
JSObject *obj = fp->getScopeChain();
|
||||
JS_ASSERT(obj->getClass() == &js_BlockClass);
|
||||
JS_ASSERT(obj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp));
|
||||
JS_ASSERT(obj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
|
||||
JS_ASSERT(OBJ_IS_CLONED_BLOCK(obj));
|
||||
|
||||
/*
|
||||
@ -3730,12 +3731,12 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
|
||||
JSScopeProperty *sprop;
|
||||
|
||||
/*
|
||||
* Find the global object. Use cx->fp directly to avoid falling off
|
||||
* Find the global object. Use cx->fp() directly to avoid falling off
|
||||
* trace; all JIT-elided stack frames have the same global object as
|
||||
* cx->fp.
|
||||
* cx->fp().
|
||||
*/
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
if (!start && (fp = cx->fp) != NULL)
|
||||
if (!start && (fp = cx->maybefp()) != NULL)
|
||||
start = fp->maybeScopeChain();
|
||||
|
||||
if (start) {
|
||||
@ -4776,7 +4777,7 @@ js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow,
|
||||
op = (JSOp) *pc;
|
||||
if (op == JSOP_TRAP) {
|
||||
JS_ASSERT_NOT_ON_TRACE(cx);
|
||||
op = JS_GetTrapOpcode(cx, cx->fp->getScript(), pc);
|
||||
op = JS_GetTrapOpcode(cx, cx->fp()->getScript(), pc);
|
||||
}
|
||||
if (op == JSOP_GETXPROP) {
|
||||
flags = JSREPORT_ERROR;
|
||||
@ -5263,7 +5264,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval)
|
||||
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
|
||||
|
||||
if (fun != funobj) {
|
||||
for (JSStackFrame *fp = cx->fp; fp; fp = fp->down) {
|
||||
for (JSStackFrame *fp = cx->maybefp(); fp; fp = fp->down) {
|
||||
if (fp->callee() == fun &&
|
||||
fp->getThisValue().isObject() &&
|
||||
&fp->getThisValue().toObject() == obj) {
|
||||
@ -5560,8 +5561,8 @@ js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
|
||||
|
||||
if (protoKey != JSProto_Null) {
|
||||
if (!scope) {
|
||||
if (cx->fp)
|
||||
scope = cx->fp->maybeScopeChain();
|
||||
if (cx->hasfp())
|
||||
scope = cx->fp()->maybeScopeChain();
|
||||
if (!scope) {
|
||||
scope = cx->globalObject;
|
||||
if (!scope) {
|
||||
@ -6351,7 +6352,7 @@ js_DumpStackFrame(JSContext *cx, JSStackFrame *start)
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
|
||||
if (!start)
|
||||
start = cx->fp;
|
||||
start = cx->maybefp();
|
||||
FrameRegsIter i(cx);
|
||||
while (!i.done() && i.fp() != start)
|
||||
++i;
|
||||
|
@ -547,7 +547,7 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, JSObject *p
|
||||
JS_ASSERT(proto->isNative());
|
||||
JS_ASSERT(parent);
|
||||
|
||||
DTrace::ObjectCreationScope objectCreationScope(cx, cx->fp, clasp);
|
||||
DTrace::ObjectCreationScope objectCreationScope(cx, cx->maybefp(), clasp);
|
||||
|
||||
/*
|
||||
* Allocate an object from the GC heap and initialize all its fields before
|
||||
@ -599,13 +599,13 @@ NewBuiltinClassInstance(JSContext *cx, Class *clasp)
|
||||
|
||||
/* NB: inline-expanded and specialized version of js_GetClassPrototype. */
|
||||
JSObject *global;
|
||||
if (!cx->fp) {
|
||||
if (!cx->hasfp()) {
|
||||
global = cx->globalObject;
|
||||
OBJ_TO_INNER_OBJECT(cx, global);
|
||||
if (!global)
|
||||
return NULL;
|
||||
} else {
|
||||
global = cx->fp->getScopeChain()->getGlobal();
|
||||
global = cx->fp()->getScopeChain()->getGlobal();
|
||||
}
|
||||
JS_ASSERT(global->getClass()->flags & JSCLASS_IS_GLOBAL);
|
||||
|
||||
@ -682,7 +682,7 @@ NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
|
||||
}
|
||||
|
||||
|
||||
DTrace::ObjectCreationScope objectCreationScope(cx, cx->fp, clasp);
|
||||
DTrace::ObjectCreationScope objectCreationScope(cx, cx->maybefp(), clasp);
|
||||
|
||||
/*
|
||||
* Allocate an object from the GC heap and initialize all its fields before
|
||||
|
@ -279,7 +279,7 @@ js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp)
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_DumpPC(JSContext *cx)
|
||||
{
|
||||
return js_DisassembleAtPC(cx, cx->fp->getScript(), true, stdout, cx->regs->pc);
|
||||
return js_DisassembleAtPC(cx, cx->fp()->getScript(), true, stdout, cx->regs->pc);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -5190,7 +5190,8 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v_in,
|
||||
jsbytecode* savepc = i.pc();
|
||||
jsbytecode* savedIMacroPC = fp->maybeIMacroPC();
|
||||
if (savedIMacroPC) {
|
||||
if (fp == cx->fp)
|
||||
JS_ASSERT(cx->hasfp());
|
||||
if (fp == cx->fp())
|
||||
cx->regs->pc = savedIMacroPC;
|
||||
else
|
||||
fp->savedPC = savedIMacroPC;
|
||||
@ -5208,7 +5209,8 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v_in,
|
||||
name = DecompileExpression(cx, script, fp->maybeFunction(), pc);
|
||||
|
||||
if (savedIMacroPC) {
|
||||
if (fp == cx->fp)
|
||||
JS_ASSERT(cx->hasfp());
|
||||
if (fp == cx->fp())
|
||||
cx->regs->pc = savedIMacroPC;
|
||||
else
|
||||
fp->savedPC = savepc;
|
||||
|
@ -62,7 +62,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
|
||||
JS_ASSERT(!cx->runtime->gcRunning);
|
||||
|
||||
/* FIXME bug 489098: consider enabling the property cache for eval. */
|
||||
if (js_IsPropertyCacheDisabled(cx) || (cx->fp->flags & JSFRAME_EVAL)) {
|
||||
if (js_IsPropertyCacheDisabled(cx) || (cx->fp()->flags & JSFRAME_EVAL)) {
|
||||
PCMETER(disfills++);
|
||||
return JS_NO_PROP_CACHE_FILL;
|
||||
}
|
||||
@ -128,7 +128,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
|
||||
* opcode format flags.
|
||||
*/
|
||||
pc = cx->regs->pc;
|
||||
op = js_GetOpcode(cx, cx->fp->getScript(), pc);
|
||||
op = js_GetOpcode(cx, cx->fp()->getScript(), pc);
|
||||
cs = &js_CodeSpec[op];
|
||||
kshape = 0;
|
||||
|
||||
@ -322,7 +322,7 @@ GetAtomFromBytecode(JSContext *cx, jsbytecode *pc, JSOp op, const JSCodeSpec &cs
|
||||
|
||||
ptrdiff_t pcoff = (JOF_TYPE(cs.format) == JOF_SLOTATOM) ? SLOTNO_LEN : 0;
|
||||
JSAtom *atom;
|
||||
GET_ATOM_FROM_BYTECODE(cx->fp->getScript(), pc, pcoff, atom);
|
||||
GET_ATOM_FROM_BYTECODE(cx->fp()->getScript(), pc, pcoff, atom);
|
||||
return atom;
|
||||
}
|
||||
|
||||
@ -333,12 +333,13 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
|
||||
JSObject *obj, *pobj, *tmp;
|
||||
uint32 vcap;
|
||||
|
||||
JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
|
||||
JS_ASSERT(
|
||||
uintN((cx->fp->hasIMacroPC() ? cx->fp->getIMacroPC() : pc) - cx->fp->getScript()->code)
|
||||
< cx->fp->getScript()->length);
|
||||
JSStackFrame *fp = cx->fp();
|
||||
|
||||
JSOp op = js_GetOpcode(cx, cx->fp->getScript(), pc);
|
||||
JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
|
||||
JS_ASSERT(uintN((fp->hasIMacroPC() ? fp->getIMacroPC() : pc) - fp->getScript()->code)
|
||||
< fp->getScript()->length);
|
||||
|
||||
JSOp op = js_GetOpcode(cx, fp->getScript(), pc);
|
||||
const JSCodeSpec &cs = js_CodeSpec[op];
|
||||
|
||||
obj = *objp;
|
||||
|
@ -183,10 +183,10 @@ TraceRecorder::downSnapshot(FrameInfo* downFrame)
|
||||
JS_ASSERT(unsigned(exit->calldepth) == callDepth);
|
||||
exit->numGlobalSlots = ngslots;
|
||||
exit->numStackSlots = downPostSlots + 1;
|
||||
exit->numStackSlotsBelowCurrentFrame = cx->fp->down->argv ?
|
||||
nativeStackOffset(&cx->fp->argv[-2]) / sizeof(double) : 0;
|
||||
exit->numStackSlotsBelowCurrentFrame = cx->fp()->down->argv ?
|
||||
nativeStackOffset(&cx->fp()->argv[-2]) / sizeof(double) : 0;
|
||||
exit->exitType = UNSTABLE_LOOP_EXIT;
|
||||
exit->block = cx->fp->down->maybeBlockChain();
|
||||
exit->block = cx->fp()->down->maybeBlockChain();
|
||||
exit->pc = downFrame->pc + JSOP_CALL_LENGTH;
|
||||
exit->imacpc = NULL;
|
||||
exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - tree->nativeStackBase;
|
||||
@ -205,16 +205,16 @@ DownFrameSP(JSContext *cx)
|
||||
{
|
||||
FrameRegsIter i(cx);
|
||||
++i;
|
||||
JS_ASSERT(i.fp() == cx->fp->down);
|
||||
JS_ASSERT(i.fp() == cx->fp()->down);
|
||||
return i.sp();
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::upRecursion()
|
||||
{
|
||||
JS_ASSERT((JSOp)*cx->fp->down->savedPC == JSOP_CALL);
|
||||
JS_ASSERT(js_CodeSpec[js_GetOpcode(cx, cx->fp->down->getScript(),
|
||||
cx->fp->down->savedPC)].length == JSOP_CALL_LENGTH);
|
||||
JS_ASSERT((JSOp)*cx->fp()->down->savedPC == JSOP_CALL);
|
||||
JS_ASSERT(js_CodeSpec[js_GetOpcode(cx, cx->fp()->down->getScript(),
|
||||
cx->fp()->down->savedPC)].length == JSOP_CALL_LENGTH);
|
||||
|
||||
JS_ASSERT(callDepth == 0);
|
||||
|
||||
@ -226,10 +226,10 @@ TraceRecorder::upRecursion()
|
||||
if (anchor && (anchor->exitType == RECURSIVE_EMPTY_RP_EXIT ||
|
||||
anchor->exitType == RECURSIVE_SLURP_MISMATCH_EXIT ||
|
||||
anchor->exitType == RECURSIVE_SLURP_FAIL_EXIT)) {
|
||||
return slurpDownFrames(cx->fp->down->savedPC);
|
||||
return slurpDownFrames(cx->fp()->down->savedPC);
|
||||
}
|
||||
|
||||
jsbytecode* return_pc = cx->fp->down->savedPC;
|
||||
jsbytecode* return_pc = cx->fp()->down->savedPC;
|
||||
jsbytecode* recursive_pc = return_pc + JSOP_CALL_LENGTH;
|
||||
|
||||
/*
|
||||
@ -256,11 +256,11 @@ TraceRecorder::upRecursion()
|
||||
* Need to compute this from the down frame, since the stack could have
|
||||
* moved on this one.
|
||||
*/
|
||||
fi->spdist = DownFrameSP(cx) - cx->fp->down->slots();
|
||||
JS_ASSERT(cx->fp->numActualArgs() == cx->fp->down->numActualArgs());
|
||||
fi->set_argc(uint16(cx->fp->numActualArgs()), false);
|
||||
fi->spdist = DownFrameSP(cx) - cx->fp()->down->slots();
|
||||
JS_ASSERT(cx->fp()->numActualArgs() == cx->fp()->down->numActualArgs());
|
||||
fi->set_argc(uint16(cx->fp()->numActualArgs()), false);
|
||||
fi->callerHeight = downPostSlots;
|
||||
fi->callerArgc = cx->fp->down->numActualArgs();
|
||||
fi->callerArgc = cx->fp()->down->numActualArgs();
|
||||
|
||||
if (anchor && anchor->exitType == RECURSIVE_MISMATCH_EXIT) {
|
||||
/*
|
||||
@ -390,7 +390,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
||||
{
|
||||
/* Missing - no go */
|
||||
if (cx->fp->numActualArgs() != cx->fp->numFormalArgs())
|
||||
if (cx->fp()->numActualArgs() != cx->fp()->numFormalArgs())
|
||||
RETURN_STOP_A("argc != nargs");
|
||||
|
||||
LIns* argv_ins;
|
||||
@ -398,8 +398,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
||||
unsigned downPostSlots;
|
||||
|
||||
FrameRegsIter i(cx);
|
||||
LIns* fp_ins =
|
||||
addName(lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, fp), ACCSET_OTHER), "fp");
|
||||
LIns* fp_ins = addName(entryFrameIns(), "fp");
|
||||
|
||||
/*
|
||||
* When first emitting slurp code, do so against the down frame. After
|
||||
@ -434,7 +433,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
||||
addName(lir->insLoad(LIR_ldp, fp_ins,
|
||||
JSStackFrame::offsetScript(), ACCSET_OTHER),
|
||||
"script"),
|
||||
INS_CONSTPTR(cx->fp->down->getScript())),
|
||||
INS_CONSTPTR(cx->fp()->down->getScript())),
|
||||
RECURSIVE_LOOP_EXIT);
|
||||
}
|
||||
|
||||
@ -453,7 +452,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
|
||||
addName(lir->insLoad(LIR_ldi, fp_ins, JSStackFrame::offsetNumActualArgs(),
|
||||
ACCSET_OTHER),
|
||||
"argc"),
|
||||
INS_CONST(cx->fp->numActualArgs())),
|
||||
INS_CONST(cx->fp()->numActualArgs())),
|
||||
MISMATCH_EXIT);
|
||||
|
||||
/* Pop the interpreter frame. */
|
||||
@ -672,7 +671,7 @@ public:
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::downRecursion()
|
||||
{
|
||||
JSStackFrame* fp = cx->fp;
|
||||
JSStackFrame* fp = cx->fp();
|
||||
JSScript *script = fp->getScript();
|
||||
if ((jsbytecode*)fragment->ip < script->code ||
|
||||
(jsbytecode*)fragment->ip >= script->code + script->length) {
|
||||
|
@ -2340,7 +2340,7 @@ ASTSerializer::literal(JSParseNode *pn, Value *dst)
|
||||
LOCAL_ASSERT(re1 && re1->isRegExp());
|
||||
|
||||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, cx->fp->getScopeChain(), JSProto_RegExp, &proto))
|
||||
if (!js_GetClassPrototype(cx, cx->fp()->getScopeChain(), JSProto_RegExp, &proto))
|
||||
return false;
|
||||
|
||||
JSObject *re2 = js_CloneRegExpObject(cx, re1, proto);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1144,6 +1144,7 @@ class TraceRecorder
|
||||
|
||||
JS_REQUIRES_STACK nanojit::LIns* scopeChain();
|
||||
JS_REQUIRES_STACK nanojit::LIns* entryScopeChain() const;
|
||||
JS_REQUIRES_STACK nanojit::LIns* entryFrameIns() const;
|
||||
JS_REQUIRES_STACK JSStackFrame* frameIfInRange(JSObject* obj, unsigned* depthp = NULL) const;
|
||||
JS_REQUIRES_STACK RecordingStatus traverseScopeChain(JSObject *obj, nanojit::LIns *obj_ins, JSObject *obj2, nanojit::LIns *&obj2_ins);
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus scopeChainProp(JSObject* obj, Value*& vp, nanojit::LIns*& ins, NameResult& nr);
|
||||
|
@ -387,7 +387,8 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
|
||||
* we parent all wrappers to the global object in their home compartment.
|
||||
* This loses us some transparency, and is generally very cheesy.
|
||||
*/
|
||||
JSObject *global = cx->fp ? cx->fp->getScopeChain()->getGlobal() : cx->globalObject;
|
||||
JSObject *global =
|
||||
cx->hasfp() ? cx->fp()->getScopeChain()->getGlobal() : cx->globalObject;
|
||||
wrapper->setParent(global);
|
||||
return true;
|
||||
}
|
||||
|
@ -3195,7 +3195,7 @@ EvalInFrame(JSContext *cx, uintN argc, jsval *vp)
|
||||
? !!(JSVAL_TO_BOOLEAN(argv[2]))
|
||||
: false;
|
||||
|
||||
JS_ASSERT(cx->fp);
|
||||
JS_ASSERT(cx->hasfp());
|
||||
|
||||
FrameRegsIter fi(cx);
|
||||
for (uint32 i = 0; i < upCount; ++i, ++fi) {
|
||||
|
Loading…
Reference in New Issue
Block a user