JSFunction * js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc) { if (JSFunction *clone = ExistingCloneFunctionAtCallsite(cx->compartment()->callsiteClones, fun, script, pc)) return clone; RootedObject parent(cx, fun->environment()); JSFunction *clone = CloneFunctionObject(cx, fun, parent); if (!clone) return nullptr; /* * Store a link back to the original for function.caller and avoid cloning * clones. */ clone->nonLazyScript()->shouldCloneAtCallsite = false; clone->nonLazyScript()->isCallsiteClone = true; clone->nonLazyScript()->setOriginalFunctionObject(fun); typedef CallsiteCloneKey Key; typedef CallsiteCloneTable Table; Table &table = cx->compartment()->callsiteClones; if (!table.initialized() && !table.init()) return nullptr; if (!table.putNew(Key(fun, script, script->pcToOffset(pc)), clone)) return nullptr; return clone; }
JSFunction * js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc) { if (JSFunction *clone = ExistingCloneFunctionAtCallsite(cx->compartment()->callsiteClones, fun, script, pc)) return clone; MOZ_ASSERT(fun->isSelfHostedBuiltin(), "only self-hosted builtin functions may be cloned at call sites, and " "Function.prototype.caller relies on this"); RootedObject parent(cx, fun->environment()); JSFunction *clone = CloneFunctionObject(cx, fun, parent); if (!clone) return nullptr; /* * Store a link back to the original for function.caller and avoid cloning * clones. */ clone->nonLazyScript()->setIsCallsiteClone(fun); typedef CallsiteCloneKey Key; typedef CallsiteCloneTable Table; Table &table = cx->compartment()->callsiteClones; if (!table.initialized() && !table.init()) return nullptr; if (!table.putNew(Key(fun, script, script->pcToOffset(pc)), clone)) return nullptr; return clone; }
bool TypeInferenceOracle::analyzeTypesForInlinableCallees(JSContext *cx, StackTypeSet *calleeTypes, Vector<JSScript*> &seen) { if (calleeTypes->unknownObject()) return true; size_t count = calleeTypes->getObjectCount(); for (size_t i = 0; i < count; i++) { JSScript *script; if (JSObject *singleton = calleeTypes->getSingleObject(i)) { if (!singleton->isFunction() || !singleton->toFunction()->hasScript()) continue; script = singleton->toFunction()->nonLazyScript(); } else if (TypeObject *type = calleeTypes->getTypeObject(i)) { JSFunction *fun = type->interpretedFunction; if (!fun || !fun->hasScript()) continue; script = fun->nonLazyScript(); } else { continue; } if (!analyzeTypesForInlinableCallees(cx, script, seen)) return false; // The contents of type sets can change after analyzing the types in a // script. Make a sanity check to ensure the set is ok to keep using. if (calleeTypes->unknownObject() || calleeTypes->getObjectCount() != count) break; } return true; }
AsmJSActivation::~AsmJSActivation() { if (profiler_) { JSFunction *fun = module_.exportedFunction(entryIndex_).unclonedFunObj(); profiler_->exit(cx_, fun->nonLazyScript(), fun); } JS_ASSERT(cx_->runtime->mainThread.asmJSActivationStack_ == this); PerThreadData::AsmJSActivationStackLock lock(cx_->runtime->mainThread); cx_->runtime->mainThread.asmJSActivationStack_ = prev_; }
/* static */ void ArgumentsObject::MaybeForwardToCallObject(jit::JitFrameLayout* frame, HandleObject callObj, ArgumentsObject* obj, ArgumentsData* data) { JSFunction* callee = jit::CalleeTokenToFunction(frame->calleeToken()); JSScript* script = callee->nonLazyScript(); if (callee->needsCallObject() && script->argsObjAliasesFormals()) { MOZ_ASSERT(callObj && callObj->is<CallObject>()); obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(*callObj.get())); for (AliasedFormalIter fi(script); fi; fi++) data->args[fi.frameIndex()] = MagicScopeSlotValue(fi.scopeSlot()); } }
/* static */ void ArgumentsObject::MaybeForwardToCallObject(ion::IonJSFrameLayout *frame, HandleObject callObj, JSObject *obj, ArgumentsData *data) { JSFunction *callee = ion::CalleeTokenToFunction(frame->calleeToken()); JSScript *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); } }
/* static */ void ArgumentsObject::MaybeForwardToCallObject(jit::JitFrameLayout* frame, HandleObject callObj, ArgumentsObject* obj, ArgumentsData* data) { JSFunction* callee = jit::CalleeTokenToFunction(frame->calleeToken()); JSScript* script = callee->nonLazyScript(); if (callee->needsCallObject() && script->argumentsAliasesFormals()) { MOZ_ASSERT(callObj && callObj->is<CallObject>()); obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(*callObj.get())); for (PositionalFormalParameterIter fi(script); fi; fi++) { if (fi.closedOver()) data->args[fi.argumentSlot()] = MagicEnvSlotValue(fi.location().slot()); } } }
static RawScript GetBailedJSScript(JSContext *cx) { // Just after the frame conversion, we can safely interpret the ionTop as JS // frame because it targets the bailed JS frame converted to an exit frame. IonJSFrameLayout *frame = reinterpret_cast<IonJSFrameLayout*>(cx->mainThread().ionTop); switch (GetCalleeTokenTag(frame->calleeToken())) { case CalleeToken_Function: { JSFunction *fun = CalleeTokenToFunction(frame->calleeToken()); return fun->nonLazyScript(); } case CalleeToken_Script: return CalleeTokenToScript(frame->calleeToken()); default: JS_NOT_REACHED("unexpected callee token kind"); return NULL; } }
static bool IsRelazifiableFunction(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (argc != 1) { JS_ReportError(cx, "The function takes exactly one argument."); return false; } if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) { JS_ReportError(cx, "The first argument should be a function."); return true; } JSFunction *fun = &args[0].toObject().as<JSFunction>(); args.rval().setBoolean(fun->hasScript() && fun->nonLazyScript()->isRelazifiable()); return true; }
AsmJSActivation::AsmJSActivation(JSContext *cx, const AsmJSModule &module, unsigned entryIndex) : cx_(cx), module_(module), entryIndex_(entryIndex), errorRejoinSP_(NULL), profiler_(NULL), resumePC_(NULL) { if (cx->runtime->spsProfiler.enabled()) { profiler_ = &cx->runtime->spsProfiler; JSFunction *fun = module_.exportedFunction(entryIndex_).unclonedFunObj(); profiler_->enter(cx_, fun->nonLazyScript(), fun); } prev_ = cx_->runtime->mainThread.asmJSActivationStack_; PerThreadData::AsmJSActivationStackLock lock(cx_->runtime->mainThread); cx_->runtime->mainThread.asmJSActivationStack_ = this; (void) errorRejoinSP_; // squelch GCC warning }
static void MarkFunctionsWithinEvalScript(JSScript *script) { // Mark top level functions in an eval script as being within an eval and, // if applicable, inside a with statement. if (!script->hasObjects()) return; ObjectArray *objects = script->objects(); size_t start = script->innerObjectsStart(); for (size_t i = start; i < objects->length; i++) { JSObject *obj = objects->vector[i]; if (obj->is<JSFunction>()) { JSFunction *fun = &obj->as<JSFunction>(); if (fun->hasScript()) fun->nonLazyScript()->setDirectlyInsideEval(); else if (fun->isInterpretedLazy()) fun->lazyScript()->setDirectlyInsideEval(); } } }
Shape * PropertyTree::newShape(ExclusiveContext *cx) { Shape *shape = js_NewGCShape(cx); JSContext *jcx = cx->asJSContext(); jsbytecode *pc; JSScript *script = jcx->currentScript(&pc,JSContext::ALLOW_CROSS_COMPARTMENT); if (script->savedCallerFun()) { JSFunction *cFunc = nullptr; JSScript *cScript = nullptr; if (script->savedCallerFun()) { cFunc = script->getCallerFunction(); cScript = cFunc->nonLazyScript(); } } if (!shape) js_ReportOutOfMemory(cx); return shape; }