bool JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, HandlePropertyName name, HandleFunction targetFun) { RootedId id(cx, NameToId(name)); RootedValue funVal(cx); if (!GetUnclonedValue(cx, HandleObject::fromMarkedLocation(&selfHostingGlobal_), id, &funVal)) return false; RootedFunction sourceFun(cx, &funVal.toObject().as<JSFunction>()); // JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there // aren't any. JS_ASSERT(!sourceFun->isGenerator()); RootedScript sourceScript(cx, sourceFun->getOrCreateScript(cx)); if (!sourceScript) return false; JS_ASSERT(!sourceScript->enclosingStaticScope()); JSScript *cscript = CloneScript(cx, NullPtr(), targetFun, sourceScript); if (!cscript) return false; cscript->setFunction(targetFun); JS_ASSERT(sourceFun->nargs() == targetFun->nargs()); // The target function might have been relazified after it's flags changed. targetFun->setFlags((targetFun->flags() & ~JSFunction::INTERPRETED_LAZY) | sourceFun->flags() | JSFunction::EXTENDED); targetFun->setScript(cscript); JS_ASSERT(targetFun->isExtended()); return true; }
bool FrameIter::matchCallee(JSContext *cx, HandleFunction fun) const { RootedFunction currentCallee(cx, calleeTemplate()); // As we do not know if the calleeTemplate is the real function, or the // template from which it would be cloned, we compare properties which are // stable across the cloning of JSFunctions. if (((currentCallee->flags() ^ fun->flags()) & JSFunction::STABLE_ACROSS_CLONES) != 0 || currentCallee->nargs() != fun->nargs()) { return false; } // Only some lambdas are optimized in a way which cannot be recovered without // invalidating the frame. Thus, if one of the function is not a lambda we can just // compare it against the calleeTemplate. if (!fun->isLambda() || !currentCallee->isLambda()) return currentCallee == fun; // Use the same condition as |js::CloneFunctionObject|, to know if we should // expect both functions to have the same JSScript. If so, and if they are // different, then they cannot be equal. bool useSameScript = CloneFunctionObjectUseSameScript(fun->compartment(), currentCallee); if (useSameScript && (currentCallee->hasScript() != fun->hasScript() || currentCallee->nonLazyScript() != fun->nonLazyScript())) { return false; } // If none of the previous filters worked, then take the risk of // invalidating the frame to identify the JSFunction. return callee(cx) == fun; }