Bug 729382 - move the rest of the CallObject into ScopeObject (r=waldo)
authorLuke Wagner <luke@mozilla.com>
Thu, 23 Feb 2012 13:58:39 -0800
changeset 87895 d485f2378abe54f7e1acdff0fbb79c9888978c77
parent 87894 bd71047c9b4d53b5e8ead4cfe63b6e5267b02fe7
child 87896 43766cfb6d30600beaf695a9f652a8befd4631fe
push id6561
push userlwagner@mozilla.com
push dateTue, 28 Feb 2012 08:34:43 +0000
treeherdermozilla-inbound@d485f2378abe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswaldo
bugs729382
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 729382 - move the rest of the CallObject into ScopeObject (r=waldo)
js/src/jsdbgapi.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsinterp.cpp
js/src/jsscript.cpp
js/src/methodjit/PolyIC.cpp
js/src/vm/Debugger.cpp
js/src/vm/ScopeObject.cpp
js/src/vm/ScopeObject.h
js/src/vm/Stack-inl.h
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -584,17 +584,17 @@ JS_GetFrameCallObject(JSContext *cx, JSS
     if (!ac.enter())
         return NULL;
 
     /*
      * XXX ill-defined: null return here means error was reported, unlike a
      *     null returned above or in the #else
      */
     if (!fp->hasCallObj() && fp->isNonEvalFunctionFrame())
-        return CreateFunCallObject(cx, fp);
+        return CallObject::createForFunction(cx, fp);
     return &fp->callObj();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetFrameThis(JSContext *cx, JSStackFrame *fpArg, jsval *thisv)
 {
     StackFrame *fp = Valueify(fpArg);
     if (fp->isDummyFrame())
@@ -839,20 +839,20 @@ JS_GetPropertyDesc(JSContext *cx, JSObje
 
     if (wasThrowing)
         cx->setPendingException(lastException);
 
     pd->flags |= (shape->enumerable() ? JSPD_ENUMERATE : 0)
               |  (!shape->writable()  ? JSPD_READONLY  : 0)
               |  (!shape->configurable() ? JSPD_PERMANENT : 0);
     pd->spare = 0;
-    if (shape->getter() == GetCallArg) {
+    if (shape->getter() == CallObject::getArgOp) {
         pd->slot = shape->shortid();
         pd->flags |= JSPD_ARGUMENT;
-    } else if (shape->getter() == GetCallVar) {
+    } else if (shape->getter() == CallObject::getVarOp) {
         pd->slot = shape->shortid();
         pd->flags |= JSPD_VARIABLE;
     } else {
         pd->slot = 0;
     }
     pd->alias = JSVAL_VOID;
 
     return JS_TRUE;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -594,360 +594,16 @@ Class js::StrictArgumentsObjectClass = {
         NULL,       /* outerObject */
         NULL,       /* innerObject */
         JS_ElementIteratorStub,
         NULL,       /* unused      */
         false,      /* isWrappedNative */
     }
 };
 
-namespace js {
-
-CallObject *
-CreateFunCallObject(JSContext *cx, StackFrame *fp)
-{
-    JS_ASSERT(fp->isNonEvalFunctionFrame());
-    JS_ASSERT(!fp->hasCallObj());
-
-    JSObject *scopeChain = &fp->scopeChain();
-    JS_ASSERT_IF(scopeChain->isWith() || scopeChain->isBlock() || scopeChain->isCall(),
-                 scopeChain->getPrivate() != fp);
-
-    /*
-     * For a named function expression Call's parent points to an environment
-     * object holding function's name.
-     */
-    if (JSAtom *lambdaName = CallObjectLambdaName(fp->fun())) {
-        scopeChain = DeclEnvObject::create(cx, fp);
-        if (!scopeChain)
-            return NULL;
-
-        if (!DefineNativeProperty(cx, scopeChain, ATOM_TO_JSID(lambdaName),
-                                  ObjectValue(fp->callee()), NULL, NULL,
-                                  JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
-            return NULL;
-        }
-    }
-
-    CallObject *callobj = CallObject::create(cx, fp->script(), *scopeChain, &fp->callee());
-    if (!callobj)
-        return NULL;
-
-    callobj->setStackFrame(fp);
-    fp->setScopeChainWithOwnCallObj(*callobj);
-    return callobj;
-}
-
-CallObject *
-CreateEvalCallObject(JSContext *cx, StackFrame *fp)
-{
-    CallObject *callobj = CallObject::create(cx, fp->script(), fp->scopeChain(), NULL);
-    if (!callobj)
-        return NULL;
-
-    callobj->setStackFrame(fp);
-    fp->setScopeChainWithOwnCallObj(*callobj);
-    return callobj;
-}
-
-} // namespace js
-
-void
-js_PutCallObject(StackFrame *fp)
-{
-    CallObject &callobj = fp->callObj().asCall();
-    JS_ASSERT(callobj.maybeStackFrame() == fp);
-    JS_ASSERT_IF(fp->isEvalFrame(), fp->isStrictEvalFrame());
-    JS_ASSERT(fp->isEvalFrame() == callobj.isForEval());
-
-    /* Get the arguments object to snapshot fp's actual argument values. */
-    if (fp->hasArgsObj()) {
-        if (callobj.arguments().isMagic(JS_UNASSIGNED_ARGUMENTS))
-            callobj.setArguments(ObjectValue(fp->argsObj()));
-        js_PutArgsObject(fp);
-    }
-
-    JSScript *script = fp->script();
-    Bindings &bindings = script->bindings;
-
-    if (callobj.isForEval()) {
-        JS_ASSERT(script->strictModeCode);
-        JS_ASSERT(bindings.countArgs() == 0);
-
-        /* This could be optimized as below, but keep it simple for now. */
-        callobj.copyValues(0, NULL, bindings.countVars(), fp->slots());
-    } else {
-        JSFunction *fun = fp->fun();
-        JS_ASSERT(script == callobj.getCalleeFunction()->script());
-        JS_ASSERT(script == fun->script());
-
-        uintN n = bindings.countArgsAndVars();
-        if (n > 0) {
-            uint32_t nvars = bindings.countVars();
-            uint32_t nargs = bindings.countArgs();
-            JS_ASSERT(fun->nargs == nargs);
-            JS_ASSERT(nvars + nargs == n);
-
-            JSScript *script = fun->script();
-            if (script->usesEval
-#ifdef JS_METHODJIT
-                || script->debugMode
-#endif
-                ) {
-                callobj.copyValues(nargs, fp->formalArgs(), nvars, fp->slots());
-            } else {
-                /*
-                 * For each arg & var that is closed over, copy it from the stack
-                 * into the call object. We use initArg/VarUnchecked because,
-                 * when you call a getter on a call object, js_NativeGetInline
-                 * caches the return value in the slot, so we can't assert that
-                 * it's undefined.
-                 */
-                uint32_t nclosed = script->nClosedArgs;
-                for (uint32_t i = 0; i < nclosed; i++) {
-                    uint32_t e = script->getClosedArg(i);
-#ifdef JS_GC_ZEAL
-                    callobj.setArg(e, fp->formalArg(e));
-#else
-                    callobj.initArgUnchecked(e, fp->formalArg(e));
-#endif
-                }
-
-                nclosed = script->nClosedVars;
-                for (uint32_t i = 0; i < nclosed; i++) {
-                    uint32_t e = script->getClosedVar(i);
-#ifdef JS_GC_ZEAL
-                    callobj.setVar(e, fp->slots()[e]);
-#else
-                    callobj.initVarUnchecked(e, fp->slots()[e]);
-#endif
-                }
-            }
-
-            /*
-             * Update the args and vars for the active call if this is an outer
-             * function in a script nesting.
-             */
-            types::TypeScriptNesting *nesting = script->nesting();
-            if (nesting && script->isOuterFunction) {
-                nesting->argArray = callobj.argArray();
-                nesting->varArray = callobj.varArray();
-            }
-        }
-
-        /* Clear private pointers to fp, which is about to go away. */
-        if (js_IsNamedLambda(fun)) {
-            JSObject &env = callobj.enclosingScope();
-            JS_ASSERT(env.asDeclEnv().maybeStackFrame() == fp);
-            env.setPrivate(NULL);
-        }
-    }
-
-    callobj.setStackFrame(NULL);
-}
-
-namespace js {
-
-static JSBool
-GetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-
-    StackFrame *fp = callobj.maybeStackFrame();
-    if (fp && callobj.arguments().isMagic(JS_UNASSIGNED_ARGUMENTS)) {
-        JSObject *argsobj = js_GetArgsObject(cx, fp);
-        if (!argsobj)
-            return false;
-        vp->setObject(*argsobj);
-    } else {
-        /* Nested functions cannot get the 'arguments' of enclosing scopes. */
-        JS_ASSERT(!callobj.arguments().isMagic(JS_UNASSIGNED_ARGUMENTS));
-        *vp = callobj.arguments();
-    }
-    return true;
-}
-
-static JSBool
-SetCallArguments(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
-{
-    /* Nested functions cannot set the 'arguments' of enclosing scopes. */
-    JS_ASSERT(obj->asCall().maybeStackFrame());
-    obj->asCall().setArguments(*vp);
-    return true;
-}
-
-JSBool
-GetCallArg(JSContext *cx, JSObject *obj, jsid id, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        *vp = fp->formalArg(i);
-    else
-        *vp = callobj.arg(i);
-    return true;
-}
-
-JSBool
-SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        fp->formalArg(i) = *vp;
-    else
-        callobj.setArg(i, *vp);
-
-    JSFunction *fun = callobj.getCalleeFunction();
-    JSScript *script = fun->script();
-    if (!script->ensureHasTypes(cx))
-        return false;
-
-    TypeScript::SetArgument(cx, script, i, *vp);
-
-    return true;
-}
-
-JSBool
-GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    *vp = callobj.getCallee()->toFunction()->getFlatClosureUpvar(i);
-    return true;
-}
-
-JSBool
-SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    callobj.getCallee()->toFunction()->setFlatClosureUpvar(i, *vp);
-    return true;
-}
-
-JSBool
-GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        *vp = fp->varSlot(i);
-    else
-        *vp = callobj.var(i);
-    return true;
-}
-
-JSBool
-SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        fp->varSlot(i) = *vp;
-    else
-        callobj.setVar(i, *vp);
-
-    JSFunction *fun = callobj.getCalleeFunction();
-    JSScript *script = fun->script();
-    if (!script->ensureHasTypes(cx))
-        return false;
-
-    TypeScript::SetLocal(cx, script, i, *vp);
-
-    return true;
-}
-
-} // namespace js
-
-static JSBool
-call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
-{
-    JS_ASSERT(!obj->getProto());
-
-    if (!JSID_IS_ATOM(id))
-        return true;
-
-    JSObject *callee = obj->asCall().getCallee();
-#ifdef DEBUG
-    if (callee) {
-        JSScript *script = callee->toFunction()->script();
-        JS_ASSERT(!script->bindings.hasBinding(cx, JSID_TO_ATOM(id)));
-    }
-#endif
-
-    /*
-     * Resolve arguments so that we never store a particular Call object's
-     * arguments object reference in a Call prototype's |arguments| slot.
-     *
-     * Include JSPROP_ENUMERATE for consistency with all other Call object
-     * properties; see js::Bindings::add and js::Interpret's JSOP_DEFFUN
-     * rebinding-Call-property logic.
-     */
-    if (callee && id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) {
-        if (!DefineNativeProperty(cx, obj, id, UndefinedValue(),
-                                  GetCallArguments, SetCallArguments,
-                                  JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE,
-                                  0, 0, DNP_DONT_PURGE)) {
-            return false;
-        }
-        *objp = obj;
-        return true;
-    }
-
-    /* Control flow reaches here only if id was not resolved. */
-    return true;
-}
-
-static void
-call_trace(JSTracer *trc, JSObject *obj)
-{
-    JS_ASSERT(obj->isCall());
-
-    /* Mark any generator frame, as for arguments objects. */
-#if JS_HAS_GENERATORS
-    StackFrame *fp = (StackFrame *) obj->getPrivate();
-    if (fp && fp->isFloatingGenerator())
-        MarkObject(trc, &js_FloatingFrameToGenerator(fp)->obj, "generator object");
-#endif
-}
-
-JS_PUBLIC_DATA(Class) js::CallClass = {
-    "Call",
-    JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
-    JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS) |
-    JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS,
-    JS_PropertyStub,         /* addProperty */
-    JS_PropertyStub,         /* delProperty */
-    JS_PropertyStub,         /* getProperty */
-    JS_StrictPropertyStub,   /* setProperty */
-    JS_EnumerateStub,
-    (JSResolveOp)call_resolve,
-    NULL,                    /* convert: Leave it NULL so we notice if calls ever escape */
-    NULL,                    /* finalize */
-    NULL,                    /* checkAccess */
-    NULL,                    /* call        */
-    NULL,                    /* construct   */
-    NULL,                    /* hasInstance */
-    call_trace
-};
-
 bool
 StackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
 {
     if (!isFunctionFrame()) {
         vp->setNull();
         return true;
     }
 
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -357,40 +357,16 @@ js_ValueToCallableObject(JSContext *cx, 
 extern void
 js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
 
 extern void
 js_PutCallObject(js::StackFrame *fp);
 
 namespace js {
 
-CallObject *
-CreateFunCallObject(JSContext *cx, StackFrame *fp);
-
-CallObject *
-CreateEvalCallObject(JSContext *cx, StackFrame *fp);
-
-extern JSBool
-GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
-
-extern JSBool
-GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
-
-extern JSBool
-GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
-
-extern JSBool
-SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
-
-extern JSBool
-SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
-
-extern JSBool
-SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
-
 /*
  * Function extended with reserved slots for use by various kinds of functions.
  * Most functions do not have these extensions, but enough are that efficient
  * storage is required (no malloc'ed reserved slots).
  */
 class FunctionExtended : public JSFunction
 {
     friend struct JSFunction;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -155,17 +155,17 @@ js::GetScopeChain(JSContext *cx, StackFr
      * make sure there's a call object at the current head of the scope chain,
      * if this frame is a call frame.
      *
      * Also, identify the innermost compiler-allocated block we needn't clone.
      */
     JSObject *limitBlock, *limitClone;
     if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj()) {
         JS_ASSERT_IF(fp->scopeChain().isClonedBlock(), fp->scopeChain().getPrivate() != fp);
-        if (!CreateFunCallObject(cx, fp))
+        if (!CallObject::createForFunction(cx, fp))
             return NULL;
 
         /* We know we must clone everything on blockChain. */
         limitBlock = limitClone = NULL;
     } else {
         /*
          * scopeChain includes all blocks whose static scope we're within that
          * have already been cloned.  Find the innermost such block.  Its
@@ -641,17 +641,17 @@ js::ExecuteKernel(JSContext *cx, JSScrip
     if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg))
         return false;
 
     if (!script->ensureRanAnalysis(cx, &scopeChain))
         return false;
 
     /* Give strict mode eval its own fresh lexical environment. */
     StackFrame *fp = efg.fp();
-    if (fp->isStrictEvalFrame() && !CreateEvalCallObject(cx, fp))
+    if (fp->isStrictEvalFrame() && !CallObject::createForStrictEval(cx, fp))
         return false;
 
     Probes::startExecution(cx, script);
 
     TypeScript::SetThis(cx, script, fp->thisValue());
 
     AutoPreserveEnumerators preserve(cx);
     JSBool ok = RunScript(cx, script, fp);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -93,19 +93,19 @@ Bindings::lookup(JSContext *cx, JSAtom *
     Shape **spp;
     Shape *shape = Shape::search(cx, lastBinding, ATOM_TO_JSID(name), &spp);
     if (!shape)
         return NONE;
 
     if (indexp)
         *indexp = shape->shortid();
 
-    if (shape->getter() == GetCallArg)
+    if (shape->getter() == CallObject::getArgOp)
         return ARGUMENT;
-    if (shape->getter() == GetCallUpvar)
+    if (shape->getter() == CallObject::getUpvarOp)
         return UPVAR;
 
     return shape->writable() ? VARIABLE : CONSTANT;
 }
 
 bool
 Bindings::add(JSContext *cx, JSAtom *name, BindingKind kind)
 {
@@ -123,32 +123,32 @@ Bindings::add(JSContext *cx, JSAtom *nam
     PropertyOp getter;
     StrictPropertyOp setter;
     uint32_t slot = CallObject::RESERVED_SLOTS;
 
     if (kind == ARGUMENT) {
         JS_ASSERT(nvars == 0);
         JS_ASSERT(nupvars == 0);
         indexp = &nargs;
-        getter = GetCallArg;
-        setter = SetCallArg;
+        getter = CallObject::getArgOp;
+        setter = CallObject::setArgOp;
         slot += nargs;
     } else if (kind == UPVAR) {
         indexp = &nupvars;
-        getter = GetCallUpvar;
-        setter = SetCallUpvar;
+        getter = CallObject::getUpvarOp;
+        setter = CallObject::setUpvarOp;
         slot = lastBinding->maybeSlot();
         attrs |= JSPROP_SHARED;
     } else {
         JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
         JS_ASSERT(nupvars == 0);
 
         indexp = &nvars;
-        getter = GetCallVar;
-        setter = SetCallVar;
+        getter = CallObject::getVarOp;
+        setter = CallObject::setVarOp;
         if (kind == CONSTANT)
             attrs |= JSPROP_READONLY;
         slot += nargs + nvars;
     }
 
     if (*indexp == BINDING_COUNT_LIMIT) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              (kind == ARGUMENT)
@@ -243,31 +243,31 @@ Bindings::getLocalNameArray(JSContext *c
     for (uintN i = 0; i < n; i++)
         names[i] = POISON;
 #endif
 
     for (Shape::Range r = lastBinding->all(); !r.empty(); r.popFront()) {
         const Shape &shape = r.front();
         uintN index = uint16_t(shape.shortid());
 
-        if (shape.getter() == GetCallArg) {
+        if (shape.getter() == CallObject::getArgOp) {
             JS_ASSERT(index < nargs);
-        } else if (shape.getter() == GetCallUpvar) {
+        } else if (shape.getter() == CallObject::getUpvarOp) {
             JS_ASSERT(index < nupvars);
             index += nargs + nvars;
         } else {
             JS_ASSERT(index < nvars);
             index += nargs;
         }
 
         if (JSID_IS_ATOM(shape.propid())) {
             names[index] = JSID_TO_ATOM(shape.propid());
         } else {
             JS_ASSERT(JSID_IS_INT(shape.propid()));
-            JS_ASSERT(shape.getter() == GetCallArg);
+            JS_ASSERT(shape.getter() == CallObject::getArgOp);
             names[index] = NULL;
         }
     }
 
 #ifdef DEBUG
     for (uintN i = 0; i < n; i++)
         JS_ASSERT(names[i] != POISON);
 #endif
@@ -277,30 +277,30 @@ Bindings::getLocalNameArray(JSContext *c
 
 const Shape *
 Bindings::lastArgument() const
 {
     JS_ASSERT(lastBinding);
 
     const js::Shape *shape = lastVariable();
     if (nvars > 0) {
-        while (shape->previous() && shape->getter() != GetCallArg)
+        while (shape->previous() && shape->getter() != CallObject::getArgOp)
             shape = shape->previous();
     }
     return shape;
 }
 
 const Shape *
 Bindings::lastVariable() const
 {
     JS_ASSERT(lastBinding);
 
     const js::Shape *shape = lastUpvar();
     if (nupvars > 0) {
-        while (shape->getter() == GetCallUpvar)
+        while (shape->getter() == CallObject::getUpvarOp)
             shape = shape->previous();
     }
     return shape;
 }
 
 const Shape *
 Bindings::lastUpvar() const
 {
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -403,26 +403,26 @@ class SetPropCompiler : public PICStubCo
             JSFunction *fun = obj->asCall().getCalleeFunction();
             uint16_t slot = uint16_t(shape->shortid());
 
             /* Guard that the call object has a frame. */
             masm.loadObjPrivate(pic.objReg, pic.shapeReg, obj->numFixedSlots());
             Jump escapedFrame = masm.branchTestPtr(Assembler::Zero, pic.shapeReg, pic.shapeReg);
 
             {
-                Address addr(pic.shapeReg, shape->setterOp() == SetCallArg
+                Address addr(pic.shapeReg, shape->setterOp() == CallObject::setArgOp
                                            ? StackFrame::offsetOfFormalArg(fun, slot)
                                            : StackFrame::offsetOfFixed(slot));
                 masm.storeValue(pic.u.vr, addr);
                 skipOver = masm.jump();
             }
 
             escapedFrame.linkTo(masm.label(), &masm);
             {
-                if (shape->setterOp() == SetCallVar)
+                if (shape->setterOp() == CallObject::setVarOp)
                     slot += fun->nargs;
 
                 slot += CallObject::RESERVED_SLOTS;
                 Address address = masm.objPropAddress(obj, pic.objReg, slot);
 
                 masm.storeValue(pic.u.vr, address);
             }
 
@@ -650,18 +650,18 @@ class SetPropCompiler : public PICStubCo
         if (shape->hasDefaultSetter()) {
             if (!shape->hasSlot())
                 return disable("invalid slot");
             if (pic.typeMonitored && !updateMonitoredTypes())
                 return Lookup_Uncacheable;
         } else {
             if (shape->hasSetterValue())
                 return disable("scripted setter");
-            if (shape->setterOp() != SetCallArg &&
-                shape->setterOp() != SetCallVar) {
+            if (shape->setterOp() != CallObject::setArgOp &&
+                shape->setterOp() != CallObject::setVarOp) {
                 return disable("setter");
             }
             JS_ASSERT(obj->isCall());
             if (pic.typeMonitored) {
                 /*
                  * Update the types of the locals/args in the script according
                  * to the possible RHS types of the assignment. Note that the
                  * shape guards we have performed do not by themselves
@@ -674,17 +674,17 @@ class SetPropCompiler : public PICStubCo
                 RecompilationMonitor monitor(cx);
                 JSFunction *fun = obj->asCall().getCalleeFunction();
                 JSScript *script = fun->script();
                 uint16_t slot = uint16_t(shape->shortid());
                 if (!script->ensureHasTypes(cx))
                     return error();
                 {
                     types::AutoEnterTypeInference enter(cx);
-                    if (shape->setterOp() == SetCallArg)
+                    if (shape->setterOp() == CallObject::setArgOp)
                         pic.rhsTypes->addSubset(cx, types::TypeScript::ArgTypes(script, slot));
                     else
                         pic.rhsTypes->addSubset(cx, types::TypeScript::LocalTypes(script, slot));
                 }
                 if (monitor.recompiled())
                     return Lookup_Uncacheable;
             }
         }
@@ -1543,19 +1543,19 @@ class ScopeNameCompiler : public PICStub
         if (pic.kind == ic::PICInfo::NAME)
             masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfScopeChain()), pic.objReg);
 
         JS_ASSERT(obj == getprop.holder);
         JS_ASSERT(getprop.holder != &scopeChain->global());
 
         CallObjPropKind kind;
         const Shape *shape = getprop.shape;
-        if (shape->getterOp() == GetCallArg) {
+        if (shape->getterOp() == CallObject::getArgOp) {
             kind = ARG;
-        } else if (shape->getterOp() == GetCallVar) {
+        } else if (shape->getterOp() == CallObject::getVarOp) {
             kind = VAR;
         } else {
             return disable("unhandled callobj sprop getter");
         }
 
         LookupStatus status = walkScopeChain(masm, fails);
         if (status != Lookup_Cacheable)
             return status;
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2489,17 +2489,17 @@ DebuggerFrame_getType(JSContext *cx, uin
                           : cx->runtime->atomState.callAtom);
     return true;
 }
 
 static Env *
 Frame_GetEnv(JSContext *cx, StackFrame *fp)
 {
     assertSameCompartment(cx, fp);
-    if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj() && !CreateFunCallObject(cx, fp))
+    if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj() && !CallObject::createForFunction(cx, fp))
         return NULL;
     return GetScopeChain(cx, fp);
 }
 
 static JSBool
 DebuggerFrame_getEnvironment(JSContext *cx, uintN argc, Value *vp)
 {
     THIS_FRAME_OWNER(cx, argc, vp, "get environment", args, thisobj, fp, dbg);
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -18,16 +18,17 @@
  *
  * The Initial Developer of the Original Code is
  * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Paul Biggar <pbiggar@mozilla.com> (original author)
+ *   Luke Wagner <luke@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -51,16 +52,110 @@
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 
 #include "ScopeObject-inl.h"
 
 using namespace js;
 using namespace js::types;
 
+void
+js_PutCallObject(StackFrame *fp)
+{
+    CallObject &callobj = fp->callObj().asCall();
+    JS_ASSERT(callobj.maybeStackFrame() == fp);
+    JS_ASSERT_IF(fp->isEvalFrame(), fp->isStrictEvalFrame());
+    JS_ASSERT(fp->isEvalFrame() == callobj.isForEval());
+
+    /* Get the arguments object to snapshot fp's actual argument values. */
+    if (fp->hasArgsObj()) {
+        if (callobj.arguments().isMagic(JS_UNASSIGNED_ARGUMENTS))
+            callobj.setArguments(ObjectValue(fp->argsObj()));
+        js_PutArgsObject(fp);
+    }
+
+    JSScript *script = fp->script();
+    Bindings &bindings = script->bindings;
+
+    if (callobj.isForEval()) {
+        JS_ASSERT(script->strictModeCode);
+        JS_ASSERT(bindings.countArgs() == 0);
+
+        /* This could be optimized as below, but keep it simple for now. */
+        callobj.copyValues(0, NULL, bindings.countVars(), fp->slots());
+    } else {
+        JSFunction *fun = fp->fun();
+        JS_ASSERT(script == callobj.getCalleeFunction()->script());
+        JS_ASSERT(script == fun->script());
+
+        uintN n = bindings.countArgsAndVars();
+        if (n > 0) {
+            uint32_t nvars = bindings.countVars();
+            uint32_t nargs = bindings.countArgs();
+            JS_ASSERT(fun->nargs == nargs);
+            JS_ASSERT(nvars + nargs == n);
+
+            JSScript *script = fun->script();
+            if (script->usesEval
+#ifdef JS_METHODJIT
+                || script->debugMode
+#endif
+                ) {
+                callobj.copyValues(nargs, fp->formalArgs(), nvars, fp->slots());
+            } else {
+                /*
+                 * For each arg & var that is closed over, copy it from the stack
+                 * into the call object. We use initArg/VarUnchecked because,
+                 * when you call a getter on a call object, js_NativeGetInline
+                 * caches the return value in the slot, so we can't assert that
+                 * it's undefined.
+                 */
+                uint32_t nclosed = script->nClosedArgs;
+                for (uint32_t i = 0; i < nclosed; i++) {
+                    uint32_t e = script->getClosedArg(i);
+#ifdef JS_GC_ZEAL
+                    callobj.setArg(e, fp->formalArg(e));
+#else
+                    callobj.initArgUnchecked(e, fp->formalArg(e));
+#endif
+                }
+
+                nclosed = script->nClosedVars;
+                for (uint32_t i = 0; i < nclosed; i++) {
+                    uint32_t e = script->getClosedVar(i);
+#ifdef JS_GC_ZEAL
+                    callobj.setVar(e, fp->slots()[e]);
+#else
+                    callobj.initVarUnchecked(e, fp->slots()[e]);
+#endif
+                }
+            }
+
+            /*
+             * Update the args and vars for the active call if this is an outer
+             * function in a script nesting.
+             */
+            types::TypeScriptNesting *nesting = script->nesting();
+            if (nesting && script->isOuterFunction) {
+                nesting->argArray = callobj.argArray();
+                nesting->varArray = callobj.varArray();
+            }
+        }
+
+        /* Clear private pointers to fp, which is about to go away. */
+        if (js_IsNamedLambda(fun)) {
+            JSObject &env = callobj.enclosingScope();
+            JS_ASSERT(env.asDeclEnv().maybeStackFrame() == fp);
+            env.setPrivate(NULL);
+        }
+    }
+
+    callobj.setStackFrame(NULL);
+}
+
 /*
  * Construct a call object for the given bindings.  If this is a call object
  * for a function invocation, callee should be the function being called.
  * Otherwise it must be a call object for eval of strict mode code, and callee
  * must be null.
  */
 CallObject *
 CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee)
@@ -121,16 +216,258 @@ CallObject::create(JSContext *cx, JSScri
      * its Call should have its own shape; see BaseShape::extensibleParents.
      */
     if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
         return NULL;
 
     return &obj->asCall();
 }
 
+CallObject *
+CallObject::createForFunction(JSContext *cx, StackFrame *fp)
+{
+    JS_ASSERT(fp->isNonEvalFunctionFrame());
+    JS_ASSERT(!fp->hasCallObj());
+
+    JSObject *scopeChain = &fp->scopeChain();
+    JS_ASSERT_IF(scopeChain->isWith() || scopeChain->isBlock() || scopeChain->isCall(),
+                 scopeChain->getPrivate() != fp);
+
+    /*
+     * For a named function expression Call's parent points to an environment
+     * object holding function's name.
+     */
+    if (JSAtom *lambdaName = CallObjectLambdaName(fp->fun())) {
+        scopeChain = DeclEnvObject::create(cx, fp);
+        if (!scopeChain)
+            return NULL;
+
+        if (!DefineNativeProperty(cx, scopeChain, ATOM_TO_JSID(lambdaName),
+                                  ObjectValue(fp->callee()), NULL, NULL,
+                                  JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
+            return NULL;
+        }
+    }
+
+    CallObject *callobj = create(cx, fp->script(), *scopeChain, &fp->callee());
+    if (!callobj)
+        return NULL;
+
+    callobj->setStackFrame(fp);
+    fp->setScopeChainWithOwnCallObj(*callobj);
+    return callobj;
+}
+
+CallObject *
+CallObject::createForStrictEval(JSContext *cx, StackFrame *fp)
+{
+    CallObject *callobj = create(cx, fp->script(), fp->scopeChain(), NULL);
+    if (!callobj)
+        return NULL;
+
+    callobj->setStackFrame(fp);
+    fp->setScopeChainWithOwnCallObj(*callobj);
+    return callobj;
+}
+
+JSBool
+CallObject::getArgumentsOp(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+{
+    CallObject &callobj = obj->asCall();
+
+    StackFrame *fp = callobj.maybeStackFrame();
+    if (fp && callobj.arguments().isMagic(JS_UNASSIGNED_ARGUMENTS)) {
+        JSObject *argsobj = js_GetArgsObject(cx, fp);
+        if (!argsobj)
+            return false;
+        vp->setObject(*argsobj);
+    } else {
+        /* Nested functions cannot get the 'arguments' of enclosing scopes. */
+        JS_ASSERT(!callobj.arguments().isMagic(JS_UNASSIGNED_ARGUMENTS));
+        *vp = callobj.arguments();
+    }
+    return true;
+}
+
+JSBool
+CallObject::setArgumentsOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
+{
+    /* Nested functions cannot set the 'arguments' of enclosing scopes. */
+    JS_ASSERT(obj->asCall().maybeStackFrame());
+    obj->asCall().setArguments(*vp);
+    return true;
+}
+
+JSBool
+CallObject::getArgOp(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+{
+    CallObject &callobj = obj->asCall();
+    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
+    uintN i = (uint16_t) JSID_TO_INT(id);
+
+    if (StackFrame *fp = callobj.maybeStackFrame())
+        *vp = fp->formalArg(i);
+    else
+        *vp = callobj.arg(i);
+    return true;
+}
+
+JSBool
+CallObject::setArgOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
+{
+    CallObject &callobj = obj->asCall();
+    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
+    uintN i = (uint16_t) JSID_TO_INT(id);
+
+    if (StackFrame *fp = callobj.maybeStackFrame())
+        fp->formalArg(i) = *vp;
+    else
+        callobj.setArg(i, *vp);
+
+    JSFunction *fun = callobj.getCalleeFunction();
+    JSScript *script = fun->script();
+    if (!script->ensureHasTypes(cx))
+        return false;
+
+    TypeScript::SetArgument(cx, script, i, *vp);
+
+    return true;
+}
+
+JSBool
+CallObject::getUpvarOp(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+{
+    CallObject &callobj = obj->asCall();
+    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
+    uintN i = (uint16_t) JSID_TO_INT(id);
+
+    *vp = callobj.getCallee()->toFunction()->getFlatClosureUpvar(i);
+    return true;
+}
+
+JSBool
+CallObject::setUpvarOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
+{
+    CallObject &callobj = obj->asCall();
+    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
+    uintN i = (uint16_t) JSID_TO_INT(id);
+
+    callobj.getCallee()->toFunction()->setFlatClosureUpvar(i, *vp);
+    return true;
+}
+
+JSBool
+CallObject::getVarOp(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+{
+    CallObject &callobj = obj->asCall();
+    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
+    uintN i = (uint16_t) JSID_TO_INT(id);
+
+    if (StackFrame *fp = callobj.maybeStackFrame())
+        *vp = fp->varSlot(i);
+    else
+        *vp = callobj.var(i);
+    return true;
+}
+
+JSBool
+CallObject::setVarOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
+{
+    CallObject &callobj = obj->asCall();
+
+    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
+    uintN i = (uint16_t) JSID_TO_INT(id);
+
+    if (StackFrame *fp = callobj.maybeStackFrame())
+        fp->varSlot(i) = *vp;
+    else
+        callobj.setVar(i, *vp);
+
+    JSFunction *fun = callobj.getCalleeFunction();
+    JSScript *script = fun->script();
+    if (!script->ensureHasTypes(cx))
+        return false;
+
+    TypeScript::SetLocal(cx, script, i, *vp);
+
+    return true;
+}
+
+static JSBool
+call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
+{
+    JS_ASSERT(!obj->getProto());
+
+    if (!JSID_IS_ATOM(id))
+        return true;
+
+    JSObject *callee = obj->asCall().getCallee();
+#ifdef DEBUG
+    if (callee) {
+        JSScript *script = callee->toFunction()->script();
+        JS_ASSERT(!script->bindings.hasBinding(cx, JSID_TO_ATOM(id)));
+    }
+#endif
+
+    /*
+     * Resolve arguments so that we never store a particular Call object's
+     * arguments object reference in a Call prototype's |arguments| slot.
+     *
+     * Include JSPROP_ENUMERATE for consistency with all other Call object
+     * properties; see js::Bindings::add and js::Interpret's JSOP_DEFFUN
+     * rebinding-Call-property logic.
+     */
+    if (callee && id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) {
+        if (!DefineNativeProperty(cx, obj, id, UndefinedValue(),
+                                  CallObject::getArgumentsOp, CallObject::setArgumentsOp,
+                                  JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE,
+                                  0, 0, DNP_DONT_PURGE)) {
+            return false;
+        }
+        *objp = obj;
+        return true;
+    }
+
+    /* Control flow reaches here only if id was not resolved. */
+    return true;
+}
+
+static void
+call_trace(JSTracer *trc, JSObject *obj)
+{
+    JS_ASSERT(obj->isCall());
+
+    /* Mark any generator frame, as for arguments objects. */
+#if JS_HAS_GENERATORS
+    StackFrame *fp = (StackFrame *) obj->getPrivate();
+    if (fp && fp->isFloatingGenerator())
+        MarkObject(trc, &js_FloatingFrameToGenerator(fp)->obj, "generator object");
+#endif
+}
+
+JS_PUBLIC_DATA(Class) js::CallClass = {
+    "Call",
+    JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
+    JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS) |
+    JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS,
+    JS_PropertyStub,         /* addProperty */
+    JS_PropertyStub,         /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    JS_EnumerateStub,
+    (JSResolveOp)call_resolve,
+    NULL,                    /* convert: Leave it NULL so we notice if calls ever escape */
+    NULL,                    /* finalize */
+    NULL,                    /* checkAccess */
+    NULL,                    /* call        */
+    NULL,                    /* construct   */
+    NULL,                    /* hasInstance */
+    call_trace
+};
+
 Class js::DeclEnvClass = {
     js_Object_str,
     JSCLASS_HAS_PRIVATE |
     JSCLASS_HAS_RESERVED_SLOTS(DeclEnvObject::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
--- a/js/src/vm/ScopeObject.h
+++ b/js/src/vm/ScopeObject.h
@@ -98,33 +98,36 @@ class ScopeObject : public JSObject
      */
     inline JSObject &enclosingScope() const;
     inline bool setEnclosingScope(JSContext *cx, JSObject &obj);
 
     /*
      * The stack frame for this scope object, if the frame is still active.
      * Note: these members may not be called for a StaticBlockObject.
      */
-    inline js::StackFrame *maybeStackFrame() const;
+    inline StackFrame *maybeStackFrame() const;
     inline void setStackFrame(StackFrame *frame);
 
     /* For jit access. */
     static inline size_t offsetOfEnclosingScope();
 };
 
 class CallObject : public ScopeObject
 {
     static const uint32_t CALLEE_SLOT = 1;
     static const uint32_t ARGUMENTS_SLOT = 2;
 
+    static CallObject *
+    create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee);
+
   public:
     static const uint32_t RESERVED_SLOTS = 3;
 
-    static CallObject *
-    create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObject *callee);
+    static CallObject *createForFunction(JSContext *cx, StackFrame *fp);
+    static CallObject *createForStrictEval(JSContext *cx, StackFrame *fp);
 
     /* True if this is for a strict mode eval frame or for a function call. */
     inline bool isForEval() const;
 
     /*
      * The callee function if this CallObject was created for a function
      * invocation, or null if it was created for a strict mode eval frame.
      */
@@ -133,38 +136,47 @@ class CallObject : public ScopeObject
     inline void setCallee(JSObject *callee);
 
     /*
      * When a call object is created, CallObject::arguments has the value
      * MagicValue(JS_UNASSIGNED_ARGUMENTS). This value is overwritten if:
      *  1. js_PutCallObject is called in a frame which hasArgsObj
      *  2. the script assigns to 'arguments'
      */
-    inline const js::Value &arguments() const;
-    inline void setArguments(const js::Value &v);
+    inline const Value &arguments() const;
+    inline void setArguments(const Value &v);
 
     /* Returns the formal argument at the given index. */
-    inline const js::Value &arg(uintN i) const;
-    inline void setArg(uintN i, const js::Value &v);
-    inline void initArgUnchecked(uintN i, const js::Value &v);
+    inline const Value &arg(uintN i) const;
+    inline void setArg(uintN i, const Value &v);
+    inline void initArgUnchecked(uintN i, const Value &v);
 
     /* Returns the variable at the given index. */
-    inline const js::Value &var(uintN i) const;
-    inline void setVar(uintN i, const js::Value &v);
-    inline void initVarUnchecked(uintN i, const js::Value &v);
+    inline const Value &var(uintN i) const;
+    inline void setVar(uintN i, const Value &v);
+    inline void initVarUnchecked(uintN i, const Value &v);
 
     /*
      * Get the actual arrays of arguments and variables. Only call if type
      * inference is enabled, where we ensure that call object variables are in
      * contiguous slots (see NewCallObject).
      */
-    inline js::HeapSlotArray argArray();
-    inline js::HeapSlotArray varArray();
+    inline HeapSlotArray argArray();
+    inline HeapSlotArray varArray();
 
     inline void copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots);
+
+    static JSBool getArgumentsOp(JSContext *cx, JSObject *obj, jsid id, Value *vp);
+    static JSBool setArgumentsOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp);
+    static JSBool getArgOp(JSContext *cx, JSObject *obj, jsid id, Value *vp);
+    static JSBool getVarOp(JSContext *cx, JSObject *obj, jsid id, Value *vp);
+    static JSBool getUpvarOp(JSContext *cx, JSObject *obj, jsid id, Value *vp);
+    static JSBool setArgOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp);
+    static JSBool setVarOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp);
+    static JSBool setUpvarOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp);
 };
 
 class DeclEnvObject : public ScopeObject
 {
   public:
     static const uint32_t RESERVED_SLOTS = 1;
     static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT2;
 
@@ -215,17 +227,17 @@ class BlockObject : public NestedScopeOb
   protected:
     /* Blocks contain an object slot for each slot i: 0 <= i < slotCount. */
     inline HeapSlot &slotValue(unsigned i);
 };
 
 class StaticBlockObject : public BlockObject
 {
     /* These ScopeObject operations are not valid on a static block object. */
-    js::StackFrame *maybeStackFrame() const;
+    StackFrame *maybeStackFrame() const;
     void setStackFrame(StackFrame *frame);
 
   public:
     static StaticBlockObject *create(JSContext *cx);
 
     inline StaticBlockObject *enclosingBlock() const;
     inline void setEnclosingBlock(StaticBlockObject *blockObj);
 
@@ -234,17 +246,17 @@ class StaticBlockObject : public BlockOb
     /*
      * Frontend compilation temporarily uses the object's slots to link
      * a let var to its associated Definition parse node.
      */
     void setDefinitionParseNode(unsigned i, Definition *def);
     Definition *maybeDefinitionParseNode(unsigned i);
     void poisonDefinitionParseNode(unsigned i);
 
-    const js::Shape *addVar(JSContext *cx, jsid id, intN index, bool *redeclared);
+    const Shape *addVar(JSContext *cx, jsid id, intN index, bool *redeclared);
 };
 
 class ClonedBlockObject : public BlockObject
 {
   public:
     static ClonedBlockObject *create(JSContext *cx, StaticBlockObject &block, StackFrame *fp);
 
     /* The static block from which this block was cloned. */
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -365,17 +365,17 @@ StackFrame::maintainNestingState() const
 inline bool
 StackFrame::functionPrologue(JSContext *cx)
 {
     JS_ASSERT(isNonEvalFunctionFrame());
 
     JSFunction *fun = this->fun();
 
     if (fun->isHeavyweight()) {
-        if (!CreateFunCallObject(cx, this))
+        if (!CallObject::createForFunction(cx, this))
             return false;
     } else {
         /* Force instantiation of the scope chain, for JIT frames. */
         scopeChain();
     }
 
     if (script()->nesting()) {
         JS_ASSERT(maintainNestingState());