mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound.
This commit is contained in:
commit
5bf5a8b84c
@ -95,32 +95,18 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter)
|
||||
if (iter.bailoutKind() == Bailout_ArgumentCheck) {
|
||||
// Temporary hack -- skip the (unused) scopeChain, because it could be
|
||||
// bogus (we can fail before the scope chain slot is set). Strip the
|
||||
// hasScopeChain flag. If a call object is needed, it will get handled later
|
||||
// by |ThunkToInterpreter| which call |EnsureHasScopeObjects|.
|
||||
// hasScopeChain flag and we'll check this later to run prologue().
|
||||
iter.skip();
|
||||
flags_ &= ~StackFrame::HAS_SCOPECHAIN;
|
||||
|
||||
// If the script binds arguments, then skip the snapshot slot reserved to hold
|
||||
// its value.
|
||||
if (script()->argumentsHasVarBinding())
|
||||
iter.skip();
|
||||
flags_ &= ~StackFrame::HAS_ARGS_OBJ;
|
||||
} else {
|
||||
Value scopeChain = iter.read();
|
||||
JS_ASSERT(scopeChain.isObject() || scopeChain.isUndefined());
|
||||
if (scopeChain.isObject()) {
|
||||
scopeChain_ = &scopeChain.toObject();
|
||||
Value v = iter.read();
|
||||
if (v.isObject()) {
|
||||
scopeChain_ = &v.toObject();
|
||||
flags_ |= StackFrame::HAS_SCOPECHAIN;
|
||||
if (isFunctionFrame() && fun()->isHeavyweight())
|
||||
flags_ |= StackFrame::HAS_CALL_OBJ;
|
||||
}
|
||||
|
||||
// The second slot will be an arguments object if the script needs one.
|
||||
if (script()->argumentsHasVarBinding()) {
|
||||
Value argsObj = iter.read();
|
||||
JS_ASSERT(argsObj.isObject() || argsObj.isUndefined());
|
||||
if (argsObj.isObject())
|
||||
initArgsObj(argsObj.toObject().asArguments());
|
||||
} else {
|
||||
JS_ASSERT(v.isUndefined());
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +125,7 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter)
|
||||
if (isConstructing())
|
||||
JS_ASSERT(!thisv.isPrimitive());
|
||||
|
||||
JS_ASSERT(iter.slots() >= CountArgSlots(script(), fun()));
|
||||
JS_ASSERT(iter.slots() >= CountArgSlots(fun()));
|
||||
IonSpew(IonSpew_Bailouts, " frame slots %u, nargs %u, nfixed %u",
|
||||
iter.slots(), fun()->nargs, script()->nfixed);
|
||||
|
||||
@ -148,7 +134,7 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter)
|
||||
formals()[i] = arg;
|
||||
}
|
||||
}
|
||||
exprStackSlots -= CountArgSlots(script(), maybeFun());
|
||||
exprStackSlots -= CountArgSlots(maybeFun());
|
||||
|
||||
for (uint32_t i = 0; i < script()->nfixed; i++) {
|
||||
Value slot = iter.read();
|
||||
@ -512,7 +498,7 @@ ion::ReflowTypeInfo(uint32_t bailoutResult)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize the decl env Object, call object, and any arguments obj of the current frame.
|
||||
// Initialize the decl env Object and the call object of the current frame.
|
||||
bool
|
||||
ion::EnsureHasScopeObjects(JSContext *cx, AbstractFramePtr fp)
|
||||
{
|
||||
@ -617,22 +603,20 @@ ion::ThunkToInterpreter(Value *vp)
|
||||
fp = iter.interpFrame();
|
||||
script = iter.script();
|
||||
if (script->needsArgsObj()) {
|
||||
ArgumentsObject *argsObj;
|
||||
if (fp->hasArgsObj()) {
|
||||
argsObj = &fp->argsObj();
|
||||
} else {
|
||||
argsObj = ArgumentsObject::createExpected(cx, fp);
|
||||
if (!argsObj) {
|
||||
resumeMode = JSINTERP_RETHROW;
|
||||
break;
|
||||
}
|
||||
// Currently IonMonkey does not compile if the script needs an
|
||||
// arguments object, so the frame should not have any argument
|
||||
// object yet.
|
||||
JS_ASSERT(!fp->hasArgsObj());
|
||||
ArgumentsObject *argsobj = ArgumentsObject::createExpected(cx, fp);
|
||||
if (!argsobj) {
|
||||
resumeMode = JSINTERP_RETHROW;
|
||||
break;
|
||||
}
|
||||
|
||||
// The arguments is a local binding and needsArgsObj does not
|
||||
// check if it is clobbered. Ensure that the local binding
|
||||
// restored during bailout before storing the arguments object
|
||||
// to the slot.
|
||||
SetFrameArgumentsObject(cx, fp, script, argsObj);
|
||||
SetFrameArgumentsObject(cx, fp, script, argsobj);
|
||||
}
|
||||
++iter;
|
||||
} while (fp != br->entryfp());
|
||||
|
@ -447,7 +447,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
bool invalidate, BaselineStackBuilder &builder,
|
||||
MutableHandleFunction nextCallee, jsbytecode **callPC)
|
||||
{
|
||||
uint32_t exprStackSlots = iter.slots() - (script->nfixed + CountArgSlots(script, fun));
|
||||
uint32_t exprStackSlots = iter.slots() - (script->nfixed + CountArgSlots(fun));
|
||||
|
||||
builder.resetFramePushed();
|
||||
|
||||
@ -508,25 +508,15 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
flags |= BaselineFrame::HAS_PUSHED_SPS_FRAME;
|
||||
}
|
||||
|
||||
// Initialize BaselineFrame's scopeChain and argsObj
|
||||
// Initialize BaselineFrame::scopeChain
|
||||
JSObject *scopeChain = NULL;
|
||||
ArgumentsObject *argsObj = NULL;
|
||||
BailoutKind bailoutKind = iter.bailoutKind();
|
||||
if (bailoutKind == Bailout_ArgumentCheck) {
|
||||
// Temporary hack -- skip the (unused) scopeChain, because it could be
|
||||
// bogus (we can fail before the scope chain slot is set). Strip the
|
||||
// hasScopeChain flag and this will be fixed up later in |FinishBailoutToBaseline|,
|
||||
// which calls |EnsureHasScopeObjects|.
|
||||
// hasScopeChain flag and we'll check this later to run prologue().
|
||||
IonSpew(IonSpew_BaselineBailouts, " Bailout_ArgumentCheck! (no valid scopeChain)");
|
||||
iter.skip();
|
||||
|
||||
// Scripts with |argumentsHasVarBinding| have an extra slot.
|
||||
if (script->argumentsHasVarBinding()) {
|
||||
IonSpew(IonSpew_BaselineBailouts,
|
||||
" Bailout_ArgumentCheck for script with argumentsHasVarBinding!"
|
||||
"Using empty arguments object");
|
||||
iter.skip();
|
||||
}
|
||||
} else {
|
||||
Value v = iter.read();
|
||||
if (v.isObject()) {
|
||||
@ -554,19 +544,9 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
scopeChain = &(script->global());
|
||||
}
|
||||
}
|
||||
|
||||
// If script maybe has an arguments object, the second slot will hold it.
|
||||
if (script->argumentsHasVarBinding()) {
|
||||
v = iter.read();
|
||||
JS_ASSERT(v.isObject() || v.isUndefined());
|
||||
if (v.isObject())
|
||||
argsObj = &v.toObject().asArguments();
|
||||
}
|
||||
}
|
||||
IonSpew(IonSpew_BaselineBailouts, " ScopeChain=%p", scopeChain);
|
||||
blFrame->setScopeChain(scopeChain);
|
||||
if (argsObj)
|
||||
blFrame->initArgsObjUnchecked(*argsObj);
|
||||
// Do not need to initialize scratchValue or returnValue fields in BaselineFrame.
|
||||
|
||||
// No flags are set.
|
||||
@ -586,7 +566,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
size_t thisvOffset = builder.framePushed() + IonJSFrameLayout::offsetOfThis();
|
||||
*builder.valuePointerAtStackOffset(thisvOffset) = thisv;
|
||||
|
||||
JS_ASSERT(iter.slots() >= CountArgSlots(script, fun));
|
||||
JS_ASSERT(iter.slots() >= CountArgSlots(fun));
|
||||
IonSpew(IonSpew_BaselineBailouts, " frame slots %u, nargs %u, nfixed %u",
|
||||
iter.slots(), fun->nargs, script->nfixed);
|
||||
|
||||
@ -1217,26 +1197,19 @@ ion::FinishBailoutToBaseline(BaselineBailoutInfo *bailoutInfo)
|
||||
|
||||
if (iter.isBaselineJS()) {
|
||||
BaselineFrame *frame = iter.baselineFrame();
|
||||
JS_ASSERT(!frame->hasArgsObj());
|
||||
|
||||
// If the frame doesn't even have a scope chain set yet, then it's resuming
|
||||
// into the the prologue before the scope chain is initialized. Any
|
||||
// necessary args object will also be initialized there.
|
||||
if (frame->scopeChain() && frame->script()->needsArgsObj()) {
|
||||
ArgumentsObject *argsObj;
|
||||
if (frame->hasArgsObj()) {
|
||||
argsObj = &frame->argsObj();
|
||||
} else {
|
||||
argsObj = ArgumentsObject::createExpected(cx, frame);
|
||||
if (!argsObj)
|
||||
return false;
|
||||
}
|
||||
if (frame->script()->needsArgsObj()) {
|
||||
ArgumentsObject *argsobj = ArgumentsObject::createExpected(cx, frame);
|
||||
if (!argsobj)
|
||||
return false;
|
||||
|
||||
// The arguments is a local binding and needsArgsObj does not
|
||||
// check if it is clobbered. Ensure that the local binding
|
||||
// restored during bailout before storing the arguments object
|
||||
// to the slot.
|
||||
RootedScript script(cx, frame->script());
|
||||
SetFrameArgumentsObject(cx, frame, script, argsObj);
|
||||
SetFrameArgumentsObject(cx, frame, script, argsobj);
|
||||
}
|
||||
|
||||
if (frameno == 0)
|
||||
|
@ -411,7 +411,7 @@ BaselineCompiler::emitUseCountIncrement()
|
||||
// Emit no use count increments or bailouts if Ion is not
|
||||
// enabled, or if the script will never be Ion-compileable
|
||||
|
||||
if (!ionCompileable_ && !ionOSRCompileable_)
|
||||
if (!ionCompileable_)
|
||||
return true;
|
||||
|
||||
Register scriptReg = R2.scratchReg();
|
||||
|
@ -251,13 +251,10 @@ class BaselineFrame
|
||||
bool heavyweightFunPrologue(JSContext *cx);
|
||||
bool initFunctionScopeObjects(JSContext *cx);
|
||||
|
||||
void initArgsObjUnchecked(ArgumentsObject &argsobj) {
|
||||
flags_ |= HAS_ARGS_OBJ;
|
||||
argsObj_ = &argsobj;
|
||||
}
|
||||
void initArgsObj(ArgumentsObject &argsobj) {
|
||||
JS_ASSERT(script()->needsArgsObj());
|
||||
initArgsObjUnchecked(argsobj);
|
||||
flags_ |= HAS_ARGS_OBJ;
|
||||
argsObj_ = &argsobj;
|
||||
}
|
||||
bool hasArgsObj() const {
|
||||
return flags_ & HAS_ARGS_OBJ;
|
||||
|
@ -94,9 +94,8 @@ EnterBaseline(JSContext *cx, StackFrame *fp, void *jitcode, bool osr)
|
||||
|
||||
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());
|
||||
// CountArgSlot include |this| and the |scopeChain|.
|
||||
maxArgc = CountArgSlots(fp->fun()) - 1; // -1 = discard |scopeChain|
|
||||
maxArgv = fp->formals() - 1; // -1 = include |this|
|
||||
|
||||
// Formal arguments are the argument corresponding to the function
|
||||
|
@ -1807,19 +1807,21 @@ CodeGenerator::generateArgumentsChecks()
|
||||
|
||||
CompileInfo &info = gen->info();
|
||||
|
||||
// Indexes need to be shifted by one, to skip the scope chain slot.
|
||||
JS_ASSERT(info.scopeChainSlot() == 0);
|
||||
static const uint32_t START_SLOT = 1;
|
||||
|
||||
Label miss;
|
||||
for (uint32_t i = info.startArgSlot(); i < info.endArgSlot(); i++) {
|
||||
for (uint32_t i = START_SLOT; i < CountArgSlots(info.fun()); i++) {
|
||||
// All initial parameters are guaranteed to be MParameters.
|
||||
MParameter *param = rp->getOperand(i)->toParameter();
|
||||
const types::TypeSet *types = param->typeSet();
|
||||
if (!types || types->unknown())
|
||||
continue;
|
||||
|
||||
// Calculate the offset on the stack of the argument.
|
||||
// (i - info.startArgSlot()) - Compute index of arg within arg vector.
|
||||
// ... * sizeof(Value) - Scale by value size.
|
||||
// ArgToStackOffset(...) - Compute displacement within arg vector.
|
||||
int32_t offset = ArgToStackOffset((i - info.startArgSlot()) * sizeof(Value));
|
||||
// Use ReturnReg as a scratch register here, since not all platforms
|
||||
// have an actual ScratchReg.
|
||||
int32_t offset = ArgToStackOffset((i - START_SLOT) * sizeof(Value));
|
||||
Label matched;
|
||||
masm.guardTypeSet(Address(StackPointer, offset), types, temp, &matched, &miss);
|
||||
masm.jump(&miss);
|
||||
@ -2848,66 +2850,6 @@ CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*NewIonArgumentsObjectFn)(JSContext *cx, IonJSFrameLayout *frame, HandleObject);
|
||||
static const VMFunction NewIonArgumentsObjectInfo =
|
||||
FunctionInfo<NewIonArgumentsObjectFn>((NewIonArgumentsObjectFn) ArgumentsObject::createForIon);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitCreateArgumentsObject(LCreateArgumentsObject *lir)
|
||||
{
|
||||
// This should be getting constructed in the first block only, and not any OSR entry blocks.
|
||||
JS_ASSERT(lir->mir()->block()->id() == 0);
|
||||
|
||||
const LAllocation *callObj = lir->getCallObject();
|
||||
Register temp = ToRegister(lir->getTemp(0));
|
||||
|
||||
masm.movePtr(StackPointer, temp);
|
||||
masm.addPtr(Imm32(frameSize()), temp);
|
||||
|
||||
pushArg(ToRegister(callObj));
|
||||
pushArg(temp);
|
||||
return callVM(NewIonArgumentsObjectInfo, lir);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitGetArgumentsObjectArg(LGetArgumentsObjectArg *lir)
|
||||
{
|
||||
Register temp = ToRegister(lir->getTemp(0));
|
||||
Register argsObj = ToRegister(lir->getArgsObject());
|
||||
ValueOperand out = ToOutValue(lir);
|
||||
|
||||
masm.loadPrivate(Address(argsObj, ArgumentsObject::getDataSlotOffset()), temp);
|
||||
Address argAddr(temp, ArgumentsData::offsetOfArgs() + lir->mir()->argno() * sizeof(Value));
|
||||
masm.loadValue(argAddr, out);
|
||||
#ifdef DEBUG
|
||||
Label success;
|
||||
masm.branchTestMagic(Assembler::NotEqual, out, &success);
|
||||
masm.breakpoint();
|
||||
masm.bind(&success);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitSetArgumentsObjectArg(LSetArgumentsObjectArg *lir)
|
||||
{
|
||||
Register temp = ToRegister(lir->getTemp(0));
|
||||
Register argsObj = ToRegister(lir->getArgsObject());
|
||||
ValueOperand value = ToValue(lir, LSetArgumentsObjectArg::ValueIndex);
|
||||
|
||||
masm.loadPrivate(Address(argsObj, ArgumentsObject::getDataSlotOffset()), temp);
|
||||
Address argAddr(temp, ArgumentsData::offsetOfArgs() + lir->mir()->argno() * sizeof(Value));
|
||||
emitPreBarrier(argAddr, MIRType_Value);
|
||||
#ifdef DEBUG
|
||||
Label success;
|
||||
masm.branchTestMagic(Assembler::NotEqual, argAddr, &success);
|
||||
masm.breakpoint();
|
||||
masm.bind(&success);
|
||||
#endif
|
||||
masm.storeValue(value, argAddr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitReturnFromCtor(LReturnFromCtor *lir)
|
||||
{
|
||||
|
@ -121,9 +121,6 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitCreateThis(LCreateThis *lir);
|
||||
bool visitCreateThisWithProto(LCreateThisWithProto *lir);
|
||||
bool visitCreateThisWithTemplate(LCreateThisWithTemplate *lir);
|
||||
bool visitCreateArgumentsObject(LCreateArgumentsObject *lir);
|
||||
bool visitGetArgumentsObjectArg(LGetArgumentsObjectArg *lir);
|
||||
bool visitSetArgumentsObjectArg(LSetArgumentsObjectArg *lir);
|
||||
bool visitReturnFromCtor(LReturnFromCtor *lir);
|
||||
bool visitArrayLength(LArrayLength *lir);
|
||||
bool visitTypedArrayLength(LTypedArrayLength *lir);
|
||||
|
@ -13,17 +13,9 @@ namespace js {
|
||||
namespace ion {
|
||||
|
||||
inline unsigned
|
||||
StartArgSlot(RawScript script, JSFunction *fun)
|
||||
CountArgSlots(JSFunction *fun)
|
||||
{
|
||||
// First slot is for scope chain.
|
||||
// Second one may be for arguments object.
|
||||
return 1 + (script->argumentsHasVarBinding() ? 1 : 0);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
CountArgSlots(RawScript script, JSFunction *fun)
|
||||
{
|
||||
return StartArgSlot(script, fun) + (fun ? fun->nargs + 1 : 0);
|
||||
return fun ? fun->nargs + 2 : 1; // +2 for |scopeChain| and |this|, or +1 for |scopeChain|
|
||||
}
|
||||
|
||||
enum ExecutionMode {
|
||||
@ -45,8 +37,7 @@ class CompileInfo
|
||||
executionMode_(executionMode)
|
||||
{
|
||||
JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
|
||||
nimplicit_ = StartArgSlot(script, fun) /* scope chain and argument obj */
|
||||
+ (fun ? 1 : 0); /* this */
|
||||
nimplicit_ = 1 /* scope chain */ + (fun ? 1 /* this */: 0);
|
||||
nargs_ = fun ? fun->nargs : 0;
|
||||
nlocals_ = script->nfixed;
|
||||
nstack_ = script->nslots - script->nfixed;
|
||||
@ -126,30 +117,17 @@ class CompileInfo
|
||||
JS_ASSERT(script());
|
||||
return 0;
|
||||
}
|
||||
uint32_t argsObjSlot() const {
|
||||
JS_ASSERT(hasArguments());
|
||||
return 1;
|
||||
}
|
||||
uint32_t thisSlot() const {
|
||||
JS_ASSERT(fun());
|
||||
return hasArguments() ? 2 : 1;
|
||||
return 1;
|
||||
}
|
||||
uint32_t firstActualArgSlot() const {
|
||||
uint32_t firstArgSlot() const {
|
||||
return nimplicit_;
|
||||
}
|
||||
uint32_t argSlotUnchecked(uint32_t i) const {
|
||||
// During initialization, some routines need to get at arg
|
||||
// slots regardless of how regular argument access is done.
|
||||
uint32_t argSlot(uint32_t i) const {
|
||||
JS_ASSERT(i < nargs_);
|
||||
return nimplicit_ + i;
|
||||
}
|
||||
uint32_t argSlot(uint32_t i) const {
|
||||
// This should only be accessed when compiling functions for
|
||||
// which argument accesses don't need to go through the
|
||||
// argument object.
|
||||
JS_ASSERT(!argsObjAliasesFormals());
|
||||
return argSlotUnchecked(i);
|
||||
}
|
||||
uint32_t firstLocalSlot() const {
|
||||
return nimplicit_ + nargs_;
|
||||
}
|
||||
@ -163,28 +141,9 @@ class CompileInfo
|
||||
return firstStackSlot() + i;
|
||||
}
|
||||
|
||||
uint32_t startArgSlot() const {
|
||||
JS_ASSERT(scopeChainSlot() == 0);
|
||||
return StartArgSlot(script(), fun());
|
||||
}
|
||||
uint32_t endArgSlot() const {
|
||||
JS_ASSERT(scopeChainSlot() == 0);
|
||||
return CountArgSlots(script(), fun());
|
||||
}
|
||||
|
||||
uint32_t totalSlots() const {
|
||||
return 2 + (hasArguments() ? 1 : 0) + nargs() + nlocals();
|
||||
}
|
||||
|
||||
bool hasArguments() const {
|
||||
bool hasArguments() {
|
||||
return script()->argumentsHasVarBinding();
|
||||
}
|
||||
bool needsArgsObj() const {
|
||||
return script()->needsArgsObj();
|
||||
}
|
||||
bool argsObjAliasesFormals() const {
|
||||
return script()->argsObjAliasesFormals();
|
||||
}
|
||||
|
||||
ExecutionMode executionMode() const {
|
||||
return executionMode_;
|
||||
|
@ -1448,11 +1448,11 @@ CheckFrame(AbstractFramePtr fp)
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckScript(RawScript script, bool osr)
|
||||
CheckScript(RawScript script)
|
||||
{
|
||||
if (osr && script->needsArgsObj()) {
|
||||
// OSR-ing into functions with arguments objects is not supported.
|
||||
IonSpew(IonSpew_Abort, "OSR script has argsobj");
|
||||
if (script->needsArgsObj()) {
|
||||
// Functions with arguments objects, are not supported yet.
|
||||
IonSpew(IonSpew_Abort, "script has argsobj");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1508,9 +1508,9 @@ SequentialCompileContext::checkScriptSize(JSContext *cx, RawScript script)
|
||||
}
|
||||
|
||||
bool
|
||||
CanIonCompileScript(JSContext *cx, HandleScript script, bool osr)
|
||||
CanIonCompileScript(JSContext *cx, HandleScript script)
|
||||
{
|
||||
if (!script->canIonCompile() || !CheckScript(script, osr))
|
||||
if (!script->canIonCompile() || !CheckScript(script))
|
||||
return false;
|
||||
|
||||
SequentialCompileContext compileContext;
|
||||
@ -1519,8 +1519,8 @@ CanIonCompileScript(JSContext *cx, HandleScript script, bool osr)
|
||||
|
||||
template <typename CompileContext>
|
||||
static MethodStatus
|
||||
Compile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc,
|
||||
bool constructing, CompileContext &compileContext)
|
||||
Compile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing,
|
||||
CompileContext &compileContext)
|
||||
{
|
||||
JS_ASSERT(ion::IsEnabled(cx));
|
||||
JS_ASSERT_IF(osrPc != NULL, (JSOp)*osrPc == JSOP_LOOPENTRY);
|
||||
@ -1540,7 +1540,7 @@ Compile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrP
|
||||
return Method_CantCompile;
|
||||
}
|
||||
|
||||
if (!CheckScript(script, bool(osrPc))) {
|
||||
if (!CheckScript(script)) {
|
||||
IonSpew(IonSpew_Abort, "Aborted compilation of %s:%d", script->filename(), script->lineno);
|
||||
return Method_CantCompile;
|
||||
}
|
||||
@ -1922,9 +1922,8 @@ EnterIon(JSContext *cx, StackFrame *fp, void *jitcode)
|
||||
if (fp->isFunctionFrame()) {
|
||||
fp->cleanupTornValues();
|
||||
|
||||
// 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());
|
||||
// CountArgSlot include |this| and the |scopeChain|.
|
||||
maxArgc = CountArgSlots(fp->fun()) - 1; // -1 = discard |scopeChain|
|
||||
maxArgv = fp->formals() - 1; // -1 = include |this|
|
||||
|
||||
// Formal arguments are the argument corresponding to the function
|
||||
|
@ -282,7 +282,7 @@ IonContext *GetIonContext();
|
||||
|
||||
bool SetIonContext(IonContext *ctx);
|
||||
|
||||
bool CanIonCompileScript(JSContext *cx, HandleScript script, bool osr);
|
||||
bool CanIonCompileScript(JSContext *cx, HandleScript script);
|
||||
|
||||
MethodStatus CanEnterAtBranch(JSContext *cx, JSScript *script,
|
||||
AbstractFramePtr fp, jsbytecode *pc, bool isConstructing);
|
||||
|
@ -196,20 +196,17 @@ IsPhiObservable(MPhi *phi, Observability observe)
|
||||
|
||||
// If the Phi is of the |this| value, it must always be observable.
|
||||
uint32_t slot = phi->slot();
|
||||
CompileInfo &info = phi->block()->info();
|
||||
if (info.fun() && slot == info.thisSlot())
|
||||
if (slot == 1)
|
||||
return true;
|
||||
|
||||
// If the Phi is one of the formal argument, and we are using an argument
|
||||
// object in the function. The phi might be observable after a bailout.
|
||||
// For inlined frames this is not needed, as they are captured in the inlineResumePoint.
|
||||
CompileInfo &info = phi->block()->info();
|
||||
if (info.fun() && info.hasArguments()) {
|
||||
uint32_t first = info.firstActualArgSlot();
|
||||
if (first <= slot && slot - first < info.nargs()) {
|
||||
// If arguments obj aliases formals, then no arguments slots should ever be phis.
|
||||
JS_ASSERT(!info.argsObjAliasesFormals());
|
||||
uint32_t first = info.firstArgSlot();
|
||||
if (first <= slot && slot - first < info.nargs())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -335,13 +335,6 @@ IonBuilder::build()
|
||||
current->initSlot(info().scopeChainSlot(), scope);
|
||||
}
|
||||
|
||||
// Initialize the arguments object slot to undefined if necessary.
|
||||
if (info().hasArguments()) {
|
||||
MInstruction *argsObj = MConstant::New(UndefinedValue());
|
||||
current->add(argsObj);
|
||||
current->initSlot(info().argsObjSlot(), argsObj);
|
||||
}
|
||||
|
||||
// Emit the start instruction, so we can begin real instructions.
|
||||
current->makeStart(MStart::New(MStart::StartType_Default));
|
||||
if (instrumentedProfiling())
|
||||
@ -355,9 +348,6 @@ IonBuilder::build()
|
||||
if (!initScopeChain())
|
||||
return false;
|
||||
|
||||
if (info().needsArgsObj() && !initArgumentsObject())
|
||||
return false;
|
||||
|
||||
// Guard against over-recursion.
|
||||
MCheckOverRecursed *check = new MCheckOverRecursed;
|
||||
current->add(check);
|
||||
@ -382,14 +372,13 @@ IonBuilder::build()
|
||||
// So we attach the initial resume point to each parameter, which the type
|
||||
// analysis explicitly checks (this is the same mechanism used for
|
||||
// effectful operations).
|
||||
for (uint32_t i = 0; i < info().endArgSlot(); i++) {
|
||||
for (uint32_t i = 0; i < CountArgSlots(info().fun()); i++) {
|
||||
MInstruction *ins = current->getEntrySlot(i)->toInstruction();
|
||||
if (ins->type() == MIRType_Value)
|
||||
ins->setResumePoint(current->entryResumePoint());
|
||||
}
|
||||
|
||||
// lazyArguments should never be accessed in |argsObjAliasesFormals| scripts.
|
||||
if (info().hasArguments() && !info().argsObjAliasesFormals()) {
|
||||
if (script()->argumentsHasVarBinding()) {
|
||||
lazyArguments_ = MConstant::New(MagicValue(JS_OPTIMIZED_ARGUMENTS));
|
||||
current->add(lazyArguments_);
|
||||
}
|
||||
@ -491,25 +480,15 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
|
||||
if (!inlinedArgumentTypes_.append(callInfo.argvType().begin(), callInfo.argvType().end()))
|
||||
return false;
|
||||
|
||||
// The Oracle ensures that the inlined script does not use the scope chain, or need
|
||||
// an arguments object.
|
||||
// The Oracle ensures that the inlined script does not use the scope chain.
|
||||
JS_ASSERT(!script()->analysis()->usesScopeChain());
|
||||
MInstruction *scope = MConstant::New(UndefinedValue());
|
||||
current->add(scope);
|
||||
current->initSlot(info().scopeChainSlot(), scope);
|
||||
if (info().hasArguments()) {
|
||||
MInstruction *argsObj = MConstant::New(UndefinedValue());
|
||||
current->add(argsObj);
|
||||
current->initSlot(info().argsObjSlot(), argsObj);
|
||||
}
|
||||
current->initSlot(info().thisSlot(), callInfo.thisArg());
|
||||
|
||||
IonSpew(IonSpew_Inlining, "Initializing %u arg slots", info().nargs());
|
||||
|
||||
// NB: Ion does not inline functions which |needsArgsObj|. So using argSlot()
|
||||
// instead of argSlotUnchecked() below is OK
|
||||
JS_ASSERT(!info().needsArgsObj());
|
||||
|
||||
// Initialize actually set arguments.
|
||||
uint32_t existing_args = Min<uint32_t>(callInfo.argc(), info().nargs());
|
||||
for (size_t i = 0; i < existing_args; ++i) {
|
||||
@ -536,8 +515,8 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
|
||||
IonSpew(IonSpew_Inlining, "Inline entry block MResumePoint %p, %u operands",
|
||||
(void *) current->entryResumePoint(), current->entryResumePoint()->numOperands());
|
||||
|
||||
// +2 for the scope chain and |this|, maybe another +1 for arguments object slot.
|
||||
JS_ASSERT(current->entryResumePoint()->numOperands() == info().totalSlots());
|
||||
// +2 for the scope chain and |this|.
|
||||
JS_ASSERT(current->entryResumePoint()->numOperands() == info().nargs() + info().nlocals() + 2);
|
||||
|
||||
if (script_->argumentsHasVarBinding()) {
|
||||
lazyArguments_ = MConstant::New(MagicValue(JS_OPTIMIZED_ARGUMENTS));
|
||||
@ -547,55 +526,6 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
|
||||
return traverseBytecode();
|
||||
}
|
||||
|
||||
void
|
||||
IonBuilder::rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex)
|
||||
{
|
||||
JS_ASSERT(param->isParameter() || param->isGetArgumentsObjectArg());
|
||||
|
||||
// Find the original (not cloned) type set for the MParameter, as we
|
||||
// will be adding constraints to it.
|
||||
types::StackTypeSet *types;
|
||||
if (argIndex == MParameter::THIS_SLOT)
|
||||
types = oracle->thisTypeSet(script());
|
||||
else
|
||||
types = oracle->parameterTypeSet(script(), argIndex);
|
||||
if (!types)
|
||||
return;
|
||||
|
||||
JSValueType definiteType = types->getKnownTypeTag();
|
||||
if (definiteType == JSVAL_TYPE_UNKNOWN)
|
||||
return;
|
||||
|
||||
MInstruction *actual = NULL;
|
||||
switch (definiteType) {
|
||||
case JSVAL_TYPE_UNDEFINED:
|
||||
param->setFoldedUnchecked();
|
||||
actual = MConstant::New(UndefinedValue());
|
||||
break;
|
||||
|
||||
case JSVAL_TYPE_NULL:
|
||||
param->setFoldedUnchecked();
|
||||
actual = MConstant::New(NullValue());
|
||||
break;
|
||||
|
||||
default:
|
||||
actual = MUnbox::New(param, MIRTypeFromValueType(definiteType), MUnbox::Infallible);
|
||||
break;
|
||||
}
|
||||
|
||||
// Careful! We leave the original MParameter in the entry resume point. The
|
||||
// arguments still need to be checked unless proven otherwise at the call
|
||||
// site, and these checks can bailout. We can end up:
|
||||
// v0 = Parameter(0)
|
||||
// v1 = Unbox(v0, INT32)
|
||||
// -- ResumePoint(v0)
|
||||
//
|
||||
// As usual, it would be invalid for v1 to be captured in the initial
|
||||
// resume point, rather than v0.
|
||||
current->add(actual);
|
||||
current->rewriteSlot(slotIdx, actual);
|
||||
}
|
||||
|
||||
// Apply Type Inference information to parameters early on, unboxing them if
|
||||
// they have a definitive type. The actual guards will be emitted by the code
|
||||
// generator, explicitly, as part of the function prologue.
|
||||
@ -603,13 +533,53 @@ void
|
||||
IonBuilder::rewriteParameters()
|
||||
{
|
||||
JS_ASSERT(info().scopeChainSlot() == 0);
|
||||
static const uint32_t START_SLOT = 1;
|
||||
|
||||
if (!info().fun())
|
||||
return;
|
||||
for (uint32_t i = START_SLOT; i < CountArgSlots(info().fun()); i++) {
|
||||
MParameter *param = current->getSlot(i)->toParameter();
|
||||
|
||||
for (uint32_t i = info().startArgSlot(); i < info().endArgSlot(); i++) {
|
||||
MDefinition *param = current->getSlot(i);
|
||||
rewriteParameter(i, param, param->toParameter()->index());
|
||||
// Find the original (not cloned) type set for the MParameter, as we
|
||||
// will be adding constraints to it.
|
||||
types::StackTypeSet *types;
|
||||
if (param->index() == MParameter::THIS_SLOT)
|
||||
types = oracle->thisTypeSet(script());
|
||||
else
|
||||
types = oracle->parameterTypeSet(script(), param->index());
|
||||
if (!types)
|
||||
continue;
|
||||
|
||||
JSValueType definiteType = types->getKnownTypeTag();
|
||||
if (definiteType == JSVAL_TYPE_UNKNOWN)
|
||||
continue;
|
||||
|
||||
MInstruction *actual = NULL;
|
||||
switch (definiteType) {
|
||||
case JSVAL_TYPE_UNDEFINED:
|
||||
param->setFoldedUnchecked();
|
||||
actual = MConstant::New(UndefinedValue());
|
||||
break;
|
||||
|
||||
case JSVAL_TYPE_NULL:
|
||||
param->setFoldedUnchecked();
|
||||
actual = MConstant::New(NullValue());
|
||||
break;
|
||||
|
||||
default:
|
||||
actual = MUnbox::New(param, MIRTypeFromValueType(definiteType), MUnbox::Infallible);
|
||||
break;
|
||||
}
|
||||
|
||||
// Careful! We leave the original MParameter in the entry resume point. The
|
||||
// arguments still need to be checked unless proven otherwise at the call
|
||||
// site, and these checks can bailout. We can end up:
|
||||
// v0 = Parameter(0)
|
||||
// v1 = Unbox(v0, INT32)
|
||||
// -- ResumePoint(v0)
|
||||
//
|
||||
// As usual, it would be invalid for v1 to be captured in the initial
|
||||
// resume point, rather than v0.
|
||||
current->add(actual);
|
||||
current->rewriteSlot(i, actual);
|
||||
}
|
||||
}
|
||||
|
||||
@ -627,7 +597,7 @@ IonBuilder::initParameters()
|
||||
for (uint32_t i = 0; i < info().nargs(); i++) {
|
||||
param = MParameter::New(i, cloneTypeSet(oracle->parameterTypeSet(script(), i)));
|
||||
current->add(param);
|
||||
current->initSlot(info().argSlotUnchecked(i), param);
|
||||
current->initSlot(info().argSlot(i), param);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -639,10 +609,8 @@ IonBuilder::initScopeChain()
|
||||
MInstruction *scope = NULL;
|
||||
|
||||
// If the script doesn't use the scopechain, then it's already initialized
|
||||
// from earlier. However, always make a scope chain when |needsArgsObj| is true
|
||||
// for the script, since arguments object construction requires the scope chain
|
||||
// to be passed in.
|
||||
if (!info().needsArgsObj() && !script()->analysis()->usesScopeChain())
|
||||
// from earlier.
|
||||
if (!script()->analysis()->usesScopeChain())
|
||||
return true;
|
||||
|
||||
// The scope chain is only tracked in scripts that have NAME opcodes which
|
||||
@ -680,18 +648,6 @@ IonBuilder::initScopeChain()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::initArgumentsObject()
|
||||
{
|
||||
IonSpew(IonSpew_MIR, "%s:%d - Emitting code to initialize arguments object! block=%p",
|
||||
script()->filename(), script()->lineno, current);
|
||||
JS_ASSERT(info().needsArgsObj());
|
||||
MCreateArgumentsObject *argsObj = MCreateArgumentsObject::New(current->scopeChain());
|
||||
current->add(argsObj);
|
||||
current->setArgumentsObject(argsObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We try to build a control-flow graph in the order that it would be built as
|
||||
// if traversing the AST. This leads to a nice ordering and lets us build SSA
|
||||
// in one pass, since the bytecode is structured.
|
||||
@ -945,14 +901,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||
|
||||
case JSOP_GETARG:
|
||||
case JSOP_CALLARG:
|
||||
if (info().argsObjAliasesFormals()) {
|
||||
MGetArgumentsObjectArg *getArg = MGetArgumentsObjectArg::New(current->argumentsObject(),
|
||||
GET_SLOTNO(pc));
|
||||
current->add(getArg);
|
||||
current->push(getArg);
|
||||
} else {
|
||||
current->pushArg(GET_SLOTNO(pc));
|
||||
}
|
||||
current->pushArg(GET_SLOTNO(pc));
|
||||
return true;
|
||||
|
||||
case JSOP_SETARG:
|
||||
@ -961,16 +910,9 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||
// to wrap the spilling action, we don't want the spilling to be
|
||||
// captured by the GETARG and by the resume point, only by
|
||||
// MGetArgument.
|
||||
if (info().argsObjAliasesFormals()) {
|
||||
current->add(MSetArgumentsObjectArg::New(current->argumentsObject(), GET_SLOTNO(pc),
|
||||
current->peek(-1)));
|
||||
} else {
|
||||
// TODO: if hasArguments() is true, and the script has a JSOP_SETARG, then
|
||||
// convert all arg accesses to go through the arguments object.
|
||||
if (info().hasArguments())
|
||||
return abort("NYI: arguments & setarg.");
|
||||
current->setArg(GET_SLOTNO(pc));
|
||||
}
|
||||
if (info().hasArguments())
|
||||
return abort("NYI: arguments & setarg.");
|
||||
current->setArg(GET_SLOTNO(pc));
|
||||
return true;
|
||||
|
||||
case JSOP_GETLOCAL:
|
||||
@ -4013,7 +3955,7 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
||||
for (AliasedFormalIter i(script()); i; i++) {
|
||||
unsigned slot = i.scopeSlot();
|
||||
unsigned formal = i.frameIndex();
|
||||
MDefinition *param = current->getSlot(info().argSlotUnchecked(formal));
|
||||
MDefinition *param = current->getSlot(info().argSlot(formal));
|
||||
if (slot >= templateObj->numFixedSlots())
|
||||
current->add(MStoreSlot::New(slots, slot - templateObj->numFixedSlots(), param));
|
||||
else
|
||||
@ -5045,15 +4987,6 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
|
||||
osrBlock->initSlot(slot, scopev);
|
||||
}
|
||||
|
||||
// Initialize arguments object. Ion will not allow OSR-ing into scripts
|
||||
// with |needsArgsObj| set, so this can be undefined.
|
||||
JS_ASSERT(!info().needsArgsObj());
|
||||
if (info().hasArguments()) {
|
||||
MInstruction *argsObj = MConstant::New(UndefinedValue());
|
||||
osrBlock->add(argsObj);
|
||||
osrBlock->initSlot(info().argsObjSlot(), argsObj);
|
||||
}
|
||||
|
||||
if (info().fun()) {
|
||||
// Initialize |this| parameter.
|
||||
uint32_t slot = info().thisSlot();
|
||||
@ -5065,8 +4998,6 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
|
||||
|
||||
// Initialize arguments.
|
||||
for (uint32_t i = 0; i < info().nargs(); i++) {
|
||||
// NB: Ion does not OSR into any function which |needsArgsObj|, so
|
||||
// using argSlot() here instead of argSlotUnchecked() is ok.
|
||||
uint32_t slot = info().argSlot(i);
|
||||
ptrdiff_t offset = StackFrame::offsetOfFormalArg(info().fun(), i);
|
||||
|
||||
@ -5087,8 +5018,8 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
|
||||
}
|
||||
|
||||
// Initialize stack.
|
||||
uint32_t numStackSlots = preheader->stackDepth() - info().firstStackSlot();
|
||||
for (uint32_t i = 0; i < numStackSlots; i++) {
|
||||
uint32_t numSlots = preheader->stackDepth() - CountArgSlots(info().fun()) - info().nlocals();
|
||||
for (uint32_t i = 0; i < numSlots; i++) {
|
||||
uint32_t slot = info().stackSlot(i);
|
||||
ptrdiff_t offset = StackFrame::offsetOfFixed(info().nlocals() + i);
|
||||
|
||||
@ -5119,26 +5050,19 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
|
||||
JS_ASSERT(info().scopeChainSlot() == 0);
|
||||
JS_ASSERT(osrBlock->scopeChain()->type() == MIRType_Object);
|
||||
|
||||
// When compiling functions which |hasArguments|, an extra slot is used to hold the
|
||||
// potential arguments object. In OSR-compiled functions this object is always undefined,
|
||||
// but the slot still exists.
|
||||
bool argsSlotAdj = info().hasArguments() ? 1 : 0;
|
||||
Vector<MIRType> slotTypes(cx);
|
||||
if (!slotTypes.growByUninitialized(osrBlock->stackDepth() - argsSlotAdj))
|
||||
if (!slotTypes.growByUninitialized(osrBlock->stackDepth()))
|
||||
return NULL;
|
||||
|
||||
// Fill slotTypes with the types of the predecessor block.
|
||||
for (uint32_t i = 0; i < osrBlock->stackDepth() - argsSlotAdj; i++)
|
||||
for (uint32_t i = 0; i < osrBlock->stackDepth(); i++)
|
||||
slotTypes[i] = MIRType_Value;
|
||||
|
||||
// Update slotTypes for slots that may have a different type at this join point.
|
||||
if (!oracle->getOsrTypes(loopEntry, slotTypes))
|
||||
return NULL;
|
||||
|
||||
// Skip 0 - no type checks on scopeChain slot.
|
||||
for (uint32_t i = 1; i < slotTypes.length(); i++) {
|
||||
uint32_t slotNo = i + argsSlotAdj;
|
||||
|
||||
for (uint32_t i = 1; i < osrBlock->stackDepth(); i++) {
|
||||
// Unbox the MOsrValue if it is known to be unboxable.
|
||||
switch (slotTypes[i]) {
|
||||
case MIRType_Boolean:
|
||||
@ -5147,12 +5071,12 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
|
||||
case MIRType_String:
|
||||
case MIRType_Object:
|
||||
{
|
||||
MDefinition *def = osrBlock->getSlot(slotNo);
|
||||
MDefinition *def = osrBlock->getSlot(i);
|
||||
JS_ASSERT(def->type() == MIRType_Value);
|
||||
|
||||
MInstruction *actual = MUnbox::New(def, slotTypes[i], MUnbox::Infallible);
|
||||
osrBlock->add(actual);
|
||||
osrBlock->rewriteSlot(slotNo, actual);
|
||||
osrBlock->rewriteSlot(i, actual);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -5160,7 +5084,7 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
|
||||
{
|
||||
MConstant *c = MConstant::New(NullValue());
|
||||
osrBlock->add(c);
|
||||
osrBlock->rewriteSlot(slotNo, c);
|
||||
osrBlock->rewriteSlot(i, c);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -5168,13 +5092,13 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
|
||||
{
|
||||
MConstant *c = MConstant::New(UndefinedValue());
|
||||
osrBlock->add(c);
|
||||
osrBlock->rewriteSlot(slotNo, c);
|
||||
osrBlock->rewriteSlot(i, c);
|
||||
break;
|
||||
}
|
||||
|
||||
case MIRType_Magic:
|
||||
JS_ASSERT(lazyArguments_);
|
||||
osrBlock->rewriteSlot(slotNo, lazyArguments_);
|
||||
osrBlock->rewriteSlot(i, lazyArguments_);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -6286,10 +6210,6 @@ IonBuilder::jsop_length_fastPath()
|
||||
bool
|
||||
IonBuilder::jsop_arguments()
|
||||
{
|
||||
if (info().needsArgsObj()) {
|
||||
current->push(current->argumentsObject());
|
||||
return true;
|
||||
}
|
||||
JS_ASSERT(lazyArguments_);
|
||||
current->push(lazyArguments_);
|
||||
return true;
|
||||
|
@ -273,10 +273,8 @@ class IonBuilder : public MIRGenerator
|
||||
bool maybeInsertResume();
|
||||
|
||||
bool initParameters();
|
||||
void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex);
|
||||
void rewriteParameters();
|
||||
bool initScopeChain();
|
||||
bool initArgumentsObject();
|
||||
bool pushConstant(const Value &v);
|
||||
|
||||
// Add a guard which ensure that the set of type which goes through this
|
||||
|
@ -18,8 +18,7 @@ namespace ion {
|
||||
template <class Op>
|
||||
inline void
|
||||
SnapshotIterator::readFrameArgs(Op &op, const Value *argv, Value *scopeChain, Value *thisv,
|
||||
unsigned start, unsigned formalEnd, unsigned iterEnd,
|
||||
RawScript script)
|
||||
unsigned start, unsigned formalEnd, unsigned iterEnd)
|
||||
{
|
||||
if (scopeChain)
|
||||
*scopeChain = read();
|
||||
@ -31,10 +30,6 @@ SnapshotIterator::readFrameArgs(Op &op, const Value *argv, Value *scopeChain, Va
|
||||
else
|
||||
skip();
|
||||
|
||||
// Skip slot for arguments object.
|
||||
if (script->argumentsHasVarBinding())
|
||||
skip();
|
||||
|
||||
unsigned i = 0;
|
||||
if (formalEnd < start)
|
||||
i = start;
|
||||
@ -108,28 +103,26 @@ InlineFrameIteratorMaybeGC<allowGC>::forEachCanonicalActualArg(
|
||||
// Get the non overflown arguments
|
||||
unsigned formal_end = (end < nformal) ? end : nformal;
|
||||
SnapshotIterator s(si_);
|
||||
s.readFrameArgs(op, NULL, NULL, NULL, start, nformal, formal_end, script());
|
||||
s.readFrameArgs(op, NULL, NULL, NULL, start, nformal, formal_end);
|
||||
|
||||
// The overflown arguments are not available in current frame.
|
||||
// They are the last pushed arguments in the parent frame of this inlined frame.
|
||||
InlineFrameIteratorMaybeGC it(cx, this);
|
||||
++it;
|
||||
unsigned argsObjAdj = it.script()->argumentsHasVarBinding() ? 1 : 0;
|
||||
SnapshotIterator parent_s(it.snapshotIterator());
|
||||
SnapshotIterator parent_s((++it).snapshotIterator());
|
||||
|
||||
// Skip over all slots untill we get to the last slots (= arguments slots of callee)
|
||||
// the +2 is for [this] and [scopechain], and maybe +1 for [argsObj]
|
||||
JS_ASSERT(parent_s.slots() >= nactual + 2 + argsObjAdj);
|
||||
unsigned skip = parent_s.slots() - nactual - 2 - argsObjAdj;
|
||||
// the +2 is for [this] and [scopechain]
|
||||
JS_ASSERT(parent_s.slots() >= nactual + 2);
|
||||
unsigned skip = parent_s.slots() - nactual - 2;
|
||||
for (unsigned j = 0; j < skip; j++)
|
||||
parent_s.skip();
|
||||
|
||||
// Get the overflown arguments
|
||||
parent_s.readFrameArgs(op, NULL, NULL, NULL, nformal, nactual, end, it.script());
|
||||
parent_s.readFrameArgs(op, NULL, NULL, NULL, nformal, nactual, end);
|
||||
} else {
|
||||
SnapshotIterator s(si_);
|
||||
Value *argv = frame_->actualArgs();
|
||||
s.readFrameArgs(op, argv, NULL, NULL, start, nformal, end, script());
|
||||
s.readFrameArgs(op, argv, NULL, NULL, start, nformal, end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,8 +269,7 @@ class SnapshotIterator : public SnapshotReader
|
||||
|
||||
template <class Op>
|
||||
inline void readFrameArgs(Op &op, const Value *argv, Value *scopeChain, Value *thisv,
|
||||
unsigned start, unsigned formalEnd, unsigned iterEnd,
|
||||
RawScript script);
|
||||
unsigned start, unsigned formalEnd, unsigned iterEnd);
|
||||
|
||||
Value maybeReadSlotByIndex(size_t index) {
|
||||
while (index--) {
|
||||
|
@ -304,7 +304,7 @@ CloseLiveIterator(JSContext *cx, const InlineFrameIterator &frame, uint32_t loca
|
||||
SnapshotIterator si = frame.snapshotIterator();
|
||||
|
||||
// Skip stack slots until we reach the iterator object.
|
||||
uint32_t base = CountArgSlots(frame.script(), frame.maybeCallee()) + frame.script()->nfixed;
|
||||
uint32_t base = CountArgSlots(frame.maybeCallee()) + frame.script()->nfixed;
|
||||
uint32_t skipSlots = base + localSlot - 1;
|
||||
|
||||
for (unsigned i = 0; i < skipSlots; i++)
|
||||
|
@ -710,71 +710,6 @@ class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 0>
|
||||
}
|
||||
};
|
||||
|
||||
// Allocate a new arguments object for the frame.
|
||||
class LCreateArgumentsObject : public LCallInstructionHelper<1, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(CreateArgumentsObject)
|
||||
|
||||
LCreateArgumentsObject(const LAllocation &callObj, const LDefinition &temp)
|
||||
{
|
||||
setOperand(0, callObj);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LAllocation *getCallObject() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MCreateArgumentsObject *mir() const {
|
||||
return mir_->toCreateArgumentsObject();
|
||||
}
|
||||
};
|
||||
|
||||
// Get argument from arguments object.
|
||||
class LGetArgumentsObjectArg : public LInstructionHelper<BOX_PIECES, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(GetArgumentsObjectArg)
|
||||
|
||||
LGetArgumentsObjectArg(const LAllocation &argsObj, const LDefinition &temp)
|
||||
{
|
||||
setOperand(0, argsObj);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LAllocation *getArgsObject() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MGetArgumentsObjectArg *mir() const {
|
||||
return mir_->toGetArgumentsObjectArg();
|
||||
}
|
||||
};
|
||||
|
||||
// Set argument on arguments object.
|
||||
class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SetArgumentsObjectArg)
|
||||
|
||||
LSetArgumentsObjectArg(const LAllocation &argsObj, const LDefinition &temp)
|
||||
{
|
||||
setOperand(0, argsObj);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LAllocation *getArgsObject() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MSetArgumentsObjectArg *mir() const {
|
||||
return mir_->toSetArgumentsObjectArg();
|
||||
}
|
||||
|
||||
static const size_t ValueIndex = 1;
|
||||
};
|
||||
|
||||
// If the Value is an Object, return unbox(Value).
|
||||
// Otherwise, return the other Object.
|
||||
class LReturnFromCtor : public LInstructionHelper<1, BOX_PIECES + 1, 0>
|
||||
|
@ -50,9 +50,6 @@
|
||||
_(CreateThis) \
|
||||
_(CreateThisWithProto) \
|
||||
_(CreateThisWithTemplate) \
|
||||
_(CreateArgumentsObject) \
|
||||
_(GetArgumentsObjectArg) \
|
||||
_(SetArgumentsObjectArg) \
|
||||
_(ReturnFromCtor) \
|
||||
_(BitNotI) \
|
||||
_(BitNotV) \
|
||||
|
@ -320,34 +320,6 @@ LIRGenerator::visitCreateThis(MCreateThis *ins)
|
||||
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitCreateArgumentsObject(MCreateArgumentsObject *ins)
|
||||
{
|
||||
// LAllocation callObj = useRegisterAtStart(ins->getCallObject());
|
||||
LAllocation callObj = useFixed(ins->getCallObject(), CallTempReg0);
|
||||
LCreateArgumentsObject *lir = new LCreateArgumentsObject(callObj, tempFixed(CallTempReg1));
|
||||
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitGetArgumentsObjectArg(MGetArgumentsObjectArg *ins)
|
||||
{
|
||||
LAllocation argsObj = useRegister(ins->getArgsObject());
|
||||
LGetArgumentsObjectArg *lir = new LGetArgumentsObjectArg(argsObj, temp());
|
||||
return defineBox(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitSetArgumentsObjectArg(MSetArgumentsObjectArg *ins)
|
||||
{
|
||||
LAllocation argsObj = useRegister(ins->getArgsObject());
|
||||
LSetArgumentsObjectArg *lir = new LSetArgumentsObjectArg(argsObj, temp());
|
||||
if (!useBox(lir, LSetArgumentsObjectArg::ValueIndex, ins->getValue()))
|
||||
return false;
|
||||
|
||||
return add(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitReturnFromCtor(MReturnFromCtor *ins)
|
||||
{
|
||||
|
@ -105,9 +105,6 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
bool visitCreateThisWithTemplate(MCreateThisWithTemplate *ins);
|
||||
bool visitCreateThisWithProto(MCreateThisWithProto *ins);
|
||||
bool visitCreateThis(MCreateThis *ins);
|
||||
bool visitCreateArgumentsObject(MCreateArgumentsObject *ins);
|
||||
bool visitGetArgumentsObjectArg(MGetArgumentsObjectArg *ins);
|
||||
bool visitSetArgumentsObjectArg(MSetArgumentsObjectArg *ins);
|
||||
bool visitReturnFromCtor(MReturnFromCtor *ins);
|
||||
bool visitCall(MCall *call);
|
||||
bool visitApplyArgs(MApplyArgs *apply);
|
||||
|
108
js/src/ion/MIR.h
108
js/src/ion/MIR.h
@ -2118,114 +2118,6 @@ class MCreateThis
|
||||
}
|
||||
};
|
||||
|
||||
// Eager initialization of arguments object.
|
||||
class MCreateArgumentsObject
|
||||
: public MUnaryInstruction,
|
||||
public ObjectPolicy<0>
|
||||
{
|
||||
MCreateArgumentsObject(MDefinition *callObj)
|
||||
: MUnaryInstruction(callObj)
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
setGuard();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(CreateArgumentsObject)
|
||||
static MCreateArgumentsObject *New(MDefinition *callObj) {
|
||||
return new MCreateArgumentsObject(callObj);
|
||||
}
|
||||
|
||||
MDefinition *getCallObject() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
class MGetArgumentsObjectArg
|
||||
: public MUnaryInstruction,
|
||||
public ObjectPolicy<0>
|
||||
{
|
||||
size_t argno_;
|
||||
|
||||
MGetArgumentsObjectArg(MDefinition *argsObject, size_t argno)
|
||||
: MUnaryInstruction(argsObject),
|
||||
argno_(argno)
|
||||
{
|
||||
setResultType(MIRType_Value);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(GetArgumentsObjectArg)
|
||||
static MGetArgumentsObjectArg *New(MDefinition *argsObj, size_t argno)
|
||||
{
|
||||
return new MGetArgumentsObjectArg(argsObj, argno);
|
||||
}
|
||||
|
||||
MDefinition *getArgsObject() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
size_t argno() const {
|
||||
return argno_;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::Any);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
class MSetArgumentsObjectArg
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >
|
||||
{
|
||||
size_t argno_;
|
||||
|
||||
MSetArgumentsObjectArg(MDefinition *argsObj, size_t argno, MDefinition *value)
|
||||
: MBinaryInstruction(argsObj, value),
|
||||
argno_(argno)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SetArgumentsObjectArg)
|
||||
static MSetArgumentsObjectArg *New(MDefinition *argsObj, size_t argno, MDefinition *value)
|
||||
{
|
||||
return new MSetArgumentsObjectArg(argsObj, argno, value);
|
||||
}
|
||||
|
||||
MDefinition *getArgsObject() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
size_t argno() const {
|
||||
return argno_;
|
||||
}
|
||||
|
||||
MDefinition *getValue() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::Any);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
// Given a MIRType_Value A and a MIRType_Object B:
|
||||
// If the Value may be safely unboxed to an Object, return Object(A).
|
||||
// Otherwise, return B.
|
||||
|
@ -352,8 +352,6 @@ MBasicBlock::linkOsrValues(MStart *start)
|
||||
MDefinition *def = slots_[i];
|
||||
if (i == info().scopeChainSlot())
|
||||
def->toOsrScopeChain()->setResumePoint(res);
|
||||
else if (info().hasArguments() && i == info().argsObjSlot())
|
||||
JS_ASSERT(def->isConstant() && def->toConstant()->value() == UndefinedValue());
|
||||
else
|
||||
def->toOsrValue()->setResumePoint(res);
|
||||
}
|
||||
@ -456,24 +454,12 @@ MBasicBlock::scopeChain()
|
||||
return getSlot(info().scopeChainSlot());
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
MBasicBlock::argumentsObject()
|
||||
{
|
||||
return getSlot(info().argsObjSlot());
|
||||
}
|
||||
|
||||
void
|
||||
MBasicBlock::setScopeChain(MDefinition *scopeObj)
|
||||
{
|
||||
setSlot(info().scopeChainSlot(), scopeObj);
|
||||
}
|
||||
|
||||
void
|
||||
MBasicBlock::setArgumentsObject(MDefinition *argsObj)
|
||||
{
|
||||
setSlot(info().argsObjSlot(), argsObj);
|
||||
}
|
||||
|
||||
void
|
||||
MBasicBlock::pick(int32_t depth)
|
||||
{
|
||||
|
@ -102,7 +102,6 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
MDefinition *peek(int32_t depth);
|
||||
|
||||
MDefinition *scopeChain();
|
||||
MDefinition *argumentsObject();
|
||||
|
||||
// Increase the number of slots available
|
||||
bool increaseSlots(size_t num);
|
||||
@ -138,7 +137,6 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
void pushLocal(uint32_t local);
|
||||
void pushSlot(uint32_t slot);
|
||||
void setScopeChain(MDefinition *ins);
|
||||
void setArgumentsObject(MDefinition *ins);
|
||||
|
||||
// Returns the top of the stack, then decrements the virtual stack pointer.
|
||||
MDefinition *pop();
|
||||
|
@ -33,9 +33,6 @@ namespace ion {
|
||||
_(CreateThis) \
|
||||
_(CreateThisWithProto) \
|
||||
_(CreateThisWithTemplate) \
|
||||
_(CreateArgumentsObject) \
|
||||
_(GetArgumentsObjectArg) \
|
||||
_(SetArgumentsObjectArg) \
|
||||
_(PrepareCall) \
|
||||
_(PassArg) \
|
||||
_(Call) \
|
||||
|
@ -130,9 +130,6 @@ class ParallelArrayVisitor : public MInstructionVisitor
|
||||
UNSAFE_OP(CreateThis)
|
||||
UNSAFE_OP(CreateThisWithTemplate)
|
||||
UNSAFE_OP(CreateThisWithProto)
|
||||
UNSAFE_OP(CreateArgumentsObject)
|
||||
UNSAFE_OP(GetArgumentsObjectArg)
|
||||
UNSAFE_OP(SetArgumentsObjectArg)
|
||||
SAFE_OP(PrepareCall)
|
||||
SAFE_OP(PassArg)
|
||||
CUSTOM_OP(Call)
|
||||
|
@ -298,16 +298,15 @@ SnapshotWriter::startSnapshot(uint32_t frameCount, BailoutKind kind, bool resume
|
||||
void
|
||||
SnapshotWriter::startFrame(JSFunction *fun, RawScript script, jsbytecode *pc, uint32_t exprStack)
|
||||
{
|
||||
JS_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS);
|
||||
JS_ASSERT(CountArgSlots(fun) < SNAPSHOT_MAX_NARGS);
|
||||
|
||||
uint32_t implicit = StartArgSlot(script, fun);
|
||||
uint32_t formalArgs = CountArgSlots(script, fun);
|
||||
uint32_t formalArgs = CountArgSlots(fun);
|
||||
|
||||
nslots_ = formalArgs + script->nfixed + exprStack;
|
||||
slotsWritten_ = 0;
|
||||
|
||||
IonSpew(IonSpew_Snapshots, "Starting frame; implicit %u, formals %u, fixed %u, exprs %u",
|
||||
implicit, formalArgs - implicit, script->nfixed, exprStack);
|
||||
IonSpew(IonSpew_Snapshots, "Starting frame; formals %u, fixed %u, exprs %u",
|
||||
formalArgs, script->nfixed, exprStack);
|
||||
|
||||
JS_ASSERT(script->code <= pc && pc <= script->code + script->length);
|
||||
|
||||
|
@ -15,8 +15,7 @@ BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, HandleScript scrip
|
||||
: cx(cx),
|
||||
script(cx, script),
|
||||
pc(script->code),
|
||||
ionCompileable_(ion::IsEnabled(cx) && CanIonCompileScript(cx, script, false)),
|
||||
ionOSRCompileable_(ion::IsEnabled(cx) && CanIonCompileScript(cx, script, true)),
|
||||
ionCompileable_(ion::IsEnabled(cx) && CanIonCompileScript(cx, script)),
|
||||
debugMode_(cx->compartment->debugMode()),
|
||||
frame(cx, script, masm),
|
||||
stubSpace_(),
|
||||
|
@ -25,7 +25,6 @@ class BaselineCompilerShared
|
||||
jsbytecode *pc;
|
||||
MacroAssembler masm;
|
||||
bool ionCompileable_;
|
||||
bool ionOSRCompileable_;
|
||||
bool debugMode_;
|
||||
|
||||
FrameInfo frame;
|
||||
|
@ -1,19 +0,0 @@
|
||||
// Make sure arguments object handlig deals well with aliasing of args.
|
||||
var arr = [];
|
||||
function f(x) {
|
||||
var args = arguments;
|
||||
arr.push(arguments);
|
||||
arguments[0] = 0;
|
||||
return {
|
||||
f: function () { return x; },
|
||||
g: function () { return args[0]; }
|
||||
};
|
||||
}
|
||||
|
||||
// Check that aliased arguments are correctly set to the callObject
|
||||
for (var i = 0; i < 2000; i++)
|
||||
assertEq(f(1).f(), 0);
|
||||
|
||||
// Check that aliased arguments are correctly read from the callObject
|
||||
for (var i = 0; i < 2000; i++)
|
||||
assertEq(f(1).g(), 0);
|
@ -18,8 +18,6 @@
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/ArgumentsObject-inl.h"
|
||||
|
||||
#include "ion/IonFrames.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
@ -47,8 +45,7 @@ CopyStackFrameArguments(const AbstractFramePtr frame, HeapValue *dst)
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ArgumentsObject::MaybeForwardToCallObject(AbstractFramePtr frame, JSObject *obj,
|
||||
ArgumentsData *data)
|
||||
ArgumentsObject::MaybeForwardToCallObject(AbstractFramePtr frame, JSObject *obj, ArgumentsData *data)
|
||||
{
|
||||
RawScript script = frame.script();
|
||||
if (frame.fun()->isHeavyweight() && script->argsObjAliasesFormals()) {
|
||||
@ -58,22 +55,6 @@ ArgumentsObject::MaybeForwardToCallObject(AbstractFramePtr frame, JSObject *obj,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(JS_ION)
|
||||
/* static */ void
|
||||
ArgumentsObject::MaybeForwardToCallObject(ion::IonJSFrameLayout *frame, HandleObject callObj,
|
||||
JSObject *obj, ArgumentsData *data)
|
||||
{
|
||||
RawFunction callee = ion::CalleeTokenToFunction(frame->calleeToken());
|
||||
RawScript script = callee->nonLazyScript();
|
||||
if (callee->isHeavyweight() && script->argsObjAliasesFormals()) {
|
||||
JS_ASSERT(callObj && callObj->isCall());
|
||||
obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(*callObj.get()));
|
||||
for (AliasedFormalIter fi(script); fi; fi++)
|
||||
data->args[fi.frameIndex()] = MagicValue(JS_FORWARD_TO_CALL_OBJECT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct CopyFrameArgs
|
||||
{
|
||||
AbstractFramePtr frame_;
|
||||
@ -95,36 +76,6 @@ struct CopyFrameArgs
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(JS_ION)
|
||||
struct CopyIonJSFrameArgs
|
||||
{
|
||||
ion::IonJSFrameLayout *frame_;
|
||||
HandleObject callObj_;
|
||||
|
||||
CopyIonJSFrameArgs(ion::IonJSFrameLayout *frame, HandleObject callObj)
|
||||
: frame_(frame), callObj_(callObj)
|
||||
{ }
|
||||
|
||||
void copyArgs(JSContext *, HeapValue *dst) const {
|
||||
unsigned numActuals = frame_->numActualArgs();
|
||||
|
||||
/* Copy all arguments. */
|
||||
Value *src = frame_->argv() + 1; /* +1 to skip this. */
|
||||
Value *end = src + numActuals;
|
||||
while (src != end)
|
||||
(dst++)->init(*src++);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a call object exists and the arguments object aliases formals, the
|
||||
* call object is the canonical location for formals.
|
||||
*/
|
||||
void maybeForwardToCallObject(JSObject *obj, ArgumentsData *data) {
|
||||
ArgumentsObject::MaybeForwardToCallObject(frame_, callObj_, obj, data);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct CopyStackIterArgs
|
||||
{
|
||||
StackIter &iter_;
|
||||
@ -257,20 +208,6 @@ ArgumentsObject::createUnexpected(JSContext *cx, AbstractFramePtr frame)
|
||||
return create(cx, script, callee, frame.numActualArgs(), copy);
|
||||
}
|
||||
|
||||
#if defined(JS_ION)
|
||||
ArgumentsObject *
|
||||
ArgumentsObject::createForIon(JSContext *cx, ion::IonJSFrameLayout *frame, HandleObject scopeChain)
|
||||
{
|
||||
ion::CalleeToken token = frame->calleeToken();
|
||||
JS_ASSERT(ion::CalleeTokenIsFunction(token));
|
||||
RootedScript script(cx, ion::ScriptFromCalleeToken(token));
|
||||
RootedFunction callee(cx, ion::CalleeTokenToFunction(token));
|
||||
RootedObject callObj(cx, scopeChain->isCall() ? scopeChain.get() : NULL);
|
||||
CopyIonJSFrameArgs copy(frame, callObj);
|
||||
return create(cx, script, callee, frame->numActualArgs(), copy);
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
args_delProperty(JSContext *cx, HandleObject obj, HandleId id, JSBool *succeeded)
|
||||
{
|
||||
|
@ -125,10 +125,6 @@ class ArgumentsObject : public JSObject
|
||||
*/
|
||||
static ArgumentsObject *createUnexpected(JSContext *cx, StackIter &iter);
|
||||
static ArgumentsObject *createUnexpected(JSContext *cx, AbstractFramePtr frame);
|
||||
#if defined(JS_ION)
|
||||
static ArgumentsObject *createForIon(JSContext *cx, ion::IonJSFrameLayout *frame,
|
||||
HandleObject scopeChain);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return the initial length of the arguments. This may differ from the
|
||||
@ -211,10 +207,6 @@ class ArgumentsObject : public JSObject
|
||||
}
|
||||
|
||||
static void MaybeForwardToCallObject(AbstractFramePtr frame, JSObject *obj, ArgumentsData *data);
|
||||
#if defined(JS_ION)
|
||||
static void MaybeForwardToCallObject(ion::IonJSFrameLayout *frame, HandleObject callObj,
|
||||
JSObject *obj, ArgumentsData *data);
|
||||
#endif
|
||||
};
|
||||
|
||||
class NormalArgumentsObject : public ArgumentsObject
|
||||
|
@ -1132,7 +1132,7 @@ ContextStack::pushBailoutArgs(JSContext *cx, const ion::IonBailoutIterator &it,
|
||||
CopyTo dst(iag->array());
|
||||
Value *src = it.actualArgs();
|
||||
Value thisv = iag->thisv();
|
||||
s.readFrameArgs(dst, src, NULL, &thisv, 0, fun->nargs, argc, it.script());
|
||||
s.readFrameArgs(dst, src, NULL, &thisv, 0, fun->nargs, argc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user