Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 22 Apr 2013 13:27:13 -0400
changeset 129492 ce672182dedcaabb42bab7767e9269f8fe634665
parent 129491 dfe59fafcaf0d9352244900d86d63f11d640003f (current diff)
parent 129464 1150403342b2111f08f0604ce6ff61e3102a47e2 (diff)
child 129493 ed9d6cd6956578897907d283a9f23ac1405f3648
push idunknown
push userunknown
push dateunknown
milestone23.0a1
Merge m-c to inbound.
js/src/ion/BaselineBailouts.cpp
js/src/ion/BaselineJIT.cpp
js/src/ion/IonFrames.cpp
js/src/jit-test/tests/ion/arguments-objects.js
--- a/js/src/ion/Bailouts.cpp
+++ b/js/src/ion/Bailouts.cpp
@@ -90,42 +90,28 @@ StackFrame::initFromBailout(JSContext *c
     iter.spewBailingFrom();
 #endif
     IonSpew(IonSpew_Bailouts, " expr stack slots %u, is function frame %u",
             exprStackSlots, isFunctionFrame());
 
     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());
         }
     }
 
     // Assume that all new stack frames have had their entry flag set if
     // profiling has been turned on. This will be corrected if necessary
     // elsewhere.
     if (cx->runtime->spsProfiler.enabled())
         setPushedSPSFrame();
@@ -134,26 +120,26 @@ StackFrame::initFromBailout(JSContext *c
         Value thisv = iter.read();
         formals()[-1] = thisv;
 
         // The new |this| must have already been constructed prior to an Ion
         // constructor running.
         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);
 
         for (uint32_t i = 0; i < fun()->nargs; i++) {
             Value arg = iter.read();
             formals()[i] = arg;
         }
     }
-    exprStackSlots -= CountArgSlots(script(), maybeFun());
+    exprStackSlots -= CountArgSlots(maybeFun());
 
     for (uint32_t i = 0; i < script()->nfixed; i++) {
         Value slot = iter.read();
         slots()[i] = slot;
     }
 
     IonSpew(IonSpew_Bailouts, " pushing %u expression stack slots", exprStackSlots);
     FrameRegs &regs = cx->regs();
