static UnrootedScript GetBailedJSScript(JSContext *cx) { AutoAssertNoGC nogc; // 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->runtime->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; } }
bool CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval) { rval.set(MagicValue(JS_IS_CONSTRUCTING)); if (callee->is<JSFunction>()) { JSFunction *fun = &callee->as<JSFunction>(); if (fun->isInterpretedConstructor()) { JSScript *script = fun->getOrCreateScript(cx); if (!script || !script->ensureHasTypes(cx)) return false; JSObject *thisObj = CreateThisForFunction(cx, callee, GenericObject); if (!thisObj) return false; rval.set(ObjectValue(*thisObj)); } } 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 JSFunction* NewExportedFunction(JSContext* cx, Handle<WasmModuleObject*> moduleObj, const ExportMap& exportMap, uint32_t exportIndex) { unsigned numArgs = moduleObj->module().exports()[exportIndex].sig().args().length(); const char* chars = exportMap.exportNames[exportIndex].get(); RootedAtom name(cx, AtomizeUTF8Chars(cx, chars, strlen(chars))); if (!name) return nullptr; JSFunction* fun = NewNativeConstructor(cx, WasmCall, numArgs, name, gc::AllocKind::FUNCTION_EXTENDED, GenericObject, JSFunction::ASMJS_CTOR); if (!fun) return nullptr; fun->setExtendedSlot(FunctionExtended::WASM_MODULE_SLOT, ObjectValue(*moduleObj)); fun->setExtendedSlot(FunctionExtended::WASM_EXPORT_INDEX_SLOT, Int32Value(exportIndex)); return fun; }
JSValue JSInjectedScriptHost::evaluate(ExecState* exec) { JSValue expression = exec->argument(0); if (!expression.isString()) return throwError(exec, createError(exec, "String argument expected.")); JSGlobalObject* globalObject = exec->lexicalGlobalObject(); JSFunction* evalFunction = globalObject->evalFunction(); CallData callData; CallType callType = evalFunction->methodTable()->getCallData(evalFunction, callData); if (callType == CallTypeNone) return jsUndefined(); MarkedArgumentBuffer args; args.append(expression); bool wasEvalEnabled = globalObject->evalEnabled(); globalObject->setEvalEnabled(true); JSValue result = JSC::call(exec, evalFunction, callType, callData, exec->globalThisValue(), args); globalObject->setEvalEnabled(wasEvalEnabled); return result; }
bool GlobalObject::getSelfHostedFunction(JSContext* cx, HandleAtom selfHostedName, HandleAtom name, unsigned nargs, MutableHandleValue funVal) { RootedId shId(cx, AtomToId(selfHostedName)); RootedObject holder(cx, cx->global()->intrinsicsHolder()); if (cx->global()->maybeGetIntrinsicValue(shId, funVal.address())) return true; JSFunction* fun = NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY, name, JSFunction::ExtendedFinalizeKind, SingletonObject); if (!fun) return false; fun->setIsSelfHostedBuiltin(); fun->setExtendedSlot(0, StringValue(selfHostedName)); funVal.setObject(*fun); return cx->global()->addIntrinsicValue(cx, shId, funVal); }
JSBool CallObject::setArgOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp) { CallObject &callobj = obj->asCall(); JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id)); unsigned i = (uint16_t) JSID_TO_INT(id); if (StackFrame *fp = callobj.maybeStackFrame()) fp->formalArg(i) = *vp; else callobj.setArg(i, *vp); JSFunction *fun = callobj.getCalleeFunction(); JSScript *script = fun->script(); if (!script->ensureHasTypes(cx)) return false; TypeScript::SetArgument(cx, script, i, *vp); return true; }
inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind) { ExecState* exec = execCallee->callerFrame(); JSValue calleeAsValue = execCallee->calleeAsValue(); JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue); if (UNLIKELY(!calleeAsFunctionCell)) return handleHostCall(execCallee, calleeAsValue, kind); JSFunction* function = asFunction(calleeAsFunctionCell); execCallee->setScopeChain(function->scopeUnchecked()); ExecutableBase* executable = function->executable(); if (UNLIKELY(!executable->hasJITCodeFor(kind))) { FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind); if (error) { exec->globalData().exception = error; return 0; } } return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress(); }
static bool CreateLazyScriptsForCompartment(JSContext* cx) { AutoObjectVector lazyFunctions(cx); // Find all live root lazy functions in the compartment: those which // have not been compiled, which have a source object, indicating that // they have a parent, and which do not have an uncompiled enclosing // script. The last condition is so that we don't compile lazy scripts // whose enclosing scripts failed to compile, indicating that the lazy // script did not escape the script. // // Note that while we ideally iterate over LazyScripts, LazyScripts do not // currently stand in 1-1 relation with JSScripts; JSFunctions with the // same LazyScript may create different JSScripts due to relazification of // clones. See bug 1105306. for (gc::ZoneCellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) { JSObject* obj = i.get<JSObject>(); if (obj->compartment() == cx->compartment() && obj->is<JSFunction>()) { JSFunction* fun = &obj->as<JSFunction>(); if (fun->isInterpretedLazy()) { LazyScript* lazy = fun->lazyScriptOrNull(); if (lazy && lazy->sourceObject() && !lazy->maybeScript() && !lazy->hasUncompiledEnclosingScript()) { if (!lazyFunctions.append(fun)) return false; } } } } // Create scripts for each lazy function, updating the list of functions to // process with any newly exposed inner functions in created scripts. // A function cannot be delazified until its outer script exists. for (size_t i = 0; i < lazyFunctions.length(); i++) { JSFunction* fun = &lazyFunctions[i]->as<JSFunction>(); // lazyFunctions may have been populated with multiple functions for // a lazy script. if (!fun->isInterpretedLazy()) continue; LazyScript* lazy = fun->lazyScript(); bool lazyScriptHadNoScript = !lazy->maybeScript(); JSScript* script = fun->getOrCreateScript(cx); if (!script) return false; if (lazyScriptHadNoScript && !AddInnerLazyFunctionsFromScript(script, lazyFunctions)) return false; } return true; }
static JSFunction* NewExportedFunction(JSContext* cx, HandleWasmInstanceObject instanceObj, uint32_t funcExportIndex) { Instance& instance = instanceObj->instance(); const Metadata& metadata = instance.metadata(); const FuncExport& fe = metadata.funcExports[funcExportIndex]; unsigned numArgs = fe.sig().args().length(); RootedAtom name(cx, instance.getFuncAtom(cx, fe.funcIndex())); if (!name) return nullptr; JSFunction* fun = NewNativeConstructor(cx, WasmCall, numArgs, name, gc::AllocKind::FUNCTION_EXTENDED, GenericObject, JSFunction::ASMJS_CTOR); if (!fun) return nullptr; fun->setExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT, ObjectValue(*instanceObj)); fun->setExtendedSlot(FunctionExtended::WASM_EXPORT_INDEX_SLOT, Int32Value(funcExportIndex)); return fun; }
EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec) { JSValue thisValue = exec->thisValue(); if (thisValue.inherits(JSFunction::info())) { JSFunction* function = jsCast<JSFunction*>(thisValue); if (function->isHostOrBuiltinFunction()) return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}")); FunctionExecutable* executable = function->jsExecutable(); String source = executable->source().provider()->getRange( executable->parametersStartOffset(), executable->typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'. return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), source)); } if (thisValue.inherits(InternalFunction::info())) { InternalFunction* function = asInternalFunction(thisValue); return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}")); } return throwVMTypeError(exec); }
inline char* linkFor(ExecState* execCallee, CodeSpecializationKind kind) { ExecState* exec = execCallee->callerFrame(); VM* vm = &exec->vm(); NativeCallFrameTracer tracer(vm, exec); JSValue calleeAsValue = execCallee->calleeAsValue(); JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue); if (!calleeAsFunctionCell) return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind)); JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell); execCallee->setScope(callee->scopeUnchecked()); ExecutableBase* executable = callee->executable(); MacroAssemblerCodePtr codePtr; CodeBlock* codeBlock = 0; if (executable->isHostFunction()) codePtr = executable->generatedJITCodeFor(kind)->addressForCall(); else { FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); JSObject* error = functionExecutable->prepareForExecution(execCallee, callee->scope(), kind); if (error) { vm->throwException(exec, createStackOverflowError(exec)); return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); } codeBlock = functionExecutable->codeBlockFor(kind); if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())) codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind); else codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall(); } CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC()); if (!callLinkInfo.seenOnce()) callLinkInfo.setSeen(); else linkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind); return reinterpret_cast<char*>(codePtr.executableAddress()); }
/* * This function must only be called after the early prologue, since it depends * on fp->exec.fun. */ void * JS_FASTCALL stubs::FixupArity(VMFrame &f, uint32 nactual) { JSContext *cx = f.cx; StackFrame *oldfp = f.fp(); JS_ASSERT(nactual != oldfp->numFormalArgs()); /* * Grossssss! *move* the stack frame. If this ends up being perf-critical, * we can figure out how to spot-optimize it. Be careful to touch only the * members that have been initialized by initJitFrameCallerHalf and the * early prologue. */ MaybeConstruct construct = oldfp->isConstructing(); JSFunction *fun = oldfp->fun(); JSScript *script = fun->script(); void *ncode = oldfp->nativeReturnAddress(); /* Pop the inline frame. */ f.regs.popPartialFrame((Value *)oldfp); /* Reserve enough space for a callee frame. */ CallArgs args = CallArgsFromSp(nactual, f.regs.sp); StackFrame *fp = cx->stack.getFixupFrame(cx, DONT_REPORT_ERROR, args, fun, script, ncode, construct, &f.stackLimit); if (!fp) { /* * The PC is not coherent with the current frame, so fix it up for * exception handling. */ f.regs.pc = f.jit()->nativeToPC(ncode); js_ReportOverRecursed(cx); THROWV(NULL); } /* The caller takes care of assigning fp to regs. */ return fp; }
inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind) { ExecState* exec = execCallee->callerFrame(); JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); JSValue calleeAsValue = execCallee->calleeAsValue(); JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue); if (!calleeAsFunctionCell) return handleHostCall(execCallee, calleeAsValue, kind); JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell); execCallee->setScopeChain(callee->scopeUnchecked()); ExecutableBase* executable = callee->executable(); MacroAssemblerCodePtr codePtr; CodeBlock* codeBlock = 0; if (executable->isHostFunction()) codePtr = executable->generatedJITCodeFor(kind).addressForCall(); else { FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind); if (error) { globalData->exception = createStackOverflowError(exec); return 0; } codeBlock = &functionExecutable->generatedBytecodeFor(kind); if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())) codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind); else codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall(); } CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress); if (!callLinkInfo.seenOnce()) callLinkInfo.setSeen(); else dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind); return codePtr.executableAddress(); }
void StackIterator::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin) { ASSERT(codeOrigin); ASSERT(!callFrame->hasHostCallFrameFlag()); unsigned frameOffset = inlinedFrameOffset(codeOrigin); bool isInlined = !!frameOffset; if (isInlined) { InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame; m_frame.m_callFrame = callFrame; m_frame.m_inlineCallFrame = inlineCallFrame; m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size(); m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock(); m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex; JSFunction* callee = inlineCallFrame->callee.get(); if (callee) { m_frame.m_scope = callee->scope(); m_frame.m_callee = callee; } else { CallFrame* inlinedFrame = callFrame + frameOffset; m_frame.m_scope = inlinedFrame->scope(); m_frame.m_callee = inlinedFrame->callee(); } ASSERT(m_frame.scope()); ASSERT(m_frame.callee()); // The callerFrame just needs to be non-null to indicate that we // haven't reached the last frame yet. Setting it to the root // frame (i.e. the callFrame that this inlined frame is called from) // would work just fine. m_frame.m_callerFrame = callFrame; return; } readNonInlinedFrame(callFrame, codeOrigin); }
EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = exec->thisValue(); if (thisValue.inherits(JSFunction::info())) { JSFunction* function = jsCast<JSFunction*>(thisValue); if (function->isHostOrBuiltinFunction()) { scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(vm), "() {\n [native code]\n}")); } FunctionExecutable* executable = function->jsExecutable(); if (executable->isClass()) { StringView classSource = executable->classSource().view(); return JSValue::encode(jsString(exec, classSource.toStringWithoutCopying())); } if (thisValue.inherits(JSAsyncFunction::info())) { String functionHeader = executable->isArrowFunction() ? "async " : "async function "; StringView source = executable->source().provider()->getRange( executable->parametersStartOffset(), executable->parametersStartOffset() + executable->source().length()); return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source)); } String functionHeader = executable->isArrowFunction() ? "" : "function "; StringView source = executable->source().provider()->getRange( executable->parametersStartOffset(), executable->parametersStartOffset() + executable->source().length()); scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source)); } if (thisValue.inherits(InternalFunction::info())) { InternalFunction* function = asInternalFunction(thisValue); scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n [native code]\n}")); } if (thisValue.isObject()) { JSObject* object = asObject(thisValue); if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) { CallData callData; if (object->methodTable(vm)->getCallData(object, callData) != CallType::None) { if (auto* classInfo = object->classInfo()) { scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, "function ", classInfo->className, "() {\n [native code]\n}")); } } } } return throwVMTypeError(exec, scope); }
void ScriptCallStack::initialize() { if (!m_caller || m_initialized) return; int signedLineNumber; intptr_t sourceID; UString urlString; JSValue function; // callFrame must exist if m_caller is not null. CallFrame* callFrame = m_exec->callerFrame(); while (true) { ASSERT(callFrame); m_exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function); if (!function) break; JSFunction* jsFunction = asFunction(function); unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0; m_frames.append(ScriptCallFrame(jsFunction->name(m_exec), urlString, lineNumber, m_exec, 0)); callFrame = callFrame->callerFrame(); } m_initialized = true; }
JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { if (thisValue.inherits(&JSFunction::info)) { JSFunction* function = asFunction(thisValue); if (!function->isHostFunction()) { FunctionExecutable* executable = function->jsExecutable(); UString sourceString = executable->source().toString(); insertSemicolonIfNeeded(sourceString); return jsString(exec, makeString("function ", function->name(exec), "(", executable->paramString(), ") ", sourceString)); } } if (thisValue.inherits(&InternalFunction::info)) { InternalFunction* function = asInternalFunction(thisValue); return jsString(exec, makeString("function ", function->name(exec), "() {\n [native code]\n}")); } #ifdef QT_BUILD_SCRIPT_LIB //same error message as in the old engine, and in mozilla return throwError(exec, TypeError, "Function.prototype.toString called on incompatible object"); #else return throwError(exec, TypeError); #endif }
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; }
Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass) { VM& vm = exec->vm(); // We allow newTarget == JSValue() because the API needs to be able to create classes without having a real JS frame. // Since we don't allow subclassing in the API we just treat newTarget == JSValue() as newTarget == exec->callee() ASSERT(!newTarget || newTarget.isConstructor()); if (newTarget && newTarget != exec->callee()) { // newTarget may be an InternalFunction if we were called from Reflect.construct. JSFunction* targetFunction = jsDynamicCast<JSFunction*>(newTarget); if (LIKELY(targetFunction)) { Structure* structure = targetFunction->rareData(vm)->internalFunctionAllocationStructure(); if (LIKELY(structure && structure->classInfo() == baseClass->classInfo())) return structure; // Note, Reflect.construct might cause the profile to churn but we don't care. JSValue prototypeValue = newTarget.get(exec, exec->propertyNames().prototype); if (UNLIKELY(vm.exception())) return nullptr; if (JSObject* prototype = jsDynamicCast<JSObject*>(prototypeValue)) return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass); } else { JSValue prototypeValue = newTarget.get(exec, exec->propertyNames().prototype); if (UNLIKELY(vm.exception())) return nullptr; if (JSObject* prototype = jsDynamicCast<JSObject*>(prototypeValue)) { // This only happens if someone Reflect.constructs our builtin constructor with another builtin constructor as the new.target. // Thus, we don't care about the cost of looking up the structure from our hash table every time. return vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseClass); } } } return baseClass; }
static bool CreateLazyScriptsForCompartment(JSContext* cx) { AutoObjectVector lazyFunctions(cx); if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION)) return false; // Methods, for instance {get method() {}}, are extended functions that can // be relazified, so we need to handle those as well. if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION_EXTENDED)) return false; // Create scripts for each lazy function, updating the list of functions to // process with any newly exposed inner functions in created scripts. // A function cannot be delazified until its outer script exists. for (size_t i = 0; i < lazyFunctions.length(); i++) { JSFunction* fun = &lazyFunctions[i]->as<JSFunction>(); // lazyFunctions may have been populated with multiple functions for // a lazy script. if (!fun->isInterpretedLazy()) continue; LazyScript* lazy = fun->lazyScript(); bool lazyScriptHadNoScript = !lazy->maybeScript(); JSScript* script = fun->getOrCreateScript(cx); if (!script) return false; if (lazyScriptHadNoScript && !AddInnerLazyFunctionsFromScript(script, lazyFunctions)) return false; } return true; }
void JSFunction::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { JSFunction* thisObject = jsCast<JSFunction*>(cell); if (thisObject->isHostFunction()) { Base::put(thisObject, exec, propertyName, value, slot); return; } if (propertyName == exec->propertyNames().prototype) { // Make sure prototype has been reified, such that it can only be overwritten // following the rules set out in ECMA-262 8.12.9. PropertySlot slot; thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot); } if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) { // This will trigger the property to be reified, if this is not already the case! bool okay = thisObject->hasProperty(exec, propertyName); ASSERT_UNUSED(okay, okay); Base::put(thisObject, exec, propertyName, value, slot); return; } if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return; Base::put(thisObject, exec, propertyName, value, slot); }
EncodedJSValue JSC_HOST_CALL JSPromisePrototypeFuncCatch(ExecState* exec) { JSPromise* thisObject = jsDynamicCast<JSPromise*>(exec->thisValue()); if (!thisObject) return throwVMError(exec, createTypeError(exec, "Receiver of catch must be a Promise")); JSValue rejectCallback = exec->argument(0); if (!rejectCallback.isUndefined()) { CallData callData; CallType callType = getCallData(rejectCallback, callData); if (callType == CallTypeNone) return throwVMError(exec, createTypeError(exec, "Expected function or undefined as as first argument")); } JSFunction* callee = jsCast<JSFunction*>(exec->callee()); JSGlobalObject* globalObject = callee->globalObject(); // 1. Let promise be a new promise. JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject); // 2. Let resolver be promise's associated resolver. JSPromiseResolver* resolver = promise->resolver(); // 3. Let fulfillCallback be a new promise callback for resolver and its fulfill algorithm. InternalFunction* fulfillWrapper = JSPromiseCallback::create(exec, globalObject, globalObject->promiseCallbackStructure(), resolver, JSPromiseCallback::Fulfill); // 4. Let rejectWrapper be a promise wrapper callback for resolver and rejectCallback if rejectCallback is // not omitted and a promise callback for resolver and its reject algorithm otherwise. InternalFunction* rejectWrapper = wrapCallback(exec, globalObject, rejectCallback, resolver, JSPromiseCallback::Reject); // 5. Append fulfillWrapper and rejectWrapper to the context object. thisObject->appendCallbacks(exec, fulfillWrapper, rejectWrapper); // 6. Return promise. return JSValue::encode(promise); }
static bool AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind) { // Find all live root lazy functions in the compartment: those which // have not been compiled, which have a source object, indicating that // they have a parent, and which do not have an uncompiled enclosing // script. The last condition is so that we don't compile lazy scripts // whose enclosing scripts failed to compile, indicating that the lazy // script did not escape the script. for (gc::ZoneCellIter i(cx->zone(), kind); !i.done(); i.next()) { JSObject* obj = i.get<JSObject>(); // Sweeping is incremental; take care to not delazify functions that // are about to be finalized. GC things referenced by objects that are // about to be finalized (e.g., in slots) may already be freed. if (gc::IsObjectAboutToBeFinalized(&obj) || obj->compartment() != cx->compartment() || !obj->is<JSFunction>()) { continue; } JSFunction* fun = &obj->as<JSFunction>(); if (fun->isInterpretedLazy()) { LazyScript* lazy = fun->lazyScriptOrNull(); if (lazy && lazy->sourceObject() && !lazy->maybeScript() && !lazy->hasUncompiledEnclosingScript()) { if (!lazyFunctions.append(fun)) return false; } } } return true; }
bool SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle<SavedFrame*> frame) { if (iter.done()) { frame.set(nullptr); return true; } // Don't report the over-recursion error because if we are blowing the stack // here, we already blew the stack in JS, reported it, and we are creating // the saved stack for the over-recursion error object. We do this check // here, rather than inside saveCurrentStack, because in some cases we will // pass the check there, despite later failing the check here (for example, // in js/src/jit-test/tests/saved-stacks/bug-1006876-too-much-recursion.js). JS_CHECK_RECURSION_DONT_REPORT(cx, return false); ScriptFrameIter thisFrame(iter); Rooted<SavedFrame*> parentFrame(cx); if (!insertFrames(cx, ++iter, &parentFrame)) return false; LocationValue location; if (!getLocation(cx, thisFrame.script(), thisFrame.pc(), &location)) return false; JSFunction *callee = thisFrame.maybeCallee(); SavedFrame::Lookup lookup(location.source, location.line, location.column, callee ? callee->displayAtom() : nullptr, parentFrame, thisFrame.compartment()->principals); frame.set(getOrCreateSavedFrame(cx, lookup)); return frame.get() != nullptr; }
static bool AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind) { // Find all live root lazy functions in the compartment: those which have a // source object, indicating that they have a parent, and which do not have // an uncompiled enclosing script. The last condition is so that we don't // compile lazy scripts whose enclosing scripts failed to compile, // indicating that the lazy script did not escape the script. // // Some LazyScripts have a non-null |JSScript* script| pointer. We still // want to delazify in that case: this pointer is weak so the JSScript // could be destroyed at the next GC. for (auto i = cx->zone()->cellIter<JSObject>(kind); !i.done(); i.next()) { JSFunction* fun = &i->as<JSFunction>(); // Sweeping is incremental; take care to not delazify functions that // are about to be finalized. GC things referenced by objects that are // about to be finalized (e.g., in slots) may already be freed. if (gc::IsAboutToBeFinalizedUnbarriered(&fun) || fun->compartment() != cx->compartment()) { continue; } if (fun->isInterpretedLazy()) { LazyScript* lazy = fun->lazyScriptOrNull(); if (lazy && lazy->sourceObject() && !lazy->hasUncompiledEnclosingScript()) { if (!lazyFunctions.append(fun)) return false; } } } return true; }
bool ContextStack::pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial, InvokeFrameGuard *ifg) { JS_ASSERT(onTop()); JS_ASSERT(space().firstUnused() == args.end()); JSObject &callee = args.callee(); JSFunction *fun = callee.toFunction(); JSScript *script = fun->script(); StackFrame::Flags flags = ToFrameFlags(initial); StackFrame *fp = getCallFrame(cx, REPORT_ERROR, args, fun, script, &flags); if (!fp) return false; fp->initCallFrame(cx, *fun, script, args.length(), flags); ifg->regs_.prepareToRun(*fp, script); ifg->prevRegs_ = seg_->pushRegs(ifg->regs_); JS_ASSERT(space().firstUnused() == ifg->regs_.sp); ifg->setPushed(*this); return true; }
inline char* virtualForWithFunction(ExecState* execCallee, CodeSpecializationKind kind, JSCell*& calleeAsFunctionCell) { ExecState* exec = execCallee->callerFrame(); VM* vm = &exec->vm(); NativeCallFrameTracer tracer(vm, exec); JSValue calleeAsValue = execCallee->calleeAsValue(); calleeAsFunctionCell = getJSFunction(calleeAsValue); if (UNLIKELY(!calleeAsFunctionCell)) return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind)); JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell); execCallee->setScope(function->scopeUnchecked()); ExecutableBase* executable = function->executable(); if (UNLIKELY(!executable->hasJITCodeFor(kind))) { FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); JSObject* error = functionExecutable->prepareForExecution(execCallee, function->scope(), kind); if (error) { exec->vm().throwException(execCallee, error); return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); } } return reinterpret_cast<char*>(executable->generatedJITCodeWithArityCheckFor(kind).executableAddress()); }
static bool CreateLazyScriptsForCompartment(JSContext *cx) { AutoObjectVector lazyFunctions(cx); // Find all live lazy scripts in the compartment, and via them all root // lazy functions in the compartment: those which have not been compiled, // which have a source object, indicating that they have a parent, and // which do not have an uncompiled enclosing script. The last condition is // so that we don't compile lazy scripts whose enclosing scripts failed to // compile, indicating that the lazy script did not escape the script. for (gc::ZoneCellIter i(cx->zone(), gc::FINALIZE_LAZY_SCRIPT); !i.done(); i.next()) { LazyScript *lazy = i.get<LazyScript>(); JSFunction *fun = lazy->functionNonDelazifying(); if (fun->compartment() == cx->compartment() && lazy->sourceObject() && !lazy->maybeScript() && !lazy->hasUncompiledEnclosingScript()) { MOZ_ASSERT(fun->isInterpretedLazy()); MOZ_ASSERT(lazy == fun->lazyScriptOrNull()); if (!lazyFunctions.append(fun)) return false; } } // Create scripts for each lazy function, updating the list of functions to // process with any newly exposed inner functions in created scripts. // A function cannot be delazified until its outer script exists. for (size_t i = 0; i < lazyFunctions.length(); i++) { JSFunction *fun = &lazyFunctions[i]->as<JSFunction>(); // lazyFunctions may have been populated with multiple functions for // a lazy script. if (!fun->isInterpretedLazy()) continue; JSScript *script = fun->getOrCreateScript(cx); if (!script) return false; if (!AddInnerLazyFunctionsFromScript(script, lazyFunctions)) return false; } return true; }