Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2013-04-22 13:27:13 -04:00
commit 5bf5a8b84c
32 changed files with 149 additions and 714 deletions

View File

@ -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());

View File

@ -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)

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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_;

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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);
}
}

View File

@ -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--) {

View File

@ -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++)

View File

@ -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>

View File

@ -50,9 +50,6 @@
_(CreateThis) \
_(CreateThisWithProto) \
_(CreateThisWithTemplate) \
_(CreateArgumentsObject) \
_(GetArgumentsObjectArg) \
_(SetArgumentsObjectArg) \
_(ReturnFromCtor) \
_(BitNotI) \
_(BitNotV) \

View File

@ -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)
{

View File

@ -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);

View File

@ -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.

View File

@ -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)
{

View File

@ -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();

View File

@ -33,9 +33,6 @@ namespace ion {
_(CreateThis) \
_(CreateThisWithProto) \
_(CreateThisWithTemplate) \
_(CreateArgumentsObject) \
_(GetArgumentsObjectArg) \
_(SetArgumentsObjectArg) \
_(PrepareCall) \
_(PassArg) \
_(Call) \

View File

@ -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)

View File

@ -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);

View File

@ -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_(),

View File

@ -25,7 +25,6 @@ class BaselineCompilerShared
jsbytecode *pc;
MacroAssembler masm;
bool ionCompileable_;
bool ionOSRCompileable_;
bool debugMode_;
FrameInfo frame;

View File

@ -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);

View File

@ -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)
{

View File

@ -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

View File

@ -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;
}