@@ -507,17 +493,17 @@ ion::ReflowTypeInfo(uint32_t bailoutResu
 
     // When a type barrier fails, the bad value is at the top of the stack.
     Value &result = cx->regs().sp[-1];
     types::TypeScript::Monitor(cx, script, pc, result);
 
     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)
 {
     if (fp.isFunctionFrame() &&
         fp.fun()->isHeavyweight() &&
         !fp.hasCallObj())
     {
         return fp.initFunctionScopeObjects(cx);
@@ -612,32 +598,30 @@ ion::ThunkToInterpreter(Value *vp)
     {
         ScriptFrameIter iter(cx);
         StackFrame *fp = NULL;
         Rooted<JSScript*> script(cx);
         do {
             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());
     }
 
     if (activation->entryfp() == br->entryfp()) {
         // If the bailout entry fp is the same as the activation entryfp, then
         // there are no scripted frames below us. In this case, just shortcut
--- a/js/src/ion/BaselineBailouts.cpp
+++ b/js/src/ion/BaselineBailouts.cpp
@@ -442,17 +442,17 @@ struct BaselineStackBuilder
 //                      +===============+
 //
 static bool
 InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
                 HandleFunction fun, HandleScript script, SnapshotIterator &iter,
                 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();
 
     // Build first baseline frame:
     // +===============+
     // | PrevFramePtr  |
     // +---------------+
     // |   Baseline    |
@@ -503,35 +503,25 @@ InitFromBailout(JSContext *cx, HandleScr
     // If SPS Profiler is enabled, mark the frame as having pushed an SPS entry.
     // This may be wrong for the last frame of ArgumentCheck bailout, but
     // that will be fixed later.
     if (cx->runtime->spsProfiler.enabled()) {
         IonSpew(IonSpew_BaselineBailouts, "      Setting SPS flag on frame!");
         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()) {
             scopeChain = &v.toObject();
             if (fun && fun->isHeavyweight())
                 flags |= BaselineFrame::HAS_CALL_OBJ;
         } else {
             JS_ASSERT(v.isUndefined());
@@ -549,29 +539,19 @@ InitFromBailout(JSContext *cx, HandleScr
                 // scripts). Also note that it's invalid to resume into the
                 // prologue in this case because the prologue expects the scope
                 // chain in R1 for eval and global scripts.
                 JS_ASSERT(!script->isForEval());
                 JS_ASSERT(script->compileAndGo);
                 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.
     blFrame->setFlags(flags);
 
     // Ion doesn't compile code with try/catch, so the block object will always be
     // null.
     blFrame->setBlockChainNull();
@@ -581,17 +561,17 @@ InitFromBailout(JSContext *cx, HandleScr
         // in the calling frame.
         Value thisv = iter.read();
         IonSpew(IonSpew_BaselineBailouts, "      Is function!");
         IonSpew(IonSpew_BaselineBailouts, "      thisv=%016llx", *((uint64_t *) &thisv));
 
         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);
 
         for (uint32_t i = 0; i < fun->nargs; i++) {
             Value arg = iter.read();
             IonSpew(IonSpew_BaselineBailouts, "      arg %d = %016llx",
                         (int) i, *((uint64_t *) &arg));
             size_t argOffset = builder.framePushed() + IonJSFrameLayout::offsetOfActualArg(i);
@@ -1212,36 +1192,29 @@ ion::FinishBailoutToBaseline(BaselineBai
     RootedScript outerScript(cx, NULL);
     IonFrameIterator iter(cx);
     uint32_t frameno = 0;
     while (frameno < numFrames) {
         JS_ASSERT(!iter.isOptimizedJS());
 
         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)
                 innerScript = frame->script();
 
             if (frameno == numFrames - 1)
                 outerScript = frame->script();
 
--- a/js/src/ion/BaselineCompiler.cpp
+++ b/js/src/ion/BaselineCompiler.cpp
@@ -406,17 +406,17 @@ BaselineCompiler::emitInterruptCheck()
 }
 
 bool
 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();
     Register countReg = R0.scratchReg();
     Address useCountAddr(scriptReg, JSScript::offsetOfUseCount());
 
     masm.movePtr(ImmGCPtr(script), scriptReg);
     masm.load32(useCountAddr, countReg);
--- a/js/src/ion/BaselineFrame.h
+++ b/js/src/ion/BaselineFrame.h
@@ -246,24 +246,21 @@ class BaselineFrame
 
     inline bool pushBlock(JSContext *cx, Handle<StaticBlockObject *> block);
     inline void popBlock(JSContext *cx);
 
     bool strictEvalPrologue(JSContext *cx);
     bool heavyweightFunPrologue(JSContext *cx);
     bool initFunctionScopeObjects(JSContext *cx);
 
-    void initArgsObjUnchecked(ArgumentsObject &argsobj) {
+    void initArgsObj(ArgumentsObject &argsobj) {
+        JS_ASSERT(script()->needsArgsObj());
         flags_ |= HAS_ARGS_OBJ;
         argsObj_ = &argsobj;
     }
-    void initArgsObj(ArgumentsObject &argsobj) {
-        JS_ASSERT(script()->needsArgsObj());
-        initArgsObjUnchecked(argsobj);
-    }
     bool hasArgsObj() const {
         return flags_ & HAS_ARGS_OBJ;
     }
     ArgumentsObject &argsObj() const {
         JS_ASSERT(hasArgsObj());
         JS_ASSERT(script()->needsArgsObj());
         return *argsObj_;
     }
--- a/js/src/ion/BaselineJIT.cpp
+++ b/js/src/ion/BaselineJIT.cpp
@@ -89,19 +89,18 @@ EnterBaseline(JSContext *cx, StackFrame 
     // arguments and the number of formal arguments. It accounts for |this|.
     int maxArgc = 0;
     Value *maxArgv = NULL;
     int numActualArgs = 0;
     RootedValue thisv(cx);
 
     void *calleeToken;
     if (fp->isNonEvalFunctionFrame()) {
-        // CountArgSlot include |this| and the |scopeChain|, and maybe |argumentsObj|
-        // Want to keep including this, but remove the scopeChain and any argumentsObj.
-        maxArgc = CountArgSlots(fp->script(), fp->fun()) - StartArgSlot(fp->script(), fp->fun());
+        // 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
         // definition and actual arguments are corresponding to the call-site
         // arguments.
         numActualArgs = fp->numActualArgs();
 
         // We do not need to handle underflow because formal arguments are pad
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -1802,29 +1802,31 @@ CodeGenerator::generateArgumentsChecks()
     // monomorphic call case will bypass this entire path.
     masm.reserveStack(frameSize());
 
     // No registers are allocated yet, so it's safe to grab anything.
     Register temp = GeneralRegisterSet(EntryTempMask).getAny();
 
     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);
         masm.bind(&matched);
     }
 
     if (miss.used() && !bailoutFrom(&miss, graph.entrySnapshot()))
         return false;
@@ -2843,76 +2845,16 @@ CodeGenerator::visitCreateThisWithTempla
 
     // Initialize based on the templateObject.
     masm.bind(ool->rejoin());
     masm.initGCThing(objReg, templateObject);
 
     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)
 {
     ValueOperand value = ToValue(lir, LReturnFromCtor::ValueIndex);
     Register obj = ToRegister(lir->getObject());
     Register output = ToRegister(lir->output());
 
     Label valueIsObject, end;
--- a/js/src/ion/CodeGenerator.h
+++ b/js/src/ion/CodeGenerator.h
@@ -116,19 +116,16 @@ class CodeGenerator : public CodeGenerat
     bool visitParNew(LParNew *lir);
     bool visitParNewDenseArray(LParNewDenseArray *lir);
     bool visitParBailout(LParBailout *lir);
     bool visitInitElem(LInitElem *lir);
     bool visitInitProp(LInitProp *lir);
     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);
     bool visitTypedArrayElements(LTypedArrayElements *lir);
     bool visitStringLength(LStringLength *lir);
     bool visitInitializedLength(LInitializedLength *lir);
     bool visitSetInitializedLength(LSetInitializedLength *lir);
     bool visitNotO(LNotO *ins);
--- a/js/src/ion/CompileInfo.h
+++ b/js/src/ion/CompileInfo.h
@@ -8,27 +8,19 @@
 #define jsion_compileinfo_h__
 
 #include "Registers.h"
 
 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 {
     // Normal JavaScript execution
     SequentialExecution = 0,
 
     // JavaScript code to be executed in parallel worker threads,
     // e.g. by ParallelArray
@@ -40,18 +32,17 @@ class CompileInfo
 {
   public:
     CompileInfo(RawScript script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
                 ExecutionMode executionMode)
       : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
         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;
         nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
     }
 
     CompileInfo(unsigned nlocals)
       : script_(NULL), fun_(NULL), osrPc_(NULL), constructing_(false)
@@ -121,75 +112,43 @@ class CompileInfo
     unsigned ninvoke() const {
         return nslots_ - nstack_;
     }
 
     uint32_t scopeChainSlot() const {
         JS_ASSERT(script());
         return 0;
     }
-    uint32_t argsObjSlot() const {
-        JS_ASSERT(hasArguments());
+    uint32_t thisSlot() const {
+        JS_ASSERT(fun());
         return 1;
     }
-    uint32_t thisSlot() const {
-        JS_ASSERT(fun());
-        return hasArguments() ? 2 : 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_;
     }
     uint32_t localSlot(uint32_t i) const {
         return firstLocalSlot() + i;
     }
     uint32_t firstStackSlot() const {
         return firstLocalSlot() + nlocals();
     }
     uint32_t stackSlot(uint32_t i) const {
         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_;
     }
 
     bool isParallelExecution() const {
         return executionMode_ == ParallelExecution;
     }
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -1443,21 +1443,21 @@ CheckFrame(AbstractFramePtr fp)
         IonSpew(IonSpew_Abort, "too many actual args");
         return false;
     }
 
     return true;
 }
 
 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;
     }
 
     if (!script->compileAndGo) {
         IonSpew(IonSpew_Abort, "not compile-and-go");
         return false;
     }
 
@@ -1503,29 +1503,29 @@ SequentialCompileContext::checkScriptSiz
         IonSpew(IonSpew_Abort, "Too many locals and arguments (%u)", numLocalsAndArgs);
         return Method_CantCompile;
     }
 
     return Method_Compiled;
 }
 
 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;
     return compileContext.checkScriptSize(cx, script) == Method_Compiled;
 }
 
 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);
 
     ExecutionMode executionMode = compileContext.executionMode();
 
     if (executionMode == SequentialExecution &&
         IsBaselineEnabled(cx) && !script->hasBaselineScript())
@@ -1535,17 +1535,17 @@ Compile(JSContext *cx, HandleScript scri
         return Method_Skipped;
     }
 
     if (cx->compartment->debugMode()) {
         IonSpew(IonSpew_Abort, "debugging");
         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;
     }
 
     MethodStatus status = compileContext.checkScriptSize(cx, script);
     if (status != Method_Compiled) {
         IonSpew(IonSpew_Abort, "Aborted compilation of %s:%d", script->filename(), script->lineno);
         return status;
@@ -1917,19 +1917,18 @@ EnterIon(JSContext *cx, StackFrame *fp, 
     Value *maxArgv = NULL;
     int numActualArgs = 0;
     RootedValue thisv(cx);
 
     void *calleeToken;
     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
         // definition and actual arguments are corresponding to the call-site
         // arguments.
         numActualArgs = fp->numActualArgs();
 
         // We do not need to handle underflow because formal arguments are pad
--- a/js/src/ion/Ion.h
+++ b/js/src/ion/Ion.h
@@ -277,17 +277,17 @@ extern IonOptions js_IonOptions;
 // Initialize Ion statically for all JSRuntimes.
 bool InitializeIon();
 
 // Get and set the current Ion context.
 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);
 MethodStatus CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConstructing);
 MethodStatus CompileFunctionForBaseline(JSContext *cx, HandleScript script, AbstractFramePtr fp,
                                         bool isConstructing);
 MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs);
 
--- a/js/src/ion/IonAnalysis.cpp
+++ b/js/src/ion/IonAnalysis.cpp
@@ -191,30 +191,27 @@ IsPhiObservable(MPhi *phi, Observability
                 !iter->consumer()->toDefinition()->isPhi())
                 return true;
         }
         break;
     }
 
     // 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;
 }
 
 // Handles cases like:
 //    x is phi(a, x) --> a
 //    x is phi(a, a) --> a
 inline MDefinition *
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -330,39 +330,29 @@ IonBuilder::build()
     // instruction, which means generating any code that could load into
     // registers is illegal.
     {
         MInstruction *scope = MConstant::New(UndefinedValue());
         current->add(scope);
         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())
         current->add(MFunctionBoundary::New(script(), MFunctionBoundary::Enter));
 
     // Parameters have been checked to correspond to the typeset, now we unbox
     // what we can in an infallible manner.
     rewriteParameters();
 
     // It's safe to start emitting actual IR, so now build the scope chain.
     if (!initScopeChain())
         return false;
 
