mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 873155 - Remove StackFrame argument duplication. r=luke
This commit is contained in:
parent
58c6661d63
commit
b14b043ee4
@ -132,7 +132,7 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter)
|
||||
|
||||
if (isFunctionFrame()) {
|
||||
Value thisv = iter.read();
|
||||
formals()[-1] = thisv;
|
||||
argv()[-1] = thisv;
|
||||
|
||||
// The new |this| must have already been constructed prior to an Ion
|
||||
// constructor running.
|
||||
@ -145,7 +145,7 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter)
|
||||
|
||||
for (uint32_t i = 0; i < fun()->nargs; i++) {
|
||||
Value arg = iter.read();
|
||||
formals()[i] = arg;
|
||||
argv()[i] = arg;
|
||||
}
|
||||
}
|
||||
exprStackSlots -= CountArgSlots(script(), maybeFun());
|
||||
@ -197,7 +197,7 @@ PushInlinedFrame(JSContext *cx, StackFrame *callerFrame)
|
||||
JS_ASSERT(js_CodeSpec[*regs.pc].format & JOF_INVOKE);
|
||||
int callerArgc = GET_ARGC(regs.pc);
|
||||
if (JSOp(*regs.pc) == JSOP_FUNAPPLY)
|
||||
callerArgc = callerFrame->nactual();
|
||||
callerArgc = callerFrame->numActualArgs();
|
||||
const Value &calleeVal = regs.sp[-callerArgc - 2];
|
||||
|
||||
RootedFunction fun(cx, calleeVal.toObject().toFunction());
|
||||
@ -219,7 +219,7 @@ PushInlinedFrame(JSContext *cx, StackFrame *callerFrame)
|
||||
JS_ASSERT(fp == regs.fp());
|
||||
JS_ASSERT(fp->prev() == callerFrame);
|
||||
|
||||
fp->formals()[-2].setObject(*fun);
|
||||
fp->argv()[-2].setObject(*fun);
|
||||
|
||||
return fp;
|
||||
}
|
||||
@ -285,7 +285,7 @@ ConvertFrames(JSContext *cx, IonActivation *activation, IonBailoutIterator &it)
|
||||
|
||||
JSFunction *callee = it.maybeCallee();
|
||||
if (callee)
|
||||
fp->formals()[-2].setObject(*callee);
|
||||
fp->argv()[-2].setObject(*callee);
|
||||
|
||||
if (it.isConstructing())
|
||||
fp->setConstructing();
|
||||
|
@ -27,8 +27,7 @@ BaselineFrame::trace(JSTracer *trc)
|
||||
// Mark actual and formal args.
|
||||
if (isNonEvalFunctionFrame()) {
|
||||
unsigned numArgs = js::Max(numActualArgs(), numFormalArgs());
|
||||
JS_ASSERT(actuals() == formals());
|
||||
gc::MarkValueRootRange(trc, numArgs, actuals(), "baseline-args");
|
||||
gc::MarkValueRootRange(trc, numArgs, argv(), "baseline-args");
|
||||
}
|
||||
|
||||
// Mark scope chain.
|
||||
@ -62,7 +61,7 @@ BaselineFrame::copyRawFrameSlots(AutoValueVector *vec) const
|
||||
if (!vec->resize(nformals + nfixed))
|
||||
return false;
|
||||
|
||||
mozilla::PodCopy(vec->begin(), formals(), nformals);
|
||||
mozilla::PodCopy(vec->begin(), argv(), nformals);
|
||||
for (unsigned i = 0; i < nfixed; i++)
|
||||
(*vec)[nformals + i] = *valueSlot(i);
|
||||
return true;
|
||||
|
@ -154,14 +154,14 @@ class BaselineFrame
|
||||
JS_ASSERT(i < numFormalArgs());
|
||||
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
||||
JS_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
|
||||
return formals()[i];
|
||||
return argv()[i];
|
||||
}
|
||||
|
||||
Value &unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing) const {
|
||||
JS_ASSERT(i < numActualArgs());
|
||||
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
||||
JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
|
||||
return actuals()[i];
|
||||
return argv()[i];
|
||||
}
|
||||
|
||||
Value &unaliasedLocal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
|
||||
@ -184,14 +184,11 @@ class BaselineFrame
|
||||
BaselineFrame::Size() +
|
||||
offsetOfThis());
|
||||
}
|
||||
Value *formals() const {
|
||||
Value *argv() const {
|
||||
return (Value *)(reinterpret_cast<const uint8_t *>(this) +
|
||||
BaselineFrame::Size() +
|
||||
offsetOfArg(0));
|
||||
}
|
||||
Value *actuals() const {
|
||||
return formals();
|
||||
}
|
||||
|
||||
bool copyRawFrameSlots(AutoValueVector *vec) const;
|
||||
|
||||
|
@ -778,7 +778,7 @@ PrepareOsrTempData(JSContext *cx, ICUseCount_Fallback *stub, BaselineFrame *fram
|
||||
//
|
||||
|
||||
// Copy formal args and thisv.
|
||||
memcpy(stackFrameStart, frame->formals() - 1, (numFormalArgs + 1) * sizeof(Value));
|
||||
memcpy(stackFrameStart, frame->argv() - 1, (numFormalArgs + 1) * sizeof(Value));
|
||||
|
||||
// Initialize ScopeChain, Exec, and Flags fields in StackFrame struct.
|
||||
uint8_t *stackFrame = info->stackFrame;
|
||||
|
@ -89,34 +89,14 @@ EnterBaseline(JSContext *cx, StackFrame *fp, void *jitcode, bool osr)
|
||||
// arguments and the number of formal arguments. It accounts for |this|.
|
||||
int maxArgc = 0;
|
||||
Value *maxArgv = NULL;
|
||||
int numActualArgs = 0;
|
||||
unsigned numActualArgs = 0;
|
||||
RootedValue thisv(cx);
|
||||
|
||||
void *calleeToken;
|
||||
if (fp->isNonEvalFunctionFrame()) {
|
||||
// CountArgSlot include |this| and the |scopeChain|, and maybe |argumentsObj|
|
||||
// Want to keep including this, but remove the scopeChain and any argumentsObj.
|
||||
maxArgc = CountArgSlots(fp->script(), fp->fun()) - StartArgSlot(fp->script(), fp->fun());
|
||||
maxArgv = fp->formals() - 1; // -1 = include |this|
|
||||
|
||||
// Formal arguments are the argument corresponding to the function
|
||||
// definition and actual arguments are corresponding to the call-site
|
||||
// arguments.
|
||||
numActualArgs = fp->numActualArgs();
|
||||
|
||||
// We do not need to handle underflow because formal arguments are pad
|
||||
// with |undefined| values but we need to distinguish between the
|
||||
if (fp->hasOverflowArgs()) {
|
||||
int formalArgc = maxArgc;
|
||||
Value *formalArgv = maxArgv;
|
||||
maxArgc = numActualArgs + 1; // +1 = include |this|
|
||||
maxArgv = fp->actuals() - 1; // -1 = include |this|
|
||||
|
||||
// The beginning of the actual args is not updated, so we just copy
|
||||
// the formal args into the actual args to get a linear vector which
|
||||
// can be copied by generateEnterJit.
|
||||
memcpy(maxArgv, formalArgv, formalArgc * sizeof(Value));
|
||||
}
|
||||
maxArgc = Max(numActualArgs, fp->numFormalArgs()) + 1; // +1 = include |this|
|
||||
maxArgv = fp->argv() - 1; // -1 = include |this|
|
||||
calleeToken = CalleeToToken(&fp->callee());
|
||||
} else {
|
||||
// For eval function frames, set the callee token to the enclosing function.
|
||||
|
@ -1939,34 +1939,14 @@ EnterIon(JSContext *cx, StackFrame *fp, void *jitcode)
|
||||
// arguments and the number of formal arguments. It accounts for |this|.
|
||||
int maxArgc = 0;
|
||||
Value *maxArgv = NULL;
|
||||
int numActualArgs = 0;
|
||||
unsigned numActualArgs = 0;
|
||||
RootedValue thisv(cx);
|
||||
|
||||
void *calleeToken;
|
||||
if (fp->isFunctionFrame()) {
|
||||
// CountArgSlot include |this| and the |scopeChain| and maybe |argumentsObj|.
|
||||
// Keep |this|, but discard the others.
|
||||
maxArgc = CountArgSlots(fp->script(), fp->fun()) - StartArgSlot(fp->script(), fp->fun());
|
||||
maxArgv = fp->formals() - 1; // -1 = include |this|
|
||||
|
||||
// Formal arguments are the argument corresponding to the function
|
||||
// definition and actual arguments are corresponding to the call-site
|
||||
// arguments.
|
||||
numActualArgs = fp->numActualArgs();
|
||||
|
||||
// We do not need to handle underflow because formal arguments are pad
|
||||
// with |undefined| values but we need to distinguish between the
|
||||
if (fp->hasOverflowArgs()) {
|
||||
int formalArgc = maxArgc;
|
||||
Value *formalArgv = maxArgv;
|
||||
maxArgc = numActualArgs + 1; // +1 = include |this|
|
||||
maxArgv = fp->actuals() - 1; // -1 = include |this|
|
||||
|
||||
// The beginning of the actual args is not updated, so we just copy
|
||||
// the formal args into the actual args to get a linear vector which
|
||||
// can be copied by generateEnterJit.
|
||||
memcpy(maxArgv, formalArgv, formalArgc * sizeof(Value));
|
||||
}
|
||||
maxArgc = Max(numActualArgs, fp->numFormalArgs()) + 1; // +1 = include |this|
|
||||
maxArgv = fp->argv() - 1; // -1 = include |this|
|
||||
calleeToken = CalleeToToken(&fp->callee());
|
||||
} else {
|
||||
calleeToken = CalleeToToken(fp->script());
|
||||
|
@ -30,25 +30,13 @@ CopyStackFrameArguments(const AbstractFramePtr frame, HeapValue *dst, unsigned t
|
||||
{
|
||||
JS_ASSERT_IF(frame.isStackFrame(), !frame.asStackFrame()->runningInIon());
|
||||
|
||||
unsigned numActuals = frame.numActualArgs();
|
||||
unsigned numFormals = frame.callee()->nargs;
|
||||
JS_ASSERT(numActuals <= totalArgs);
|
||||
JS_ASSERT(numFormals <= totalArgs);
|
||||
JS_ASSERT(Max(numActuals, numFormals) == totalArgs);
|
||||
JS_ASSERT(Max(frame.numActualArgs(), frame.numFormalArgs()) == totalArgs);
|
||||
|
||||
/* Copy formal arguments. */
|
||||
Value *src = frame.formals();
|
||||
Value *end = src + numFormals;
|
||||
/* Copy arguments. */
|
||||
Value *src = frame.argv();
|
||||
Value *end = src + totalArgs;
|
||||
while (src != end)
|
||||
(dst++)->init(*src++);
|
||||
|
||||
/* Copy actual argument which are not contignous. */
|
||||
if (numFormals < numActuals) {
|
||||
src = frame.actuals() + numFormals;
|
||||
end = src + (numActuals - numFormals);
|
||||
while (src != end)
|
||||
(dst++)->init(*src++);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
|
@ -99,9 +99,7 @@ inline void
|
||||
StackFrame::initCallFrame(JSContext *cx, JSFunction &callee,
|
||||
JSScript *script, uint32_t nactual, StackFrame::Flags flagsArg)
|
||||
{
|
||||
JS_ASSERT((flagsArg & ~(CONSTRUCTING |
|
||||
OVERFLOW_ARGS |
|
||||
UNDERFLOW_ARGS)) == 0);
|
||||
JS_ASSERT((flagsArg & ~CONSTRUCTING) == 0);
|
||||
JS_ASSERT(callee.nonLazyScript() == script);
|
||||
|
||||
/* Initialize stack frame members. */
|
||||
@ -129,7 +127,7 @@ StackFrame::createRestParameter(JSContext *cx)
|
||||
JS_ASSERT(fun()->hasRest());
|
||||
unsigned nformal = fun()->nargs - 1, nactual = numActualArgs();
|
||||
unsigned nrest = (nactual > nformal) ? nactual - nformal : 0;
|
||||
return NewDenseCopiedArray(cx, nrest, actuals() + nformal, NULL);
|
||||
return NewDenseCopiedArray(cx, nrest, argv() + nformal, NULL);
|
||||
}
|
||||
|
||||
inline Value &
|
||||
@ -155,7 +153,7 @@ StackFrame::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing)
|
||||
JS_ASSERT(i < numFormalArgs());
|
||||
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
||||
JS_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
|
||||
return formals()[i];
|
||||
return argv()[i];
|
||||
}
|
||||
|
||||
inline Value &
|
||||
@ -164,7 +162,7 @@ StackFrame::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing)
|
||||
JS_ASSERT(i < numActualArgs());
|
||||
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
||||
JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
|
||||
return i < numFormalArgs() ? formals()[i] : actuals()[i];
|
||||
return argv()[i];
|
||||
}
|
||||
|
||||
template <class Op>
|
||||
@ -174,25 +172,9 @@ StackFrame::forEachUnaliasedActual(Op op)
|
||||
JS_ASSERT(!script()->funHasAnyAliasedFormal);
|
||||
JS_ASSERT(!script()->needsArgsObj());
|
||||
|
||||
unsigned nformal = numFormalArgs();
|
||||
unsigned nactual = numActualArgs();
|
||||
|
||||
const Value *formalsEnd = (const Value *)this;
|
||||
const Value *formals = formalsEnd - nformal;
|
||||
|
||||
if (nactual <= nformal) {
|
||||
const Value *actualsEnd = formals + nactual;
|
||||
for (const Value *p = formals; p < actualsEnd; ++p)
|
||||
op(*p);
|
||||
} else {
|
||||
for (const Value *p = formals; p < formalsEnd; ++p)
|
||||
op(*p);
|
||||
|
||||
const Value *actualsEnd = formals - 2;
|
||||
const Value *actuals = actualsEnd - nactual;
|
||||
for (const Value *p = actuals + nformal; p < actualsEnd; ++p)
|
||||
op(*p);
|
||||
}
|
||||
const Value *argsEnd = argv() + numActualArgs();
|
||||
for (const Value *p = argv(); p < argsEnd; ++p)
|
||||
op(*p);
|
||||
}
|
||||
|
||||
struct CopyTo
|
||||
@ -209,30 +191,6 @@ struct CopyToHeap
|
||||
void operator()(const Value &src) { dst->init(src); ++dst; }
|
||||
};
|
||||
|
||||
inline unsigned
|
||||
StackFrame::numFormalArgs() const
|
||||
{
|
||||
JS_ASSERT(hasArgs());
|
||||
return fun()->nargs;
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
StackFrame::numActualArgs() const
|
||||
{
|
||||
/*
|
||||
* u.nactual is always coherent, except for method JIT frames where the
|
||||
* callee does not access its arguments and the number of actual arguments
|
||||
* matches the number of formal arguments. The JIT requires that all frames
|
||||
* which do not have an arguments object and use their arguments have a
|
||||
* coherent u.nactual (even though the below code may not use it), as
|
||||
* JIT code may access the field directly.
|
||||
*/
|
||||
JS_ASSERT(hasArgs());
|
||||
if (JS_UNLIKELY(flags_ & (OVERFLOW_ARGS | UNDERFLOW_ARGS)))
|
||||
return u.nactual;
|
||||
return numFormalArgs();
|
||||
}
|
||||
|
||||
inline ArgumentsObject &
|
||||
StackFrame::argsObj() const
|
||||
{
|
||||
@ -315,31 +273,19 @@ ContextStack::getCallFrame(JSContext *cx, MaybeReportError report, const CallArg
|
||||
|
||||
unsigned nvals = VALUES_PER_STACK_FRAME + script->nslots;
|
||||
|
||||
/* Maintain layout invariant: &formals[0] == ((Value *)fp) - nformal. */
|
||||
|
||||
if (args.length() == nformal) {
|
||||
if (args.length() >= nformal) {
|
||||
if (!space().ensureSpace(cx, report, firstUnused, nvals))
|
||||
return NULL;
|
||||
return reinterpret_cast<StackFrame *>(firstUnused);
|
||||
}
|
||||
|
||||
if (args.length() < nformal) {
|
||||
*flags = StackFrame::Flags(*flags | StackFrame::UNDERFLOW_ARGS);
|
||||
unsigned nmissing = nformal - args.length();
|
||||
if (!space().ensureSpace(cx, report, firstUnused, nmissing + nvals))
|
||||
return NULL;
|
||||
SetValueRangeToUndefined(firstUnused, nmissing);
|
||||
return reinterpret_cast<StackFrame *>(firstUnused + nmissing);
|
||||
}
|
||||
|
||||
*flags = StackFrame::Flags(*flags | StackFrame::OVERFLOW_ARGS);
|
||||
unsigned ncopy = 2 + nformal;
|
||||
if (!space().ensureSpace(cx, report, firstUnused, ncopy + nvals))
|
||||
/* Pad any missing arguments with |undefined|. */
|
||||
JS_ASSERT(args.length() < nformal);
|
||||
unsigned nmissing = nformal - args.length();
|
||||
if (!space().ensureSpace(cx, report, firstUnused, nmissing + nvals))
|
||||
return NULL;
|
||||
Value *dst = firstUnused;
|
||||
Value *src = args.base();
|
||||
mozilla::PodCopy(dst, src, ncopy);
|
||||
return reinterpret_cast<StackFrame *>(firstUnused + ncopy);
|
||||
SetValueRangeToUndefined(firstUnused, nmissing);
|
||||
return reinterpret_cast<StackFrame *>(firstUnused + nmissing);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE bool
|
||||
@ -386,7 +332,7 @@ ContextStack::popInlineFrame(FrameRegs ®s)
|
||||
JS_ASSERT(®s == &seg_->regs());
|
||||
|
||||
StackFrame *fp = regs.fp();
|
||||
Value *newsp = fp->actuals() - 1;
|
||||
Value *newsp = fp->argv() - 1;
|
||||
JS_ASSERT(newsp >= fp->prev()->base());
|
||||
|
||||
newsp[-1] = fp->returnValue();
|
||||
@ -815,27 +761,17 @@ AbstractFramePtr::isStrictEvalFrame() const
|
||||
}
|
||||
|
||||
inline Value *
|
||||
AbstractFramePtr::formals() const
|
||||
AbstractFramePtr::argv() const
|
||||
{
|
||||
if (isStackFrame())
|
||||
return asStackFrame()->formals();
|
||||
return asStackFrame()->argv();
|
||||
#ifdef JS_ION
|
||||
return asBaselineFrame()->formals();
|
||||
#else
|
||||
JS_NOT_REACHED("Invalid frame");
|
||||
#endif
|
||||
}
|
||||
inline Value *
|
||||
AbstractFramePtr::actuals() const
|
||||
{
|
||||
if (isStackFrame())
|
||||
return asStackFrame()->actuals();
|
||||
#ifdef JS_ION
|
||||
return asBaselineFrame()->actuals();
|
||||
return asBaselineFrame()->argv();
|
||||
#else
|
||||
JS_NOT_REACHED("Invalid frame");
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
AbstractFramePtr::hasArgsObj() const
|
||||
{
|
||||
|
@ -222,7 +222,7 @@ StackFrame::copyRawFrameSlots(AutoValueVector *vec)
|
||||
{
|
||||
if (!vec->resize(numFormalArgs() + script()->nfixed))
|
||||
return false;
|
||||
PodCopy(vec->begin(), formals(), numFormalArgs());
|
||||
PodCopy(vec->begin(), argv(), numFormalArgs());
|
||||
PodCopy(vec->begin() + numFormalArgs(), slots(), script()->nfixed);
|
||||
return true;
|
||||
}
|
||||
|
@ -218,8 +218,7 @@ class AbstractFramePtr
|
||||
inline unsigned numActualArgs() const;
|
||||
inline unsigned numFormalArgs() const;
|
||||
|
||||
inline Value *formals() const;
|
||||
inline Value *actuals() const;
|
||||
inline Value *argv() const;
|
||||
|
||||
inline bool hasArgsObj() const;
|
||||
inline ArgumentsObject &argsObj() const;
|
||||
@ -293,33 +292,29 @@ class StackFrame
|
||||
YIELDING = 0x40, /* Interpret dispatched JSOP_YIELD */
|
||||
FINISHED_IN_INTERP = 0x80, /* set if frame finished in Interpret() */
|
||||
|
||||
/* Function arguments */
|
||||
OVERFLOW_ARGS = 0x100, /* numActualArgs > numFormalArgs */
|
||||
UNDERFLOW_ARGS = 0x200, /* numActualArgs < numFormalArgs */
|
||||
|
||||
/* Function prologue state */
|
||||
HAS_CALL_OBJ = 0x400, /* CallObject created for heavyweight fun */
|
||||
HAS_ARGS_OBJ = 0x800, /* ArgumentsObject created for needsArgsObj script */
|
||||
HAS_CALL_OBJ = 0x100, /* CallObject created for heavyweight fun */
|
||||
HAS_ARGS_OBJ = 0x200, /* ArgumentsObject created for needsArgsObj script */
|
||||
|
||||
/* Lazy frame initialization */
|
||||
HAS_HOOK_DATA = 0x1000, /* frame has hookData_ set */
|
||||
HAS_RVAL = 0x2000, /* frame has rval_ set */
|
||||
HAS_SCOPECHAIN = 0x4000, /* frame has scopeChain_ set */
|
||||
HAS_PREVPC = 0x8000, /* frame has prevpc_ and prevInline_ set */
|
||||
HAS_BLOCKCHAIN = 0x10000, /* frame has blockChain_ set */
|
||||
HAS_HOOK_DATA = 0x400, /* frame has hookData_ set */
|
||||
HAS_RVAL = 0x800, /* frame has rval_ set */
|
||||
HAS_SCOPECHAIN = 0x1000, /* frame has scopeChain_ set */
|
||||
HAS_PREVPC = 0x2000, /* frame has prevpc_ and prevInline_ set */
|
||||
HAS_BLOCKCHAIN = 0x4000, /* frame has blockChain_ set */
|
||||
|
||||
/* Debugger state */
|
||||
PREV_UP_TO_DATE = 0x20000, /* see DebugScopes::updateLiveScopes */
|
||||
PREV_UP_TO_DATE = 0x8000, /* see DebugScopes::updateLiveScopes */
|
||||
|
||||
/* Used in tracking calls and profiling (see vm/SPSProfiler.cpp) */
|
||||
HAS_PUSHED_SPS_FRAME = 0x40000, /* SPS was notified of enty */
|
||||
HAS_PUSHED_SPS_FRAME = 0x10000, /* SPS was notified of enty */
|
||||
|
||||
/* Ion frame state */
|
||||
RUNNING_IN_ION = 0x80000, /* frame is running in Ion */
|
||||
CALLING_INTO_ION = 0x100000, /* frame is calling into Ion */
|
||||
RUNNING_IN_ION = 0x20000, /* frame is running in Ion */
|
||||
CALLING_INTO_ION = 0x40000, /* frame is calling into Ion */
|
||||
|
||||
/* Miscellaneous state. */
|
||||
USE_NEW_TYPE = 0x200000 /* Use new type for constructed |this| object. */
|
||||
USE_NEW_TYPE = 0x80000 /* Use new type for constructed |this| object. */
|
||||
};
|
||||
|
||||
private:
|
||||
@ -362,9 +357,7 @@ class StackFrame
|
||||
public:
|
||||
Value *slots() const { return (Value *)(this + 1); }
|
||||
Value *base() const { return slots() + script()->nfixed; }
|
||||
Value *formals() const { return (Value *)this - fun()->nargs; }
|
||||
Value *actuals() const { return formals() - (flags_ & OVERFLOW_ARGS ? 2 + u.nactual : 0); }
|
||||
unsigned nactual() const { return u.nactual; }
|
||||
Value *argv() const { return (Value *)this - Max(numActualArgs(), numFormalArgs()); }
|
||||
|
||||
private:
|
||||
friend class FrameRegs;
|
||||
@ -514,15 +507,8 @@ class StackFrame
|
||||
*
|
||||
* Only non-eval function frames have arguments. The arguments pushed by
|
||||
* the caller are the 'actual' arguments. The declared arguments of the
|
||||
* callee are the 'formal' arguments. When the caller passes less or equal
|
||||
* actual arguments, the actual and formal arguments are the same array
|
||||
* (but with different extents). When the caller passes too many arguments,
|
||||
* the formal subset of the actual arguments is copied onto the top of the
|
||||
* stack. This allows the engine to maintain a jit-time constant offset of
|
||||
* arguments from the frame pointer. Since the formal subset of the actual
|
||||
* arguments is potentially on the stack twice, it is important for all
|
||||
* reads/writes to refer to the same canonical memory location. This is
|
||||
* abstracted by the unaliased{Formal,Actual} methods.
|
||||
* callee are the 'formal' arguments. When the caller passes less actual
|
||||
* arguments, missing formal arguments are padded with |undefined|.
|
||||
*
|
||||
* When a local/formal variable is "aliased" (accessed by nested closures,
|
||||
* dynamic scope operations, or 'arguments), the canonical location for
|
||||
@ -544,8 +530,8 @@ class StackFrame
|
||||
|
||||
bool copyRawFrameSlots(AutoValueVector *v);
|
||||
|
||||
inline unsigned numFormalArgs() const;
|
||||
inline unsigned numActualArgs() const;
|
||||
unsigned numFormalArgs() const { JS_ASSERT(hasArgs()); return fun()->nargs; }
|
||||
unsigned numActualArgs() const { JS_ASSERT(hasArgs()); return u.nactual; }
|
||||
|
||||
inline Value &canonicalActualArg(unsigned i) const;
|
||||
template <class Op>
|
||||
@ -714,18 +700,18 @@ class StackFrame
|
||||
JS_ASSERT(isFunctionFrame());
|
||||
if (isEvalFrame())
|
||||
return ((Value *)this)[-1];
|
||||
return formals()[-1];
|
||||
return argv()[-1];
|
||||
}
|
||||
|
||||
JSObject &constructorThis() const {
|
||||
JS_ASSERT(hasArgs());
|
||||
return formals()[-1].toObject();
|
||||
return argv()[-1].toObject();
|
||||
}
|
||||
|
||||
Value &thisValue() const {
|
||||
if (flags_ & (EVAL | GLOBAL))
|
||||
return ((Value *)this)[-1];
|
||||
return formals()[-1];
|
||||
return argv()[-1];
|
||||
}
|
||||
|
||||
/*
|
||||
@ -750,7 +736,7 @@ class StackFrame
|
||||
const Value &maybeCalleev() const {
|
||||
Value &calleev = flags_ & (EVAL | GLOBAL)
|
||||
? ((Value *)this)[-2]
|
||||
: formals()[-2];
|
||||
: argv()[-2];
|
||||
JS_ASSERT(calleev.isObjectOrNull());
|
||||
return calleev;
|
||||
}
|
||||
@ -759,11 +745,11 @@ class StackFrame
|
||||
JS_ASSERT(isFunctionFrame());
|
||||
if (isEvalFrame())
|
||||
return ((Value *)this)[-2];
|
||||
return formals()[-2];
|
||||
return argv()[-2];
|
||||
}
|
||||
|
||||
CallReceiver callReceiver() const {
|
||||
return CallReceiverFromArgv(formals());
|
||||
return CallReceiverFromArgv(argv());
|
||||
}
|
||||
|
||||
/*
|
||||
@ -858,7 +844,7 @@ class StackFrame
|
||||
|
||||
Value *generatorArgsSnapshotBegin() const {
|
||||
JS_ASSERT(isGeneratorFrame());
|
||||
return actuals() - 2;
|
||||
return argv() - 2;
|
||||
}
|
||||
|
||||
Value *generatorArgsSnapshotEnd() const {
|
||||
@ -955,10 +941,6 @@ class StackFrame
|
||||
flags_ |= PREV_UP_TO_DATE;
|
||||
}
|
||||
|
||||
bool hasOverflowArgs() const {
|
||||
return !!(flags_ & OVERFLOW_ARGS);
|
||||
}
|
||||
|
||||
bool isYielding() {
|
||||
return !!(flags_ & YIELDING);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user