void beginCompile(HandleFunction fun) { if (!active[SpewCompile]) return; spew(SpewCompile, "COMPILE %p:%s:%u", fun.get(), fun->nonLazyScript()->filename, fun->nonLazyScript()->lineno); depth++; }
RawFunction js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc) { JS_ASSERT(cx->typeInferenceEnabled()); JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite); JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope()); JS_ASSERT(types::UseNewTypeForClone(fun)); typedef CallsiteCloneKey Key; typedef CallsiteCloneTable Table; Table &table = cx->compartment->callsiteClones; if (!table.initialized() && !table.init()) return NULL; Key key; SkipRoot skipKey(cx, &key); /* Stop the analysis complaining about unrooted key. */ key.script = script; key.offset = pc - script->code; key.original = fun; Table::AddPtr p = table.lookupForAdd(key); SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */ if (p) return p->value; RootedObject parent(cx, fun->environment()); RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent)); if (!clone) return NULL; /* * 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); /* Recalculate the hash if script or fun have been moved. */ if (key.script != script && key.original != fun) { key.script = script; key.original = fun; Table::AddPtr p = table.lookupForAdd(key); JS_ASSERT(!p); } if (!table.relookupOrAdd(p, key, clone.get())) return NULL; return clone; }
static bool CheckArgumentsWithinEval(JSContext *cx, Parser<FullParseHandler> &parser, HandleFunction fun) { if (fun->hasRest()) { // It's an error to use |arguments| in a function that has a rest // parameter. parser.report(ParseError, false, NULL, JSMSG_ARGUMENTS_AND_REST); return false; } // Force construction of arguments objects for functions that use // |arguments| within an eval. RootedScript script(cx, fun->nonLazyScript()); if (script->argumentsHasVarBinding()) { if (!JSScript::argumentsOptimizationFailed(cx, script)) return false; } // It's an error to use |arguments| in a legacy generator expression. if (script->isGeneratorExp && script->isLegacyGenerator) { parser.report(ParseError, false, NULL, JSMSG_BAD_GENEXP_BODY, js_arguments_str); return false; } 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; }
JS_GetFunctionScript(JSContext *cx, HandleFunction fun) { if (fun->isNative()) return nullptr; if (fun->isInterpretedLazy()) { AutoCompartment funCompartment(cx, fun); JSScript *script = fun->getOrCreateScript(cx); if (!script) MOZ_CRASH(); return script; } return fun->nonLazyScript(); }
RawFunction js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc) { JS_ASSERT(cx->typeInferenceEnabled()); JS_ASSERT(fun->isCloneAtCallsite()); JS_ASSERT(types::UseNewTypeForClone(fun)); JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope()); typedef CallsiteCloneKey Key; typedef CallsiteCloneTable Table; Table &table = cx->compartment->callsiteClones; if (!table.initialized() && !table.init()) return NULL; Key key; key.script = script; key.offset = pc - script->code; key.original = fun; Table::AddPtr p = table.lookupForAdd(key); SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */ if (p) return p->value; RootedObject parent(cx, fun->environment()); RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent, JSFunction::ExtendedFinalizeKind)); if (!clone) return NULL; // Store a link back to the original for function.caller. clone->setExtendedSlot(0, ObjectValue(*fun)); // Recalculate the hash if script or fun have been moved. if (key.script != script && key.original != fun) { key.script = script; key.original = fun; Table::AddPtr p = table.lookupForAdd(key); JS_ASSERT(!p); } if (!table.relookupOrAdd(p, key, clone.get())) return NULL; return clone; }
ParallelIonInvoke(JSContext *cx, HandleFunction callee, uint32_t argc) : argc_(argc), args(argv_ + 2) { JS_ASSERT(argc <= maxArgc + 2); // Set 'callee' and 'this'. argv_[0] = ObjectValue(*callee); argv_[1] = UndefinedValue(); // Find JIT code pointer. IonScript *ion = callee->nonLazyScript()->parallelIonScript(); IonCode *code = ion->method(); jitcode_ = code->raw(); enter_ = cx->compartment->ionCompartment()->enterJIT(); calleeToken_ = CalleeToParallelToken(callee); }
static bool CheckArgumentsWithinEval(JSContext *cx, Parser &parser, HandleFunction fun) { if (fun->hasRest()) { // It's an error to use |arguments| in a function that has a rest // parameter. parser.reportError(NULL, JSMSG_ARGUMENTS_AND_REST); return false; } // Force construction of arguments objects for functions that use // |arguments| within an eval. RootedScript script(cx, fun->nonLazyScript()); if (script->argumentsHasVarBinding()) { if (!JSScript::argumentsOptimizationFailed(cx, script)) return false; } return true; }