-    if (info().needsArgsObj() && !initArgumentsObject())
-        return false;
-
     // Guard against over-recursion.
     MCheckOverRecursed *check = new MCheckOverRecursed;
     current->add(check);
     check->setResumePoint(current->entryResumePoint());
 
     // Prevent |this| from being DCE'd: necessary for constructors.
     if (info().fun())
         current->getSlot(info().thisSlot())->setGuard();
@@ -377,24 +367,23 @@ IonBuilder::build()
     //       v1 = MParameter(1)
     //       --   ResumePoint(v2, v3)
     //       v2 = Unbox(v0, INT32)
     //       v3 = Unbox(v1, INT32)
     //
     // 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_);
     }
 
     if (!traverseBytecode())
         return false;
 
     if (!processIterators())
@@ -486,35 +475,25 @@ IonBuilder::buildInline(IonBuilder *call
     // to shortcut operations on "arguments" in the inlined call.
     JS_ASSERT(inlinedArguments_.length() == 0);
     JS_ASSERT(inlinedArgumentTypes_.length() == 0);
     if (!inlinedArguments_.append(callInfo.argv().begin(), callInfo.argv().end()))
         return false;
     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) {
         MDefinition *arg = callInfo.getArg(i);
         current->initSlot(info().argSlot(i), arg);
     }
 
     // Pass Undefined for missing arguments
