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
ca6f7896a8
commit
c24123088d
@ -132,7 +132,7 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter)
|
|||||||
|
|
||||||
if (isFunctionFrame()) {
|
if (isFunctionFrame()) {
|
||||||
Value thisv = iter.read();
|
Value thisv = iter.read();
|
||||||
formals()[-1] = thisv;
|
argv()[-1] = thisv;
|
||||||
|
|
||||||
// The new |this| must have already been constructed prior to an Ion
|
// The new |this| must have already been constructed prior to an Ion
|
||||||
// constructor running.
|
// constructor running.
|
||||||
@ -145,7 +145,7 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter)
|
|||||||
|
|
||||||
for (uint32_t i = 0; i < fun()->nargs; i++) {
|
for (uint32_t i = 0; i < fun()->nargs; i++) {
|
||||||
Value arg = iter.read();
|
Value arg = iter.read();
|
||||||
formals()[i] = arg;
|
argv()[i] = arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exprStackSlots -= CountArgSlots(script(), maybeFun());
|
exprStackSlots -= CountArgSlots(script(), maybeFun());
|
||||||
@ -197,7 +197,7 @@ PushInlinedFrame(JSContext *cx, StackFrame *callerFrame)
|
|||||||
JS_ASSERT(js_CodeSpec[*regs.pc].format & JOF_INVOKE);
|
JS_ASSERT(js_CodeSpec[*regs.pc].format & JOF_INVOKE);
|
||||||
int callerArgc = GET_ARGC(regs.pc);
|
int callerArgc = GET_ARGC(regs.pc);
|
||||||
if (JSOp(*regs.pc) == JSOP_FUNAPPLY)
|
if (JSOp(*regs.pc) == JSOP_FUNAPPLY)
|
||||||
callerArgc = callerFrame->nactual();
|
callerArgc = callerFrame->numActualArgs();
|
||||||
const Value &calleeVal = regs.sp[-callerArgc - 2];
|
const Value &calleeVal = regs.sp[-callerArgc - 2];
|
||||||
|
|
||||||
RootedFunction fun(cx, calleeVal.toObject().toFunction());
|
RootedFunction fun(cx, calleeVal.toObject().toFunction());
|
||||||
@ -219,7 +219,7 @@ PushInlinedFrame(JSContext *cx, StackFrame *callerFrame)
|
|||||||
JS_ASSERT(fp == regs.fp());
|
JS_ASSERT(fp == regs.fp());
|
||||||
JS_ASSERT(fp->prev() == callerFrame);
|
JS_ASSERT(fp->prev() == callerFrame);
|
||||||
|
|
||||||
fp->formals()[-2].setObject(*fun);
|
fp->argv()[-2].setObject(*fun);
|
||||||
|
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
@ -285,7 +285,7 @@ ConvertFrames(JSContext *cx, IonActivation *activation, IonBailoutIterator &it)
|
|||||||
|
|
||||||
JSFunction *callee = it.maybeCallee();
|
JSFunction *callee = it.maybeCallee();
|
||||||
if (callee)
|
if (callee)
|
||||||
fp->formals()[-2].setObject(*callee);
|
fp->argv()[-2].setObject(*callee);
|
||||||
|
|
||||||
if (it.isConstructing())
|
if (it.isConstructing())
|
||||||
fp->setConstructing();
|
fp->setConstructing();
|
||||||
|
@ -27,8 +27,7 @@ BaselineFrame::trace(JSTracer *trc)
|
|||||||
// Mark actual and formal args.
|
// Mark actual and formal args.
|
||||||
if (isNonEvalFunctionFrame()) {
|
if (isNonEvalFunctionFrame()) {
|
||||||
unsigned numArgs = js::Max(numActualArgs(), numFormalArgs());
|
unsigned numArgs = js::Max(numActualArgs(), numFormalArgs());
|
||||||
JS_ASSERT(actuals() == formals());
|
gc::MarkValueRootRange(trc, numArgs, argv(), "baseline-args");
|
||||||
gc::MarkValueRootRange(trc, numArgs, actuals(), "baseline-args");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark scope chain.
|
// Mark scope chain.
|
||||||
@ -62,7 +61,7 @@ BaselineFrame::copyRawFrameSlots(AutoValueVector *vec) const
|
|||||||
if (!vec->resize(nformals + nfixed))
|
if (!vec->resize(nformals + nfixed))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mozilla::PodCopy(vec->begin(), formals(), nformals);
|
mozilla::PodCopy(vec->begin(), argv(), nformals);
|
||||||
for (unsigned i = 0; i < nfixed; i++)
|
for (unsigned i = 0; i < nfixed; i++)
|
||||||
(*vec)[nformals + i] = *valueSlot(i);
|
(*vec)[nformals + i] = *valueSlot(i);
|
||||||
return true;
|
return true;
|
||||||
|
@ -154,14 +154,14 @@ class BaselineFrame
|
|||||||
JS_ASSERT(i < numFormalArgs());
|
JS_ASSERT(i < numFormalArgs());
|
||||||
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
||||||
JS_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
|
JS_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
|
||||||
return formals()[i];
|
return argv()[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Value &unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing) const {
|
Value &unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing) const {
|
||||||
JS_ASSERT(i < numActualArgs());
|
JS_ASSERT(i < numActualArgs());
|
||||||
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
||||||
JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
|
JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
|
||||||
return actuals()[i];
|
return argv()[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Value &unaliasedLocal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
|
Value &unaliasedLocal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
|
||||||
@ -184,14 +184,11 @@ class BaselineFrame
|
|||||||
BaselineFrame::Size() +
|
BaselineFrame::Size() +
|
||||||
offsetOfThis());
|
offsetOfThis());
|
||||||
}
|
}
|
||||||
Value *formals() const {
|
Value *argv() const {
|
||||||
return (Value *)(reinterpret_cast<const uint8_t *>(this) +
|
return (Value *)(reinterpret_cast<const uint8_t *>(this) +
|
||||||
BaselineFrame::Size() +
|
BaselineFrame::Size() +
|
||||||
offsetOfArg(0));
|
offsetOfArg(0));
|
||||||
}
|
}
|
||||||
Value *actuals() const {
|
|
||||||
return formals();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool copyRawFrameSlots(AutoValueVector *vec) const;
|
bool copyRawFrameSlots(AutoValueVector *vec) const;
|
||||||
|
|
||||||
|
@ -778,7 +778,7 @@ PrepareOsrTempData(JSContext *cx, ICUseCount_Fallback *stub, BaselineFrame *fram
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Copy formal args and thisv.
|
// 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.
|
// Initialize ScopeChain, Exec, and Flags fields in StackFrame struct.
|
||||||
uint8_t *stackFrame = info->stackFrame;
|
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|.
|
// arguments and the number of formal arguments. It accounts for |this|.
|
||||||
int maxArgc = 0;
|
int maxArgc = 0;
|
||||||
Value *maxArgv = NULL;
|
Value *maxArgv = NULL;
|
||||||
int numActualArgs = 0;
|
unsigned numActualArgs = 0;
|
||||||
RootedValue thisv(cx);
|
RootedValue thisv(cx);
|
||||||
|
|
||||||
void *calleeToken;
|
void *calleeToken;
|
||||||
if (fp->isNonEvalFunctionFrame()) {
|
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();
|
numActualArgs = fp->numActualArgs();
|
||||||
|
maxArgc = Max(numActualArgs, fp->numFormalArgs()) + 1; // +1 = include |this|
|
||||||
// We do not need to handle underflow because formal arguments are pad
|
maxArgv = fp->argv() - 1; // -1 = include |this|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
calleeToken = CalleeToToken(&fp->callee());
|
calleeToken = CalleeToToken(&fp->callee());
|
||||||
} else {
|
} else {
|
||||||
// For eval function frames, set the callee token to the enclosing function.
|
// 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|.
|
// arguments and the number of formal arguments. It accounts for |this|.
|
||||||
int maxArgc = 0;
|
int maxArgc = 0;
|
||||||
Value *maxArgv = NULL;
|
Value *maxArgv = NULL;
|
||||||
int numActualArgs = 0;
|
unsigned numActualArgs = 0;
|
||||||
RootedValue thisv(cx);
|
RootedValue thisv(cx);
|
||||||
|
|
||||||
void *calleeToken;
|
void *calleeToken;
|
||||||
if (fp->isFunctionFrame()) {
|
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();
|
numActualArgs = fp->numActualArgs();
|
||||||
|
maxArgc = Max(numActualArgs, fp->numFormalArgs()) + 1; // +1 = include |this|
|
||||||
// We do not need to handle underflow because formal arguments are pad
|
maxArgv = fp->argv() - 1; // -1 = include |this|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
calleeToken = CalleeToToken(&fp->callee());
|
calleeToken = CalleeToToken(&fp->callee());
|
||||||
} else {
|
} else {
|
||||||
calleeToken = CalleeToToken(fp->script());
|
calleeToken = CalleeToToken(fp->script());
|
||||||
|
@ -30,25 +30,13 @@ CopyStackFrameArguments(const AbstractFramePtr frame, HeapValue *dst, unsigned t
|
|||||||
{
|
{
|
||||||
JS_ASSERT_IF(frame.isStackFrame(), !frame.asStackFrame()->runningInIon());
|
JS_ASSERT_IF(frame.isStackFrame(), !frame.asStackFrame()->runningInIon());
|
||||||
|
|
||||||
unsigned numActuals = frame.numActualArgs();
|
JS_ASSERT(Max(frame.numActualArgs(), frame.numFormalArgs()) == totalArgs);
|
||||||
unsigned numFormals = frame.callee()->nargs;
|
|
||||||
JS_ASSERT(numActuals <= totalArgs);
|
|
||||||
JS_ASSERT(numFormals <= totalArgs);
|
|
||||||
JS_ASSERT(Max(numActuals, numFormals) == totalArgs);
|
|
||||||
|
|
||||||
/* Copy formal arguments. */
|
/* Copy arguments. */
|
||||||
Value *src = frame.formals();
|
Value *src = frame.argv();
|
||||||
Value *end = src + numFormals;
|
Value *end = src + totalArgs;
|
||||||
while (src != end)
|
while (src != end)
|
||||||
(dst++)->init(*src++);
|
(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
|
/* static */ void
|
||||||
|
@ -99,9 +99,7 @@ inline void
|
|||||||
StackFrame::initCallFrame(JSContext *cx, JSFunction &callee,
|
StackFrame::initCallFrame(JSContext *cx, JSFunction &callee,
|
||||||
JSScript *script, uint32_t nactual, StackFrame::Flags flagsArg)
|
JSScript *script, uint32_t nactual, StackFrame::Flags flagsArg)
|
||||||
{
|
{
|
||||||
JS_ASSERT((flagsArg & ~(CONSTRUCTING |
|
JS_ASSERT((flagsArg & ~CONSTRUCTING) == 0);
|
||||||
OVERFLOW_ARGS |
|
|
||||||
UNDERFLOW_ARGS)) == 0);
|
|
||||||
JS_ASSERT(callee.nonLazyScript() == script);
|
JS_ASSERT(callee.nonLazyScript() == script);
|
||||||
|
|
||||||
/* Initialize stack frame members. */
|
/* Initialize stack frame members. */
|
||||||
@ -129,7 +127,7 @@ StackFrame::createRestParameter(JSContext *cx)
|
|||||||
JS_ASSERT(fun()->hasRest());
|
JS_ASSERT(fun()->hasRest());
|
||||||
unsigned nformal = fun()->nargs - 1, nactual = numActualArgs();
|
unsigned nformal = fun()->nargs - 1, nactual = numActualArgs();
|
||||||
unsigned nrest = (nactual > nformal) ? nactual - nformal : 0;
|
unsigned nrest = (nactual > nformal) ? nactual - nformal : 0;
|
||||||
return NewDenseCopiedArray(cx, nrest, actuals() + nformal, NULL);
|
return NewDenseCopiedArray(cx, nrest, argv() + nformal, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value &
|
inline Value &
|
||||||
@ -155,7 +153,7 @@ StackFrame::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing)
|
|||||||
JS_ASSERT(i < numFormalArgs());
|
JS_ASSERT(i < numFormalArgs());
|
||||||
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
||||||
JS_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
|
JS_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
|
||||||
return formals()[i];
|
return argv()[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value &
|
inline Value &
|
||||||
@ -164,7 +162,7 @@ StackFrame::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing)
|
|||||||
JS_ASSERT(i < numActualArgs());
|
JS_ASSERT(i < numActualArgs());
|
||||||
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
|
||||||
JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
|
JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
|
||||||
return i < numFormalArgs() ? formals()[i] : actuals()[i];
|
return argv()[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Op>
|
template <class Op>
|
||||||
@ -174,25 +172,9 @@ StackFrame::forEachUnaliasedActual(Op op)
|
|||||||
JS_ASSERT(!script()->funHasAnyAliasedFormal);
|
JS_ASSERT(!script()->funHasAnyAliasedFormal);
|
||||||
JS_ASSERT(!script()->needsArgsObj());
|
JS_ASSERT(!script()->needsArgsObj());
|
||||||
|
|
||||||
unsigned nformal = numFormalArgs();
|
const Value *argsEnd = argv() + numActualArgs();
|
||||||
unsigned nactual = numActualArgs();
|
for (const Value *p = argv(); p < argsEnd; ++p)
|
||||||
|
op(*p);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CopyTo
|
struct CopyTo
|
||||||
@ -209,30 +191,6 @@ struct CopyToHeap
|
|||||||
void operator()(const Value &src) { dst->init(src); ++dst; }
|
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 &
|
inline ArgumentsObject &
|
||||||
StackFrame::argsObj() const
|
StackFrame::argsObj() const
|
||||||
{
|
{
|
||||||
@ -315,31 +273,19 @@ ContextStack::getCallFrame(JSContext *cx, MaybeReportError report, const CallArg
|
|||||||
|
|
||||||
unsigned nvals = VALUES_PER_STACK_FRAME + script->nslots;
|
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))
|
if (!space().ensureSpace(cx, report, firstUnused, nvals))
|
||||||
return NULL;
|
return NULL;
|
||||||
return reinterpret_cast<StackFrame *>(firstUnused);
|
return reinterpret_cast<StackFrame *>(firstUnused);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length() < nformal) {
|
/* Pad any missing arguments with |undefined|. */
|
||||||
*flags = StackFrame::Flags(*flags | StackFrame::UNDERFLOW_ARGS);
|
JS_ASSERT(args.length() < nformal);
|
||||||
unsigned nmissing = nformal - args.length();
|
unsigned nmissing = nformal - args.length();
|
||||||
if (!space().ensureSpace(cx, report, firstUnused, nmissing + nvals))
|
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))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
Value *dst = firstUnused;
|
SetValueRangeToUndefined(firstUnused, nmissing);
|
||||||
Value *src = args.base();
|
return reinterpret_cast<StackFrame *>(firstUnused + nmissing);
|
||||||
mozilla::PodCopy(dst, src, ncopy);
|
|
||||||
return reinterpret_cast<StackFrame *>(firstUnused + ncopy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ALWAYS_INLINE bool
|
JS_ALWAYS_INLINE bool
|
||||||
@ -386,7 +332,7 @@ ContextStack::popInlineFrame(FrameRegs ®s)
|
|||||||
JS_ASSERT(®s == &seg_->regs());
|
JS_ASSERT(®s == &seg_->regs());
|
||||||
|
|
||||||
StackFrame *fp = regs.fp();
|
StackFrame *fp = regs.fp();
|
||||||
Value *newsp = fp->actuals() - 1;
|
Value *newsp = fp->argv() - 1;
|
||||||
JS_ASSERT(newsp >= fp->prev()->base());
|
JS_ASSERT(newsp >= fp->prev()->base());
|
||||||
|
|
||||||
newsp[-1] = fp->returnValue();
|
newsp[-1] = fp->returnValue();
|
||||||
@ -815,27 +761,17 @@ AbstractFramePtr::isStrictEvalFrame() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline Value *
|
inline Value *
|
||||||
AbstractFramePtr::formals() const
|
AbstractFramePtr::argv() const
|
||||||
{
|
{
|
||||||
if (isStackFrame())
|
if (isStackFrame())
|
||||||
return asStackFrame()->formals();
|
return asStackFrame()->argv();
|
||||||
#ifdef JS_ION
|
#ifdef JS_ION
|
||||||
return asBaselineFrame()->formals();
|
return asBaselineFrame()->argv();
|
||||||
#else
|
|
||||||
JS_NOT_REACHED("Invalid frame");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
inline Value *
|
|
||||||
AbstractFramePtr::actuals() const
|
|
||||||
{
|
|
||||||
if (isStackFrame())
|
|
||||||
return asStackFrame()->actuals();
|
|
||||||
#ifdef JS_ION
|
|
||||||
return asBaselineFrame()->actuals();
|
|
||||||
#else
|
#else
|
||||||
JS_NOT_REACHED("Invalid frame");
|
JS_NOT_REACHED("Invalid frame");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
AbstractFramePtr::hasArgsObj() const
|
AbstractFramePtr::hasArgsObj() const
|
||||||
{
|
{
|
||||||
|
@ -222,7 +222,7 @@ StackFrame::copyRawFrameSlots(AutoValueVector *vec)
|
|||||||
{
|
{
|
||||||
if (!vec->resize(numFormalArgs() + script()->nfixed))
|
if (!vec->resize(numFormalArgs() + script()->nfixed))
|
||||||
return false;
|
return false;
|
||||||
PodCopy(vec->begin(), formals(), numFormalArgs());
|
PodCopy(vec->begin(), argv(), numFormalArgs());
|
||||||
PodCopy(vec->begin() + numFormalArgs(), slots(), script()->nfixed);
|
PodCopy(vec->begin() + numFormalArgs(), slots(), script()->nfixed);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -218,8 +218,7 @@ class AbstractFramePtr
|
|||||||
inline unsigned numActualArgs() const;
|
inline unsigned numActualArgs() const;
|
||||||
inline unsigned numFormalArgs() const;
|
inline unsigned numFormalArgs() const;
|
||||||
|
|
||||||
inline Value *formals() const;
|
inline Value *argv() const;
|
||||||
inline Value *actuals() const;
|
|
||||||
|
|
||||||
inline bool hasArgsObj() const;
|
inline bool hasArgsObj() const;
|
||||||
inline ArgumentsObject &argsObj() const;
|
inline ArgumentsObject &argsObj() const;
|
||||||
@ -293,33 +292,29 @@ class StackFrame
|
|||||||
YIELDING = 0x40, /* Interpret dispatched JSOP_YIELD */
|
YIELDING = 0x40, /* Interpret dispatched JSOP_YIELD */
|
||||||
FINISHED_IN_INTERP = 0x80, /* set if frame finished in Interpret() */
|
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 */
|
/* Function prologue state */
|
||||||
HAS_CALL_OBJ = 0x400, /* CallObject created for heavyweight fun */
|
HAS_CALL_OBJ = 0x100, /* CallObject created for heavyweight fun */
|
||||||
HAS_ARGS_OBJ = 0x800, /* ArgumentsObject created for needsArgsObj script */
|
HAS_ARGS_OBJ = 0x200, /* ArgumentsObject created for needsArgsObj script */
|
||||||
|
|
||||||
/* Lazy frame initialization */
|
/* Lazy frame initialization */
|
||||||
HAS_HOOK_DATA = 0x1000, /* frame has hookData_ set */
|
HAS_HOOK_DATA = 0x400, /* frame has hookData_ set */
|
||||||
HAS_RVAL = 0x2000, /* frame has rval_ set */
|
HAS_RVAL = 0x800, /* frame has rval_ set */
|
||||||
HAS_SCOPECHAIN = 0x4000, /* frame has scopeChain_ set */
|
HAS_SCOPECHAIN = 0x1000, /* frame has scopeChain_ set */
|
||||||
HAS_PREVPC = 0x8000, /* frame has prevpc_ and prevInline_ set */
|
HAS_PREVPC = 0x2000, /* frame has prevpc_ and prevInline_ set */
|
||||||
HAS_BLOCKCHAIN = 0x10000, /* frame has blockChain_ set */
|
HAS_BLOCKCHAIN = 0x4000, /* frame has blockChain_ set */
|
||||||
|
|
||||||
/* Debugger state */
|
/* 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) */
|
/* 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 */
|
/* Ion frame state */
|
||||||
RUNNING_IN_ION = 0x80000, /* frame is running in Ion */
|
RUNNING_IN_ION = 0x20000, /* frame is running in Ion */
|
||||||
CALLING_INTO_ION = 0x100000, /* frame is calling into Ion */
|
CALLING_INTO_ION = 0x40000, /* frame is calling into Ion */
|
||||||
|
|
||||||
/* Miscellaneous state. */
|
/* 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:
|
private:
|
||||||
@ -362,9 +357,7 @@ class StackFrame
|
|||||||
public:
|
public:
|
||||||
Value *slots() const { return (Value *)(this + 1); }
|
Value *slots() const { return (Value *)(this + 1); }
|
||||||
Value *base() const { return slots() + script()->nfixed; }
|
Value *base() const { return slots() + script()->nfixed; }
|
||||||
Value *formals() const { return (Value *)this - fun()->nargs; }
|
Value *argv() const { return (Value *)this - Max(numActualArgs(), numFormalArgs()); }
|
||||||
Value *actuals() const { return formals() - (flags_ & OVERFLOW_ARGS ? 2 + u.nactual : 0); }
|
|
||||||
unsigned nactual() const { return u.nactual; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class FrameRegs;
|
friend class FrameRegs;
|
||||||
@ -514,15 +507,8 @@ class StackFrame
|
|||||||
*
|
*
|
||||||
* Only non-eval function frames have arguments. The arguments pushed by
|
* Only non-eval function frames have arguments. The arguments pushed by
|
||||||
* the caller are the 'actual' arguments. The declared arguments of the
|
* the caller are the 'actual' arguments. The declared arguments of the
|
||||||
* callee are the 'formal' arguments. When the caller passes less or equal
|
* callee are the 'formal' arguments. When the caller passes less actual
|
||||||
* actual arguments, the actual and formal arguments are the same array
|
* arguments, missing formal arguments are padded with |undefined|.
|
||||||
* (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.
|
|
||||||
*
|
*
|
||||||
* When a local/formal variable is "aliased" (accessed by nested closures,
|
* When a local/formal variable is "aliased" (accessed by nested closures,
|
||||||
* dynamic scope operations, or 'arguments), the canonical location for
|
* dynamic scope operations, or 'arguments), the canonical location for
|
||||||
@ -544,8 +530,8 @@ class StackFrame
|
|||||||
|
|
||||||
bool copyRawFrameSlots(AutoValueVector *v);
|
bool copyRawFrameSlots(AutoValueVector *v);
|
||||||
|
|
||||||
inline unsigned numFormalArgs() const;
|
unsigned numFormalArgs() const { JS_ASSERT(hasArgs()); return fun()->nargs; }
|
||||||
inline unsigned numActualArgs() const;
|
unsigned numActualArgs() const { JS_ASSERT(hasArgs()); return u.nactual; }
|
||||||
|
|
||||||
inline Value &canonicalActualArg(unsigned i) const;
|
inline Value &canonicalActualArg(unsigned i) const;
|
||||||
template <class Op>
|
template <class Op>
|
||||||
@ -714,18 +700,18 @@ class StackFrame
|
|||||||
JS_ASSERT(isFunctionFrame());
|
JS_ASSERT(isFunctionFrame());
|
||||||
if (isEvalFrame())
|
if (isEvalFrame())
|
||||||
return ((Value *)this)[-1];
|
return ((Value *)this)[-1];
|
||||||
return formals()[-1];
|
return argv()[-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject &constructorThis() const {
|
JSObject &constructorThis() const {
|
||||||
JS_ASSERT(hasArgs());
|
JS_ASSERT(hasArgs());
|
||||||
return formals()[-1].toObject();
|
return argv()[-1].toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value &thisValue() const {
|
Value &thisValue() const {
|
||||||
if (flags_ & (EVAL | GLOBAL))
|
if (flags_ & (EVAL | GLOBAL))
|
||||||
return ((Value *)this)[-1];
|
return ((Value *)this)[-1];
|
||||||
return formals()[-1];
|
return argv()[-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -750,7 +736,7 @@ class StackFrame
|
|||||||
const Value &maybeCalleev() const {
|
const Value &maybeCalleev() const {
|
||||||
Value &calleev = flags_ & (EVAL | GLOBAL)
|
Value &calleev = flags_ & (EVAL | GLOBAL)
|
||||||
? ((Value *)this)[-2]
|
? ((Value *)this)[-2]
|
||||||
: formals()[-2];
|
: argv()[-2];
|
||||||
JS_ASSERT(calleev.isObjectOrNull());
|
JS_ASSERT(calleev.isObjectOrNull());
|
||||||
return calleev;
|
return calleev;
|
||||||
}
|
}
|
||||||
@ -759,11 +745,11 @@ class StackFrame
|
|||||||
JS_ASSERT(isFunctionFrame());
|
JS_ASSERT(isFunctionFrame());
|
||||||
if (isEvalFrame())
|
if (isEvalFrame())
|
||||||
return ((Value *)this)[-2];
|
return ((Value *)this)[-2];
|
||||||
return formals()[-2];
|
return argv()[-2];
|
||||||
}
|
}
|
||||||
|
|
||||||
CallReceiver callReceiver() const {
|
CallReceiver callReceiver() const {
|
||||||
return CallReceiverFromArgv(formals());
|
return CallReceiverFromArgv(argv());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -858,7 +844,7 @@ class StackFrame
|
|||||||
|
|
||||||
Value *generatorArgsSnapshotBegin() const {
|
Value *generatorArgsSnapshotBegin() const {
|
||||||
JS_ASSERT(isGeneratorFrame());
|
JS_ASSERT(isGeneratorFrame());
|
||||||
return actuals() - 2;
|
return argv() - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *generatorArgsSnapshotEnd() const {
|
Value *generatorArgsSnapshotEnd() const {
|
||||||
@ -955,10 +941,6 @@ class StackFrame
|
|||||||
flags_ |= PREV_UP_TO_DATE;
|
flags_ |= PREV_UP_TO_DATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasOverflowArgs() const {
|
|
||||||
return !!(flags_ & OVERFLOW_ARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isYielding() {
|
bool isYielding() {
|
||||||
return !!(flags_ & YIELDING);
|
return !!(flags_ & YIELDING);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user