bool TypeInferenceOracle::propertyReadIdempotent(HandleScript script, jsbytecode *pc, HandleId id) { if (script->analysis()->getCode(pc).notIdempotent) return false; if (id != MakeTypeId(cx, id)) return false; StackTypeSet *types = script->analysis()->poppedTypes(pc, 0); if (!types || types->unknownObject()) return false; for (unsigned i = 0; i < types->getObjectCount(); i++) { if (types->getSingleObject(i)) return false; if (TypeObject *obj = types->getTypeObject(i)) { if (obj->unknownProperties()) return false; // Check if the property has been reconfigured or is a getter. HeapTypeSet *propertyTypes = obj->getProperty(cx, id, false); if (!propertyTypes || propertyTypes->isOwnProperty(cx, obj, true)) return false; } } return true; }
void beginCompile(HandleScript script) { if (!active[SpewCompile]) return; spew(SpewCompile, "COMPILE %p:%s:%u", script.get(), script->filename(), script->lineno); depth++; }
static bool FilterContainsLocation(HandleScript function) { static const char *filter = getenv("IONFILTER"); // If there is no filter we accept all outputs. if (!filter || !filter[0]) return true; // Disable asm.js output when filter is set. if (!function) return false; const char *filename = function->filename(); const size_t line = function->lineno(); const size_t filelen = strlen(filename); const char *index = strstr(filter, filename); while (index) { if (index == filter || index[-1] == ',') { if (index[filelen] == 0 || index[filelen] == ',') return true; if (index[filelen] == ':' && line != size_t(-1)) { size_t read_line = strtoul(&index[filelen + 1], nullptr, 10); if (read_line == line) return true; } } index = strstr(index + filelen, filename); } return false; }
bool TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc) { JS_ASSERT(types::IsInlinableCall(pc)); Bytecode *code = caller->analysis()->maybeCode(pc); if (code->monitoredTypes || code->monitoredTypesReturn || caller->analysis()->typeBarriers(cx, pc)) return false; return true; }
JS_DumpPCCounts(JSContext *cx, HandleScript script) { JS_ASSERT(script->hasScriptCounts()); Sprinter sprinter(cx); if (!sprinter.init()) return; fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename(), (int) script->lineno()); js_DumpPCCounts(cx, script, &sprinter); fputs(sprinter.string(), stdout); fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename(), (int) script->lineno()); }
static bool MaybeCheckEvalFreeVariables(ExclusiveContext *cxArg, HandleScript evalCaller, HandleObject scopeChain, Parser<FullParseHandler> &parser, ParseContext<FullParseHandler> &pc) { if (!evalCaller || !evalCaller->functionOrCallerFunction()) return true; // Eval scripts are only compiled on the main thread. JSContext *cx = cxArg->asJSContext(); // Watch for uses of 'arguments' within the evaluated script, both as // free variables and as variables redeclared with 'var'. RootedFunction fun(cx, evalCaller->functionOrCallerFunction()); HandlePropertyName arguments = cx->names().arguments; for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) { if (r.front().key() == arguments) { if (!CheckArgumentsWithinEval(cx, parser, fun)) return false; } } for (AtomDefnListMap::Range r = pc.decls().all(); !r.empty(); r.popFront()) { if (r.front().key() == arguments) { if (!CheckArgumentsWithinEval(cx, parser, fun)) return false; } } // If the eval'ed script contains any debugger statement, force construction // of arguments objects for the caller script and any other scripts it is // transitively nested inside. The debugger can access any variable on the // scope chain. if (pc.sc->hasDebuggerStatement()) { RootedObject scope(cx, scopeChain); while (scope->is<ScopeObject>() || scope->is<DebugScopeObject>()) { if (scope->is<CallObject>() && !scope->as<CallObject>().isForEval()) { RootedScript script(cx, scope->as<CallObject>().callee().getOrCreateScript(cx)); if (!script) return false; if (script->argumentsHasVarBinding()) { if (!JSScript::argumentsOptimizationFailed(cx, script)) return false; } } scope = scope->enclosingScope(); } } return true; }
bool TypeInferenceOracle::elementReadIsTypedArray(HandleScript script, jsbytecode *pc, int *arrayType) { // Check whether the object is a typed array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 1); StackTypeSet *id = DropUnrooted(script)->analysis()->poppedTypes(pc, 0); JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; *arrayType = obj->getTypedArrayType(); if (*arrayType == TypedArray::TYPE_MAX) return false; JS_ASSERT(*arrayType >= 0 && *arrayType < TypedArray::TYPE_MAX); // Unlike dense arrays, the types of elements in typed arrays are not // guaranteed to be present in the object's type, and we need to use // knowledge about the possible contents of the array vs. the types // that have been read out of it to figure out how to do the load. types::TypeSet *result = propertyRead(script, pc); if (*arrayType == TypedArray::TYPE_FLOAT32 || *arrayType == TypedArray::TYPE_FLOAT64) { if (!result->hasType(types::Type::DoubleType())) return false; } else { if (!result->hasType(types::Type::Int32Type())) return false; } return true; }
bool TypeInferenceOracle::inObjectIsDenseNativeWithoutExtraIndexedProperties(HandleScript script, jsbytecode *pc) { // Check whether the object is a native and index is int32 or double. StackTypeSet *id = script->analysis()->poppedTypes(pc, 1); StackTypeSet *obj = script->analysis()->poppedTypes(pc, 0); JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; Class *clasp = obj->getKnownClass(); if (!clasp || !clasp->isNative()) return false; return !types::TypeCanHaveExtraIndexedProperties(cx, obj); }
bool TypeInferenceOracle::elementWriteIsDenseArray(HandleScript script, jsbytecode *pc) { // Check whether the object is a dense array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2); StackTypeSet *id = script->analysis()->poppedTypes(pc, 1); JSValueType objType = obj->getKnownTypeTag(); if (objType != JSVAL_TYPE_OBJECT) return false; JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY); }
bool TypeInferenceOracle::elementWriteIsDenseNative(HandleScript script, jsbytecode *pc) { // Check whether the object is a dense array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2); StackTypeSet *id = script->analysis()->poppedTypes(pc, 1); JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; Class *clasp = obj->getKnownClass(); if (!clasp || !clasp->isNative()) return false; return obj->convertDoubleElements(cx) != StackTypeSet::AmbiguousDoubleConversion; }
JS_SetSingleStepMode(JSContext *cx, HandleScript script, bool singleStep) { assertSameCompartment(cx, script); if (!CheckDebugMode(cx)) return false; return script->setStepModeFlag(cx, singleStep); }
void C1Spewer::beginFunction(MIRGraph *graph, HandleScript script) { if (!spewout_) return; this->graph = graph; fprintf(spewout_, "begin_compilation\n"); if (script) { fprintf(spewout_, " name \"%s:%d\"\n", script->filename(), (int)script->lineno()); fprintf(spewout_, " method \"%s:%d\"\n", script->filename(), (int)script->lineno()); } else { fprintf(spewout_, " name \"asm.js compilation\"\n"); fprintf(spewout_, " method \"asm.js compilation\"\n"); } fprintf(spewout_, " date %d\n", (int)time(nullptr)); fprintf(spewout_, "end_compilation\n"); }
bool TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc) { JS_ASSERT(types::IsInlinableCall(pc)); JSOp op = JSOp(*pc); Bytecode *code = caller->analysis()->maybeCode(pc); // For foo.apply(this, arguments), the caller is foo and not the js_fun_apply function. // Ignore code->monitoredTypes, as we know the caller is foo if (op != JSOP_FUNAPPLY && code->monitoredTypes) return false; // Gets removed in Bug 796114 if (caller->analysis()->typeBarriers(cx, pc)) return false; return true; }
JS_SetTrap(JSContext *cx, HandleScript script, jsbytecode *pc, JSTrapHandler handler, HandleValue closure) { assertSameCompartment(cx, script, closure); if (!CheckDebugMode(cx)) return false; BreakpointSite *site = script->getOrCreateBreakpointSite(cx, pc); if (!site) return false; site->setTrap(cx->runtime()->defaultFreeOp(), handler, closure); return true; }
js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScript scriptArg, MutableHandleObject scopeArg) { CHECK_REQUEST(cx); assertSameCompartment(cx, global); MOZ_ASSERT(global->is<GlobalObject>()); MOZ_RELEASE_ASSERT(scriptArg->hasNonSyntacticScope()); RootedScript script(cx, scriptArg); Rooted<GlobalObject*> globalRoot(cx, &global->as<GlobalObject>()); if (script->compartment() != cx->compartment()) { Rooted<StaticScope*> staticScope(cx, &globalRoot->lexicalScope().staticBlock()); staticScope = StaticNonSyntacticScope::create(cx, staticScope); if (!staticScope) return false; script = CloneGlobalScript(cx, staticScope, script); if (!script) return false; Debugger::onNewScript(cx, script); } Rooted<ClonedBlockObject*> globalLexical(cx, &globalRoot->lexicalScope()); Rooted<ScopeObject*> scope(cx, NonSyntacticVariablesObject::create(cx, globalLexical)); if (!scope) return false; // Unlike the non-syntactic scope chain API used by the subscript loader, // this API creates a fresh block scope each time. Rooted<StaticNonSyntacticScope*> enclosingStaticScope(cx, &script->enclosingStaticScope()->as<StaticNonSyntacticScope>()); scope = ClonedBlockObject::createNonSyntactic(cx, enclosingStaticScope, scope); if (!scope) return false; RootedValue rval(cx); if (!ExecuteKernel(cx, script, *scope, UndefinedValue(), NullFramePtr() /* evalInFrame */, rval.address())) { return false; } scopeArg.set(scope); return true; }
BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, TempAllocator &alloc, HandleScript script) : cx(cx), script(cx, script), pc(script->code()), ionCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, false)), ionOSRCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, true)), debugMode_(cx->compartment()->debugMode()), alloc_(alloc), analysis_(alloc, script), frame(cx, script, masm), stubSpace_(), icEntries_(), pcMappingEntries_(), icLoadLabels_(), pushedBeforeCall_(0), inCall_(false), spsPushToggleOffset_() { }
void jit::IonSpewNewFunction(MIRGraph *graph, HandleScript func) { if (GetIonContext()->runtime->onMainThread()) { ionspewer.beginFunction(graph, func); return; } if (!IonSpewEnabled(IonSpew_Logs)) return; // Ionspewer isn't threads-safe. Therefore logging is disabled for // off-thread spewing. Throw informative message when trying. if (func) { IonSpew(IonSpew_Logs, "Can't log script %s:%d. (Compiled on background thread.)", func->filename(), func->lineno); } else { IonSpew(IonSpew_Logs, "Can't log asm.js compilation. (Compiled on background thread.)"); } }
js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScript scriptArg, MutableHandleObject scopeArg) { CHECK_REQUEST(cx); assertSameCompartment(cx, global); MOZ_ASSERT(global->is<GlobalObject>()); MOZ_RELEASE_ASSERT(scriptArg->hasNonSyntacticScope()); RootedScript script(cx, scriptArg); if (script->compartment() != cx->compartment()) { Rooted<ScopeObject*> staticScope(cx, StaticNonSyntacticScopeObjects::create(cx, nullptr)); if (!staticScope) return false; script = CloneGlobalScript(cx, staticScope, script); if (!script) return false; Debugger::onNewScript(cx, script); } Rooted<GlobalObject*> globalRoot(cx, &global->as<GlobalObject>()); Rooted<ScopeObject*> scope(cx, NonSyntacticVariablesObject::create(cx, globalRoot)); if (!scope) return false; JSObject* thisobj = GetThisObject(cx, global); if (!thisobj) return false; RootedValue thisv(cx, ObjectValue(*thisobj)); RootedValue rval(cx); if (!ExecuteKernel(cx, script, *scope, thisv, UndefinedValue(), EXECUTE_GLOBAL, NullFramePtr() /* evalInFrame */, rval.address())) { return false; } scopeArg.set(scope); return true; }
RawScript frontend::CompileScript(JSContext *cx, HandleObject scopeChain, HandleScript evalCaller, const CompileOptions &options, const jschar *chars, size_t length, JSString *source_ /* = NULL */, unsigned staticLevel /* = 0 */, SourceCompressionToken *extraSct /* = NULL */) { RootedString source(cx, source_); /* * The scripted callerFrame can only be given for compile-and-go scripts * and non-zero static level requires callerFrame. */ JS_ASSERT_IF(evalCaller, options.compileAndGo); JS_ASSERT_IF(staticLevel != 0, evalCaller); if (!CheckLength(cx, length)) return NULL; JS_ASSERT_IF(staticLevel != 0, options.sourcePolicy != CompileOptions::LAZY_SOURCE); ScriptSource *ss = cx->new_<ScriptSource>(); if (!ss) return NULL; if (options.filename && !ss->setFilename(cx, options.filename)) return NULL; ScriptSourceHolder ssh(ss); SourceCompressionToken mysct(cx); SourceCompressionToken *sct = (extraSct) ? extraSct : &mysct; switch (options.sourcePolicy) { case CompileOptions::SAVE_SOURCE: if (!ss->setSourceCopy(cx, chars, length, false, sct)) return NULL; break; case CompileOptions::LAZY_SOURCE: ss->setSourceRetrievable(); break; case CompileOptions::NO_SOURCE: break; } Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true); if (!parser.init()) return NULL; parser.sct = sct; GlobalSharedContext globalsc(cx, scopeChain, StrictModeFromContext(cx)); ParseContext<FullParseHandler> pc(&parser, NULL, &globalsc, staticLevel, /* bodyid = */ 0); if (!pc.init()) return NULL; bool savedCallerFun = options.compileAndGo && evalCaller && (evalCaller->function() || evalCaller->savedCallerFun); Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), savedCallerFun, options, staticLevel, ss, 0, length)); if (!script) return NULL; // Global/eval script bindings are always empty (all names are added to the // scope dynamically via JSOP_DEFFUN/VAR). InternalHandle<Bindings*> bindings(script, &script->bindings); if (!Bindings::initWithTemporaryStorage(cx, bindings, 0, 0, NULL)) return NULL; // We can specialize a bit for the given scope chain if that scope chain is the global object. JSObject *globalScope = scopeChain && scopeChain == &scopeChain->global() ? (JSObject*) scopeChain : NULL; JS_ASSERT_IF(globalScope, globalScope->isNative()); JS_ASSERT_IF(globalScope, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalScope->getClass())); BytecodeEmitter bce(/* parent = */ NULL, &parser, &globalsc, script, evalCaller, !!globalScope, options.lineno, options.selfHostingMode); if (!bce.init()) return NULL; /* If this is a direct call to eval, inherit the caller's strictness. */ if (evalCaller && evalCaller->strict) globalsc.strict = true; if (options.compileAndGo) { if (source) { /* * Save eval program source in script->atoms[0] for the * eval cache (see EvalCacheLookup in jsobj.cpp). */ JSAtom *atom = AtomizeString<CanGC>(cx, source); jsatomid _; if (!atom || !bce.makeAtomIndex(atom, &_)) return NULL; } if (evalCaller && evalCaller->functionOrCallerFunction()) { /* * An eval script in a caller frame needs to have its enclosing * function captured in case it refers to an upvar, and someone * wishes to decompile it while it's running. */ JSFunction *fun = evalCaller->functionOrCallerFunction(); ObjectBox *funbox = parser.newFunctionBox(fun, &pc, fun->strict()); if (!funbox) return NULL; bce.objectList.add(funbox); } } bool canHaveDirectives = true; for (;;) { TokenKind tt = parser.tokenStream.peekToken(TSF_OPERAND); if (tt <= TOK_EOF) { if (tt == TOK_EOF) break; JS_ASSERT(tt == TOK_ERROR); return NULL; } ParseNode *pn = parser.statement(); if (!pn) return NULL; if (canHaveDirectives) { if (!parser.maybeParseDirective(pn, &canHaveDirectives)) return NULL; } if (!FoldConstants(cx, &pn, &parser)) return NULL; if (!NameFunctions(cx, pn)) return NULL; if (!EmitTree(cx, &bce, pn)) return NULL; parser.handler.freeTree(pn); } if (!SetSourceMap(cx, parser.tokenStream, ss, script)) return NULL; if (evalCaller && evalCaller->functionOrCallerFunction()) { // Watch for uses of 'arguments' within the evaluated script, both as // free variables and as variables redeclared with 'var'. RootedFunction fun(cx, evalCaller->functionOrCallerFunction()); HandlePropertyName arguments = cx->names().arguments; for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) { if (r.front().key() == arguments) { if (!CheckArgumentsWithinEval(cx, parser, fun)) return NULL; } } for (AtomDefnListMap::Range r = pc.decls().all(); !r.empty(); r.popFront()) { if (r.front().key() == arguments) { if (!CheckArgumentsWithinEval(cx, parser, fun)) return NULL; } } // If the eval'ed script contains any debugger statement, force construction // of arguments objects for the caller script and any other scripts it is // transitively nested inside. if (pc.sc->hasDebuggerStatement()) { RootedObject scope(cx, scopeChain); while (scope->isScope() || scope->isDebugScope()) { if (scope->isCall() && !scope->asCall().isForEval()) { RootedScript script(cx, scope->asCall().callee().nonLazyScript()); if (script->argumentsHasVarBinding()) { if (!JSScript::argumentsOptimizationFailed(cx, script)) return NULL; } } scope = scope->enclosingScope(); } } } /* * Nowadays the threaded interpreter needs a stop instruction, so we * do have to emit that here. */ if (Emit1(cx, &bce, JSOP_STOP) < 0) return NULL; if (!JSScript::fullyInitFromEmitter(cx, script, &bce)) return NULL; bce.tellDebuggerAboutCompiledScript(cx); if (sct == &mysct && !sct->complete()) return NULL; return script; }
void InterpreterFrame::initExecuteFrame(JSContext *cx, HandleScript script, AbstractFramePtr evalInFramePrev, const Value &thisv, HandleObject scopeChain, ExecuteType type) { /* * See encoding of ExecuteType. When GLOBAL isn't set, we are executing a * script in the context of another frame and the frame type is determined * by the context. */ flags_ = type | HAS_SCOPECHAIN; JSObject *callee = nullptr; if (!(flags_ & (GLOBAL))) { if (evalInFramePrev) { MOZ_ASSERT(evalInFramePrev.isFunctionFrame() || evalInFramePrev.isGlobalFrame()); if (evalInFramePrev.isFunctionFrame()) { callee = evalInFramePrev.callee(); flags_ |= FUNCTION; } else { flags_ |= GLOBAL; } } else { FrameIter iter(cx); MOZ_ASSERT(iter.isFunctionFrame() || iter.isGlobalFrame()); MOZ_ASSERT(!iter.isAsmJS()); if (iter.isFunctionFrame()) { callee = iter.callee(cx); flags_ |= FUNCTION; } else { flags_ |= GLOBAL; } } } Value *dstvp = (Value *)this - 2; dstvp[1] = thisv; if (isFunctionFrame()) { dstvp[0] = ObjectValue(*callee); exec.fun = &callee->as<JSFunction>(); u.evalScript = script; } else { MOZ_ASSERT(isGlobalFrame()); dstvp[0] = NullValue(); exec.script = script; #ifdef DEBUG u.evalScript = (JSScript *)0xbad; #endif } scopeChain_ = scopeChain.get(); prev_ = nullptr; prevpc_ = nullptr; prevsp_ = nullptr; MOZ_ASSERT_IF(evalInFramePrev, isDebuggerEvalFrame()); evalInFramePrev_ = evalInFramePrev; if (script->isDebuggee()) setIsDebuggee(); #ifdef DEBUG Debug_SetValueRangeToCrashOnTouch(&rval_, 1); #endif }
bool js::DirectEvalStringFromIon(JSContext* cx, HandleObject scopeobj, HandleScript callerScript, HandleValue thisValue, HandleValue newTargetValue, HandleString str, jsbytecode* pc, MutableHandleValue vp) { AssertInnerizedScopeChain(cx, *scopeobj); Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global()); if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL); return false; } // ES5 15.1.2.1 steps 2-8. unsigned staticLevel = callerScript->staticLevel() + 1; RootedLinearString linearStr(cx, str->ensureLinear(cx)); if (!linearStr) return false; EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp); if (ejr != EvalJSON_NotJSON) return ejr == EvalJSON_Success; EvalScriptGuard esg(cx); esg.lookupInEvalCache(linearStr, callerScript, pc); if (!esg.foundScript()) { RootedScript maybeScript(cx); const char* filename; unsigned lineno; bool mutedErrors; uint32_t pcOffset; DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset, &mutedErrors, CALLED_FROM_JSOP_EVAL); const char* introducerFilename = filename; if (maybeScript && maybeScript->scriptSource()->introducerFilename()) introducerFilename = maybeScript->scriptSource()->introducerFilename(); RootedObject enclosing(cx, callerScript->innermostStaticScope(pc)); Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, enclosing)); if (!staticScope) return false; CompileOptions options(cx); options.setFileAndLine(filename, 1) .setIsRunOnce(true) .setForEval(true) .setNoScriptRval(false) .setMutedErrors(mutedErrors) .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset) .maybeMakeStrictMode(IsStrictEvalPC(pc)); AutoStableStringChars linearChars(cx); if (!linearChars.initTwoByte(cx, linearStr)) return false; const char16_t* chars = linearChars.twoByteRange().start().get(); SourceBufferHolder::Ownership ownership = linearChars.maybeGiveOwnershipToCaller() ? SourceBufferHolder::GiveOwnership : SourceBufferHolder::NoOwnership; SourceBufferHolder srcBuf(chars, linearStr->length(), ownership); JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(), scopeobj, staticScope, callerScript, options, srcBuf, linearStr, staticLevel); if (!compiled) return false; if (compiled->strict()) staticScope->setStrict(); esg.setNewScript(compiled); } // Primitive 'this' values should have been filtered out by Ion. If boxed, // the calling frame cannot be updated to store the new object. MOZ_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull()); // When eval'ing strict code in a non-strict context, compute the 'this' // value to use from what the caller passed in. This isn't necessary if // the callee is not strict, as it will compute the non-strict 'this' // value as necessary while it executes. RootedValue nthisValue(cx, thisValue); if (!callerScript->strict() && esg.script()->strict() && !thisValue.isObject()) { JSObject* obj = BoxNonStrictThis(cx, thisValue); if (!obj) return false; nthisValue = ObjectValue(*obj); } return ExecuteKernel(cx, esg.script(), *scopeobj, nthisValue, newTargetValue, ExecuteType(DIRECT_EVAL), NullFramePtr() /* evalInFrame */, vp.address()); }
bool TypeInferenceOracle::elementWriteIsDenseNative(HandleScript script, jsbytecode *pc) { return elementWriteIsDenseNative(script->analysis()->poppedTypes(pc, 2), script->analysis()->poppedTypes(pc, 1)); }
bool SPSExit(JSContext *cx, HandleScript script) { cx->runtime()->spsProfiler.exit(script, script->functionNonDelazifying()); return true; }
bool SPSExit(JSContext *cx, HandleScript script) { cx->runtime->spsProfiler.exit(cx, script, script->function()); return true; }
bool SPSEnter(JSContext *cx, HandleScript script) { return cx->runtime->spsProfiler.enter(cx, script, script->function()); }
void ModuleObject::init(HandleScript script) { MOZ_ASSERT(!script->enclosingStaticScope()); initReservedSlot(ScriptSlot, PrivateValue(script)); }
bool SPSEnter(JSContext *cx, HandleScript script) { return cx->runtime()->spsProfiler.enter(script, script->functionNonDelazifying()); }
bool js::DirectEvalFromIon(JSContext *cx, HandleObject scopeobj, HandleScript callerScript, HandleValue thisValue, HandleString str, MutableHandleValue vp) { AssertInnerizedScopeChain(cx, *scopeobj); Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global()); if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL); return false; } // ES5 15.1.2.1 steps 2-8. unsigned staticLevel = callerScript->staticLevel + 1; Rooted<JSStableString*> stableStr(cx, str->ensureStable(cx)); if (!stableStr) return false; StableCharPtr chars = stableStr->chars(); size_t length = stableStr->length(); EvalJSONResult ejr = TryEvalJSON(cx, callerScript, chars, length, vp); if (ejr != EvalJSON_NotJSON) return ejr == EvalJSON_Success; EvalScriptGuard esg(cx); // Ion will not perform cross compartment direct eval calls. JSPrincipals *principals = cx->compartment->principals; esg.lookupInEvalCache(stableStr, callerScript->function(), staticLevel); if (!esg.foundScript()) { unsigned lineno; const char *filename; JSPrincipals *originPrincipals; CurrentScriptFileLineOrigin(cx, &filename, &lineno, &originPrincipals, CALLED_FROM_JSOP_EVAL); CompileOptions options(cx); options.setFileAndLine(filename, lineno) .setCompileAndGo(true) .setNoScriptRval(false) .setPrincipals(principals) .setOriginPrincipals(originPrincipals); UnrootedScript compiled = frontend::CompileScript(cx, scopeobj, callerScript, options, chars.get(), length, stableStr, staticLevel); if (!compiled) return false; esg.setNewScript(compiled); } // Primitive 'this' values should have been filtered out by Ion. If boxed, // the calling frame cannot be updated to store the new object. JS_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull()); return ExecuteKernel(cx, esg.script(), *scopeobj, thisValue, ExecuteType(DIRECT_EVAL), NullFramePtr() /* evalInFrame */, vp.address()); }
bool js::DirectEvalStringFromIon(JSContext *cx, HandleObject scopeobj, HandleScript callerScript, HandleValue thisValue, HandleString str, jsbytecode *pc, MutableHandleValue vp) { AssertInnerizedScopeChain(cx, *scopeobj); Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global()); if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL); return false; } // ES5 15.1.2.1 steps 2-8. unsigned staticLevel = callerScript->staticLevel() + 1; Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx)); if (!flatStr) return false; EvalJSONResult ejr = TryEvalJSON(cx, callerScript, flatStr, vp); if (ejr != EvalJSON_NotJSON) return ejr == EvalJSON_Success; EvalScriptGuard esg(cx); esg.lookupInEvalCache(flatStr, callerScript, pc); if (!esg.foundScript()) { RootedScript maybeScript(cx); const char *filename; unsigned lineno; JSPrincipals *originPrincipals; uint32_t pcOffset; DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset, &originPrincipals, CALLED_FROM_JSOP_EVAL); const char *introducerFilename = filename; if (maybeScript && maybeScript->scriptSource()->introducerFilename()) introducerFilename = maybeScript->scriptSource()->introducerFilename(); CompileOptions options(cx); options.setFileAndLine(filename, 1) .setCompileAndGo(true) .setForEval(true) .setNoScriptRval(false) .setOriginPrincipals(originPrincipals) .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset); AutoStableStringChars flatChars(cx); if (!flatChars.initTwoByte(cx, flatStr)) return false; const char16_t *chars = flatChars.twoByteRange().start().get(); SourceBufferHolder::Ownership ownership = flatChars.maybeGiveOwnershipToCaller() ? SourceBufferHolder::GiveOwnership : SourceBufferHolder::NoOwnership; SourceBufferHolder srcBuf(chars, flatStr->length(), ownership); JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(), scopeobj, callerScript, options, srcBuf, flatStr, staticLevel); if (!compiled) return false; esg.setNewScript(compiled); } // Primitive 'this' values should have been filtered out by Ion. If boxed, // the calling frame cannot be updated to store the new object. JS_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull()); return ExecuteKernel(cx, esg.script(), *scopeobj, thisValue, ExecuteType(DIRECT_EVAL), NullFramePtr() /* evalInFrame */, vp.address()); }
bool js::DirectEvalStringFromIon(JSContext* cx, HandleObject scopeObj, HandleScript callerScript, HandleValue newTargetValue, HandleString str, jsbytecode* pc, MutableHandleValue vp) { AssertInnerizedScopeChain(cx, *scopeObj); Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeObj->global()); if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL); return false; } // ES5 15.1.2.1 steps 2-8. RootedLinearString linearStr(cx, str->ensureLinear(cx)); if (!linearStr) return false; EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp); if (ejr != EvalJSON_NotJSON) return ejr == EvalJSON_Success; EvalScriptGuard esg(cx); esg.lookupInEvalCache(linearStr, callerScript, pc); if (!esg.foundScript()) { RootedScript maybeScript(cx); const char* filename; unsigned lineno; bool mutedErrors; uint32_t pcOffset; DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset, &mutedErrors, CALLED_FROM_JSOP_EVAL); const char* introducerFilename = filename; if (maybeScript && maybeScript->scriptSource()->introducerFilename()) introducerFilename = maybeScript->scriptSource()->introducerFilename(); RootedObject enclosing(cx, callerScript->innermostStaticScope(pc)); Rooted<StaticEvalScope*> staticScope(cx, StaticEvalScope::create(cx, enclosing)); if (!staticScope) return false; CompileOptions options(cx); options.setIsRunOnce(true) .setForEval(true) .setNoScriptRval(false) .setMutedErrors(mutedErrors) .maybeMakeStrictMode(IsStrictEvalPC(pc)); if (introducerFilename) { options.setFileAndLine(filename, 1); options.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset); } else { options.setFileAndLine("eval", 1); options.setIntroductionType("eval"); } AutoStableStringChars linearChars(cx); if (!linearChars.initTwoByte(cx, linearStr)) return false; const char16_t* chars = linearChars.twoByteRange().start().get(); SourceBufferHolder::Ownership ownership = linearChars.maybeGiveOwnershipToCaller() ? SourceBufferHolder::GiveOwnership : SourceBufferHolder::NoOwnership; SourceBufferHolder srcBuf(chars, linearStr->length(), ownership); JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(), scopeObj, staticScope, callerScript, options, srcBuf, linearStr); if (!compiled) return false; if (compiled->strict()) staticScope->setStrict(); esg.setNewScript(compiled); } return ExecuteKernel(cx, esg.script(), *scopeObj, newTargetValue, NullFramePtr() /* evalInFrame */, vp.address()); }