@@ -531,90 +510,81 @@ IonBuilder::buildInline(IonBuilder *call
         MConstant *undef = MConstant::New(UndefinedValue());
         current->add(undef);
         current->initSlot(info().localSlot(i), undef);
     }
 
     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));
         current->add(lazyArguments_);
     }
 
     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.
 void
 IonBuilder::rewriteParameters()
 {
     JS_ASSERT(info().scopeChainSlot() == 0);
-
-    if (!info().fun())
-        return;
-
-    for (uint32_t i = info().startArgSlot(); i < info().endArgSlot(); i++) {
-        MDefinition *param = current->getSlot(i);
-        rewriteParameter(i, param, param->toParameter()->index());
+    static const uint32_t START_SLOT = 1;
+
+    for (uint32_t i = START_SLOT; i < CountArgSlots(info().fun()); i++) {
+        MParameter *param = current->getSlot(i)->toParameter();
+
+        // 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);
     }
 }
 
 bool
 IonBuilder::initParameters()
 {
     if (!info().fun())
         return true;
@@ -622,32 +592,30 @@ IonBuilder::initParameters()
     MParameter *param = MParameter::New(MParameter::THIS_SLOT,
                                         cloneTypeSet(oracle->thisTypeSet(script())));
     current->add(param);
     current->initSlot(info().thisSlot(), param);
 
     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;
 }
 
 bool
 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
     // will try to access the scope. For other scripts, the scope instructions
     // will be held live by resume points and code will still be generated for
     // them, so just use a constant undefined value.
     if (!script()->compileAndGo)
         return abort("non-CNG global scripts are not supported");
@@ -675,28 +643,16 @@ IonBuilder::initScopeChain()
         scope = MConstant::New(ObjectValue(script()->global()));
         current->add(scope);
     }
 
     current->setScopeChain(scope);
     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.
 //
 // We traverse the bytecode iteratively, maintaining a current basic block.
 // Each basic block has a mapping of local slots to instructions, as well as a
 // stack depth. As we encounter instructions we mutate this mapping in the
 // current block.
