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()); unsigned 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); }