@@ -940,42 +896,28 @@ IonBuilder::inspectOpcode(JSOp op)
       case JSOP_ARGUMENTS:
         return jsop_arguments();
 
       case JSOP_NOTEARG:
         return jsop_notearg();
 
       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:
         // To handle this case, we should spill the arguments to the space where
         // actual arguments are stored. The tricky part is that if we add a MIR
         // 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:
       case JSOP_CALLLOCAL:
         current->pushLocal(GET_SLOTNO(pc));
         return true;
 
       case JSOP_SETLOCAL:
@@ -4008,17 +3950,17 @@ IonBuilder::createCallObject(MDefinition
     // Initialize the object's reserved slots.
     current->add(MStoreFixedSlot::New(callObj, CallObject::enclosingScopeSlot(), scope));
     current->add(MStoreFixedSlot::New(callObj, CallObject::calleeSlot(), callee));
 
     // Initialize argument slots.
     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
             current->add(MStoreFixedSlot::New(callObj, slot, param));
     }
 
     return callObj;
 }
@@ -5040,38 +4982,27 @@ IonBuilder::newOsrPreheader(MBasicBlock 
     {
         uint32_t slot = info().scopeChainSlot();
 
         MOsrScopeChain *scopev = MOsrScopeChain::New(entry);
         osrBlock->add(scopev);
         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();
         ptrdiff_t offset = StackFrame::offsetOfThis(info().fun());
 
         MOsrValue *thisv = MOsrValue::New(entry, offset);
         osrBlock->add(thisv);
         osrBlock->initSlot(slot, thisv);
 
         // 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);
 
             MOsrValue *osrv = MOsrValue::New(entry, offset);
             osrBlock->add(osrv);
             osrBlock->initSlot(slot, osrv);
         }
     }
@@ -5082,18 +5013,18 @@ IonBuilder::newOsrPreheader(MBasicBlock 
         ptrdiff_t offset = StackFrame::offsetOfFixed(i);
 
         MOsrValue *osrv = MOsrValue::New(entry, offset);
         osrBlock->add(osrv);
         osrBlock->initSlot(slot, osrv);
     }
 
     // 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);
 
         MOsrValue *osrv = MOsrValue::New(entry, offset);
         osrBlock->add(osrv);
         osrBlock->initSlot(slot, osrv);
     }
 
@@ -5114,72 +5045,65 @@ IonBuilder::newOsrPreheader(MBasicBlock 
 
     // Clone types of the other predecessor of the pre-header to the osr block,
     // such as pre-header phi's won't discard specialized type of the
     // predecessor.
     JS_ASSERT(predecessor->stackDepth() == osrBlock->stackDepth());
     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:
           case MIRType_Int32:
           case MIRType_Double:
           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;
           }
 
           case MIRType_Null:
           {
             MConstant *c = MConstant::New(NullValue());
             osrBlock->add(c);
-            osrBlock->rewriteSlot(slotNo, c);
+            osrBlock->rewriteSlot(i, c);
             break;
           }
 
           case MIRType_Undefined:
           {
             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:
             break;
         }
     }
 
     // Finish the osrBlock.
@@ -6281,20 +6205,16 @@ IonBuilder::jsop_length_fastPath()
     }
 
     return false;
 }
 
 bool
 IonBuilder::jsop_arguments()
 {
-    if (info().needsArgsObj()) {
-        current->push(current->argumentsObject());
-        return true;
-    }
     JS_ASSERT(lazyArguments_);
     current->push(lazyArguments_);
     return true;
 }
 
 bool
 IonBuilder::jsop_arguments_length()
 {
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -268,20 +268,18 @@ class IonBuilder : public MIRGenerator
     // Please see the Big Honkin' Comment about how resume points work in
     // IonBuilder.cpp, near the definition for this function.
     bool resume(MInstruction *ins, jsbytecode *pc, MResumePoint::Mode mode);
     bool resumeAt(MInstruction *ins, jsbytecode *pc);
     bool resumeAfter(MInstruction *ins);
     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
     // generated code correspond to the observed or infered (actual) type.
     bool pushTypeBarrier(MInstruction *ins, types::StackTypeSet *actual, types::StackTypeSet *observed);
 
     // Add a guard which ensure that the set of type does not go through. Some
     // instructions, such as function calls, can have an excluded set of types
--- a/js/src/ion/IonFrameIterator-inl.h
+++ b/js/src/ion/IonFrameIterator-inl.h
@@ -13,33 +13,28 @@
 #include "ion/Ion.h"
 
 namespace js {
 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();
     else
         skip();
 
     if (thisv)
         *thisv = read();
     else
         skip();
 
-    // Skip slot for arguments object.
-    if (script->argumentsHasVarBinding())
-        skip();
-
     unsigned i = 0;
     if (formalEnd < start)
         i = start;
 
     for (; i < start; i++)
         skip();
     for (; i < formalEnd && i < iterEnd; i++) {
         // We are not always able to read values from the snapshots, some values
@@ -103,38 +98,36 @@ InlineFrameIteratorMaybeGC<allowGC>::for
         // The not overflown arguments are taken from the inlined frame,
         // because it will have the updated value when JSOP_SETARG is done.
         // All arguments (also the overflown) are the last pushed values in the parent frame.
         // To get the overflown arguments, we need to take them from there.
 
         // 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);
     }
 }
  
 template <AllowGC allowGC>
 inline JSObject *
 InlineFrameIteratorMaybeGC<allowGC>::scopeChain() const
 {
     SnapshotIterator s(si_);
--- a/js/src/ion/IonFrameIterator.h
+++ b/js/src/ion/IonFrameIterator.h
@@ -264,18 +264,17 @@ class SnapshotIterator : public Snapshot
             return slotValue(s);
         if (!silentFailure)
             warnUnreadableSlot();
         return UndefinedValue();
     }
 
     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--) {
             JS_ASSERT(moreSlots());
             skip();
         }
 
         Value s = maybeRead(true);
--- a/js/src/ion/IonFrames.cpp
+++ b/js/src/ion/IonFrames.cpp
@@ -299,17 +299,17 @@ IonFrameIterator::machineState() const
 }
 
 static void
 CloseLiveIterator(JSContext *cx, const InlineFrameIterator &frame, uint32_t localSlot)
 {
     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++)
         si.skip();
 
     Value v = si.read();
     RootedObject obj(cx, &v.toObject());
 
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -705,81 +705,16 @@ class LCreateThisWithTemplate : public L
     LCreateThisWithTemplate()
     { }
 
     MCreateThisWithTemplate *mir() const {
         return mir_->toCreateThisWithTemplate();
     }
 };
 
-// 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>
 {
   public:
     LIR_HEADER(ReturnFromCtor)
 
     LReturnFromCtor(const LAllocation &object)
--- a/js/src/ion/LOpcodes.h
+++ b/js/src/ion/LOpcodes.h
@@ -45,19 +45,16 @@
     _(GetDynamicName)               \
     _(FilterArguments)              \
     _(CallDirectEval)               \
     _(StackArgT)                    \
     _(StackArgV)                    \
     _(CreateThis)                   \
     _(CreateThisWithProto)          \
     _(CreateThisWithTemplate)       \
-    _(CreateArgumentsObject)        \
-    _(GetArgumentsObjectArg)        \
-    _(SetArgumentsObjectArg)        \
     _(ReturnFromCtor)               \
     _(BitNotI)                      \
     _(BitNotV)                      \
     _(BitOpI)                       \
     _(BitOpV)                       \
     _(ShiftI)                       \
     _(UrshD)                        \
     _(Return)                       \
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -316,44 +316,16 @@ LIRGenerator::visitCreateThisWithProto(M
 bool
 LIRGenerator::visitCreateThis(MCreateThis *ins)
 {
     LCreateThis *lir = new LCreateThis(useRegisterOrConstantAtStart(ins->getCallee()));
     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)
 {
     LReturnFromCtor *lir = new LReturnFromCtor(useRegister(ins->getObject()));
     if (!useBox(lir, LReturnFromCtor::ValueIndex, ins->getValue()))
         return false;
 
     return define(lir, ins);
 }
--- a/js/src/ion/Lowering.h
+++ b/js/src/ion/Lowering.h
@@ -100,19 +100,16 @@ class LIRGenerator : public LIRGenerator
     bool visitParCheckOverRecursed(MParCheckOverRecursed *ins);
     bool visitDefVar(MDefVar *ins);
     bool visitDefFun(MDefFun *ins);
     bool visitPrepareCall(MPrepareCall *ins);
     bool visitPassArg(MPassArg *arg);
     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);
     bool visitGetDynamicName(MGetDynamicName *ins);
     bool visitFilterArguments(MFilterArguments *ins);
     bool visitCallDirectEval(MCallDirectEval *ins);
     bool visitTest(MTest *test);
     bool visitFunctionDispatch(MFunctionDispatch *ins);
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -2113,124 +2113,16 @@ class MCreateThis
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     TypePolicy *typePolicy() {
         return this;
     }
 };
 
-// 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.
 // Used to implement return behavior for inlined constructors.
 class MReturnFromCtor
   : public MAryInstruction<2>,
     public MixPolicy<BoxPolicy<0>, ObjectPolicy<1> >
 {
--- a/js/src/ion/MIRGraph.cpp
+++ b/js/src/ion/MIRGraph.cpp
@@ -347,18 +347,16 @@ MBasicBlock::linkOsrValues(MStart *start
     JS_ASSERT(start->startType() == MStart::StartType_Osr);
 
     MResumePoint *res = start->resumePoint();
 
     for (uint32_t i = 0; i < stackDepth(); i++) {
         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);
     }
 }
 
 void
 MBasicBlock::setSlot(uint32_t slot, MDefinition *ins)
 {
@@ -451,35 +449,23 @@ MBasicBlock::popn(uint32_t n)
 }
 
 MDefinition *
 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)
 {
     // pick take an element and move it to the top.
     // pick(-2):
     //   A B C D E
     //   A B D C E [ swapAt(-2) ]
     //   A B D E C [ swapAt(-1) ]
     for (; depth < 0; depth++)
--- a/js/src/ion/MIRGraph.h
+++ b/js/src/ion/MIRGraph.h
@@ -97,17 +97,16 @@ class MBasicBlock : public TempObject, p
 
     // Exchange 2 stack slots at the defined depth
     void swapAt(int32_t depth);
 
     // Gets the instruction associated with various slot types.
     MDefinition *peek(int32_t depth);
 
     MDefinition *scopeChain();
-    MDefinition *argumentsObject();
 
     // Increase the number of slots available
     bool increaseSlots(size_t num);
 
     // Initializes a slot value; must not be called for normal stack
     // operations, as it will not create new SSA names for copies.
     void initSlot(uint32_t index, MDefinition *ins);
 
@@ -133,17 +132,16 @@ class MBasicBlock : public TempObject, p
     void rewriteAtDepth(int32_t depth, MDefinition *ins);
 
     // Tracks an instruction as being pushed onto the operand stack.
     void push(MDefinition *ins);
     void pushArg(uint32_t arg);
     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();
     void popn(uint32_t n);
 
     // Adds an instruction to this block's instruction list. |ins| may be NULL
     // to simplify OOM checking.
     void add(MInstruction *ins);
--- a/js/src/ion/MOpcodes.h
+++ b/js/src/ion/MOpcodes.h
@@ -28,19 +28,16 @@ namespace ion {
     _(OsrScopeChain)                                                        \
     _(ReturnFromCtor)                                                       \
     _(CheckOverRecursed)                                                    \
     _(DefVar)                                                               \
     _(DefFun)                                                               \
     _(CreateThis)                                                           \
     _(CreateThisWithProto)                                                  \
     _(CreateThisWithTemplate)                                               \
-    _(CreateArgumentsObject)                                                \
-    _(GetArgumentsObjectArg)                                                \
-    _(SetArgumentsObjectArg)                                                \
     _(PrepareCall)                                                          \
     _(PassArg)                                                              \
     _(Call)                                                                 \
     _(ApplyArgs)                                                            \
     _(GetDynamicName)                                                       \
     _(FilterArguments)                                                      \
     _(CallDirectEval)                                                       \
     _(BitNot)                                                               \
--- a/js/src/ion/ParallelArrayAnalysis.cpp
+++ b/js/src/ion/ParallelArrayAnalysis.cpp
@@ -125,19 +125,16 @@ class ParallelArrayVisitor : public MIns
     UNSAFE_OP(OsrScopeChain)
     UNSAFE_OP(ReturnFromCtor)
     CUSTOM_OP(CheckOverRecursed)
     UNSAFE_OP(DefVar)
     UNSAFE_OP(DefFun)
     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)
     UNSAFE_OP(ApplyArgs)
     UNSAFE_OP(GetDynamicName)
     UNSAFE_OP(FilterArguments)
     UNSAFE_OP(CallDirectEval)
     SAFE_OP(BitNot)
--- a/js/src/ion/Snapshots.cpp
+++ b/js/src/ion/Snapshots.cpp
@@ -293,26 +293,25 @@ SnapshotWriter::startSnapshot(uint32_t f
 
     writer_.writeUnsigned(bits);
     return lastStart_;
 }
 
 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);
 
     uint32_t pcoff = uint32_t(pc - script->code);
     IonSpew(IonSpew_Snapshots, "Writing pc offset %u, nslots %u", pcoff, nslots_);
     writer_.writeUnsigned(pcoff);
     writer_.writeUnsigned(nslots_);
 }
--- a/js/src/ion/shared/BaselineCompiler-shared.cpp
+++ b/js/src/ion/shared/BaselineCompiler-shared.cpp
@@ -10,18 +10,17 @@
 
 using namespace js;
 using namespace js::ion;
 
 BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, HandleScript script)
   : 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_(),
     icEntries_(),
     pcMappingEntries_(),
     icLoadLabels_(),
     pushedBeforeCall_(0),
     inCall_(false),
--- a/js/src/ion/shared/BaselineCompiler-shared.h
+++ b/js/src/ion/shared/BaselineCompiler-shared.h
@@ -20,17 +20,16 @@ namespace ion {
 class BaselineCompilerShared
 {
   protected:
     JSContext *cx;
     RootedScript script;
     jsbytecode *pc;
     MacroAssembler masm;
     bool ionCompileable_;
-    bool ionOSRCompileable_;
     bool debugMode_;
 
     FrameInfo frame;
 
     FallbackICStubSpace stubSpace_;
     js::Vector<ICEntry, 16, SystemAllocPolicy> icEntries_;
 
     // Stores the native code offset for a bytecode pc.
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/arguments-objects.js
+++ /dev/null
@@ -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);
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -13,18 +13,16 @@
 #include "vm/Xdr.h"
 
 #include "jsobjinlines.h"
 
 #include "gc/Barrier-inl.h"
 #include "vm/Stack-inl.h"
 #include "vm/ArgumentsObject-inl.h"
 
-#include "ion/IonFrames.h"
-
 using namespace js;
 using namespace js::gc;
 
 static void
 CopyStackFrameArguments(const AbstractFramePtr frame, HeapValue *dst)
 {
     JS_ASSERT_IF(frame.isStackFrame(), !frame.asStackFrame()->runningInIon());
 
@@ -42,43 +40,26 @@ CopyStackFrameArguments(const AbstractFr
         src = frame.actuals() + numFormals;
         end = src + (numActuals - numFormals);
         while (src != end)
             (dst++)->init(*src++);
     }
 }
 
 /* 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()) {
         obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(frame.callObj()));
         for (AliasedFormalIter fi(script); fi; fi++)
             data->args[fi.frameIndex()] = MagicValue(JS_FORWARD_TO_CALL_OBJECT);
     }
 }
 
-#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_;
 
     CopyFrameArgs(AbstractFramePtr frame)
       : frame_(frame)
     { }
 
@@ -90,46 +71,16 @@ struct CopyFrameArgs
      * 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_, obj, data);
     }
 };
 
-#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_;
 
     CopyStackIterArgs(StackIter &iter)
       : iter_(iter)
     { }
 
@@ -252,30 +203,16 @@ ArgumentsObject *
 ArgumentsObject::createUnexpected(JSContext *cx, AbstractFramePtr frame)
 {
     RootedScript script(cx, frame.script());
     RootedFunction callee(cx, frame.callee());
     CopyFrameArgs copy(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)
 {
     ArgumentsObject &argsobj = obj->asArguments();
     if (JSID_IS_INT(id)) {
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg))
             argsobj.markElementDeleted(arg);
--- a/js/src/vm/ArgumentsObject.h
+++ b/js/src/vm/ArgumentsObject.h
@@ -120,20 +120,16 @@ class ArgumentsObject : public JSObject
     /*
      * Purposefully disconnect the returned arguments object from the frame
      * by always creating a new copy that does not alias formal parameters.
      * This allows function-local analysis to determine that formals are
      * not aliased and generally simplifies arguments objects.
      */
     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
      * current value of arguments.length!
      */
     inline uint32_t initialLength() const;
 
     /* The script for the function containing this arguments object. */
@@ -206,20 +202,16 @@ class ArgumentsObject : public JSObject
     static size_t getDataSlotOffset() {
         return getFixedSlotOffset(DATA_SLOT);
     }
     static size_t getInitialLengthSlotOffset() {
         return getFixedSlotOffset(INITIAL_LENGTH_SLOT);
     }
 
     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
 {
   public:
     /*
      * Stores arguments.callee, or MagicValue(JS_ARGS_HOLE) if the callee has
      * been cleared.
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1127,17 +1127,17 @@ ContextStack::pushBailoutArgs(JSContext 
 
     ion::SnapshotIterator s(it);
     JSFunction *fun = it.callee();
     iag->setCallee(ObjectValue(*fun));
 
     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;
 }
 
 StackFrame *
 ContextStack::pushBailoutFrame(JSContext *cx, const ion::IonBailoutIterator &it,
                                const CallArgs &args, BailoutFrameGuard *bfg)
 {
     JSFunction *fun = it.callee();