PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor( CodeSpecializationKind kind) { if (classInfo() == EvalExecutable::info()) { RELEASE_ASSERT(kind == CodeForCall); EvalExecutable* executable = jsCast<EvalExecutable*>(this); EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>( executable->m_evalCodeBlock->baselineVersion()); RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock( CodeBlock::CopyParsedBlock, *baseline)); result->setAlternative(baseline); return result; } if (classInfo() == ProgramExecutable::info()) { RELEASE_ASSERT(kind == CodeForCall); ProgramExecutable* executable = jsCast<ProgramExecutable*>(this); ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>( executable->m_programCodeBlock->baselineVersion()); RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock( CodeBlock::CopyParsedBlock, *baseline)); result->setAlternative(baseline); return result; } RELEASE_ASSERT(classInfo() == FunctionExecutable::info()); FunctionExecutable* executable = jsCast<FunctionExecutable*>(this); FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>( executable->codeBlockFor(kind)->baselineVersion()); RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock( CodeBlock::CopyParsedBlock, *baseline)); result->setAlternative(baseline); return result; }
bool ClonedArguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot& slot) { ClonedArguments* thisObject = jsCast<ClonedArguments*>(object); VM& vm = exec->vm(); if (!thisObject->specialsMaterialized()) { FunctionExecutable* executable = jsCast<FunctionExecutable*>(thisObject->m_callee->executable()); bool isStrictMode = executable->isStrictMode(); if (ident == vm.propertyNames->callee) { if (isStrictMode) { slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorArgumentsCalleeAndCallerGetterSetter()); return true; } slot.setValue(thisObject, 0, thisObject->m_callee.get()); return true; } if (ident == vm.propertyNames->iteratorSymbol) { slot.setValue(thisObject, DontEnum, thisObject->globalObject()->arrayProtoValuesFunction()); return true; } } return Base::getOwnPropertySlot(thisObject, exec, ident, slot); }
EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec) { JSValue thisValue = exec->thisValue(); if (thisValue.inherits(JSFunction::info())) { JSFunction* function = jsCast<JSFunction*>(thisValue); if (function->isHostOrBuiltinFunction()) { String name; if (JSBoundFunction* boundFunction = jsDynamicCast<JSBoundFunction*>(function)) name = boundFunction->toStringName(exec); else name = function->name(exec); return JSValue::encode(jsMakeNontrivialString(exec, "function ", name, "() {\n [native code]\n}")); } FunctionExecutable* executable = function->jsExecutable(); String functionHeader = executable->isArrowFunction() ? "" : "function "; StringView source = executable->source().provider()->getRange( executable->parametersStartOffset(), executable->parametersStartOffset() + executable->source().length()); return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, 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); }
void operator()(JSCell* cell) { if (!cell->inherits(&FunctionExecutable::s_info)) return; FunctionExecutable* executable = static_cast<FunctionExecutable*>(cell); if (currentlyExecutingFunctions.contains(executable)) return; executable->discardCode(); }
inline void operator()(JSCell* cell) { if (!cell->inherits(FunctionExecutable::info())) return; FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell); executable->clearCodeIfNotCompiling(); executable->clearUnlinkedCodeForRecompilationIfNotCompiling(); }
inline void visit(JSCell* cell) { if (!cell->inherits(FunctionExecutable::info())) return; FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell); executable->clearCode(); executable->clearUnlinkedCodeForRecompilation(); }
void operator()(JSCell* cell) { if (!cell->inherits(&FunctionExecutable::s_info)) return; FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell); if (currentlyExecutingFunctions.contains(executable)) return; executable->clearCodeIfNotCompiling(); }
void Heap::discardAllCompiledCode() { // If JavaScript is running, it's not safe to recompile, since we'll end // up throwing away code that is live on the stack. if (m_globalData->dynamicGlobalObject) return; for (FunctionExecutable* current = m_functions.head(); current; current = current->next()) current->discardCode(); }
RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor( CodeSpecializationKind kind, JSFunction* function, JSScope* scope, JSObject*& exception) { VM* vm = scope->vm(); ASSERT(vm->heap.isDeferred()); ASSERT(startColumn() != UINT_MAX); ASSERT(endColumn() != UINT_MAX); if (classInfo() == EvalExecutable::info()) { EvalExecutable* executable = jsCast<EvalExecutable*>(this); RELEASE_ASSERT(kind == CodeForCall); RELEASE_ASSERT(!executable->m_evalCodeBlock); RELEASE_ASSERT(!function); return adoptRef(new EvalCodeBlock( executable, executable->m_unlinkedEvalCodeBlock.get(), scope, executable->source().provider())); } if (classInfo() == ProgramExecutable::info()) { ProgramExecutable* executable = jsCast<ProgramExecutable*>(this); RELEASE_ASSERT(kind == CodeForCall); RELEASE_ASSERT(!executable->m_programCodeBlock); RELEASE_ASSERT(!function); return adoptRef(new ProgramCodeBlock( executable, executable->m_unlinkedProgramCodeBlock.get(), scope, executable->source().provider(), executable->source().startColumn())); } RELEASE_ASSERT(classInfo() == FunctionExecutable::info()); RELEASE_ASSERT(function); FunctionExecutable* executable = jsCast<FunctionExecutable*>(this); RELEASE_ASSERT(!executable->codeBlockFor(kind)); JSGlobalObject* globalObject = scope->globalObject(); ParserError error; DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff; ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff; UnlinkedFunctionCodeBlock* unlinkedCodeBlock = executable->m_unlinkedExecutable->codeBlockFor(*vm, executable->m_source, kind, debuggerMode, profilerMode, error, executable->isArrowFunction()); recordParse(executable->m_unlinkedExecutable->features(), executable->m_unlinkedExecutable->hasCapturedVariables(), firstLine(), lastLine(), startColumn(), endColumn()); if (!unlinkedCodeBlock) { exception = vm->throwException( globalObject->globalExec(), error.toErrorObject(globalObject, executable->m_source)); return nullptr; } SourceProvider* provider = executable->source().provider(); unsigned sourceOffset = executable->source().startOffset(); unsigned startColumn = executable->source().startColumn(); return adoptRef(new FunctionCodeBlock( executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn)); }
CodeBlock* getSomeBaselineCodeBlockForFunction(JSValue theFunctionValue) { FunctionExecutable* executable = getExecutableForFunction(theFunctionValue); if (!executable) return 0; CodeBlock* baselineCodeBlock = executable->baselineCodeBlockFor(CodeForCall); if (!baselineCodeBlock) baselineCodeBlock = executable->baselineCodeBlockFor(CodeForConstruct); return baselineCodeBlock; }
void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) { FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); ScriptExecutable::visitChildren(thisObject, visitor); if (thisObject->m_codeBlockForCall) thisObject->m_codeBlockForCall->visitAggregate(visitor); if (thisObject->m_codeBlockForConstruct) thisObject->m_codeBlockForConstruct->visitAggregate(visitor); visitor.append(&thisObject->m_unlinkedExecutable); }
JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* functionExecutableAsCell) { ASSERT(functionExecutableAsCell->inherits(&FunctionExecutable::s_info)); FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(functionExecutableAsCell); JSFunction *function = functionExecutable->make(exec, exec->scopeChain()); if (!functionExecutable->name().isNull()) { JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create( exec, functionExecutable->name(), function, ReadOnly | DontDelete); function->setScope(exec->globalData(), function->scope()->push(functionScopeObject)); } return function; }
void ClonedArguments::materializeSpecials(ExecState* exec) { RELEASE_ASSERT(!specialsMaterialized()); VM& vm = exec->vm(); FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_callee->executable()); bool isStrictMode = executable->isStrictMode(); if (isStrictMode) putDirectAccessor(exec, vm.propertyNames->callee, globalObject()->throwTypeErrorArgumentsCalleeAndCallerGetterSetter(), DontDelete | DontEnum | Accessor); else putDirect(vm, vm.propertyNames->callee, JSValue(m_callee.get())); putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), DontEnum); m_callee.clear(); }
CodeBlock* ScriptExecutable::newReplacementCodeBlockFor( CodeSpecializationKind kind) { if (classInfo() == EvalExecutable::info()) { RELEASE_ASSERT(kind == CodeForCall); EvalExecutable* executable = jsCast<EvalExecutable*>(this); EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>( executable->m_evalCodeBlock->baselineVersion()); EvalCodeBlock* result = EvalCodeBlock::create(vm(), CodeBlock::CopyParsedBlock, *baseline); result->setAlternative(*vm(), baseline); return result; } if (classInfo() == ProgramExecutable::info()) { RELEASE_ASSERT(kind == CodeForCall); ProgramExecutable* executable = jsCast<ProgramExecutable*>(this); ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>( executable->m_programCodeBlock->baselineVersion()); ProgramCodeBlock* result = ProgramCodeBlock::create(vm(), CodeBlock::CopyParsedBlock, *baseline); result->setAlternative(*vm(), baseline); return result; } if (classInfo() == ModuleProgramExecutable::info()) { RELEASE_ASSERT(kind == CodeForCall); ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this); ModuleProgramCodeBlock* baseline = static_cast<ModuleProgramCodeBlock*>( executable->m_moduleProgramCodeBlock->baselineVersion()); ModuleProgramCodeBlock* result = ModuleProgramCodeBlock::create(vm(), CodeBlock::CopyParsedBlock, *baseline); result->setAlternative(*vm(), baseline); return result; } RELEASE_ASSERT(classInfo() == FunctionExecutable::info()); FunctionExecutable* executable = jsCast<FunctionExecutable*>(this); FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>( executable->codeBlockFor(kind)->baselineVersion()); FunctionCodeBlock* result = FunctionCodeBlock::create(vm(), CodeBlock::CopyParsedBlock, *baseline); result->setAlternative(*vm(), baseline); return result; }
FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, int overrideLineNumber) { SourceCode source = m_sourceOverride ? SourceCode(m_sourceOverride) : ownerSource; unsigned firstLine = source.firstLine() + m_firstLineOffset; unsigned startOffset = source.startOffset() + m_startOffset; // Adjust to one-based indexing. bool startColumnIsOnFirstSourceLine = !m_firstLineOffset; unsigned startColumn = m_unlinkedBodyStartColumn + (startColumnIsOnFirstSourceLine ? source.startColumn() : 1); bool endColumnIsOnStartLine = !m_lineCount; unsigned endColumn = m_unlinkedBodyEndColumn + (endColumnIsOnStartLine ? startColumn : 1); SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); FunctionExecutable* result = FunctionExecutable::create(vm, code, this, firstLine, firstLine + m_lineCount, startColumn, endColumn); if (overrideLineNumber != -1) result->setOverrideLineNumber(overrideLineNumber); return result; }
void prepareCodeOriginForOSRExit(ExecState* exec, CodeOrigin codeOrigin) { VM& vm = exec->vm(); DeferGC deferGC(vm.heap); for (; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) { FunctionExecutable* executable = static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get()); CodeBlock* codeBlock = executable->baselineCodeBlockFor( codeOrigin.inlineCallFrame->specializationKind()); if (codeBlock->jitType() == JSC::JITCode::BaselineJIT) continue; ASSERT(codeBlock->jitType() == JSC::JITCode::InterpreterThunk); JIT::compile(&vm, codeBlock, JITCompilationMustSucceed); codeBlock->install(); } }
void Debugger::recompileAllJSFunctions(JSGlobalData* globalData) { // If JavaScript is running, it's not safe to recompile, since we'll end // up throwing away code that is live on the stack. ASSERT(!globalData->dynamicGlobalObject); if (globalData->dynamicGlobalObject) return; typedef HashSet<FunctionExecutable*> FunctionExecutableSet; typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap; FunctionExecutableSet functionExecutables; SourceProviderMap sourceProviders; LiveObjectIterator it = globalData->heap.primaryHeapBegin(); LiveObjectIterator heapEnd = globalData->heap.primaryHeapEnd(); for ( ; it != heapEnd; ++it) { if (!(*it)->inherits(&JSFunction::info)) continue; JSFunction* function = asFunction(*it); if (function->executable()->isHostFunction()) continue; FunctionExecutable* executable = function->jsExecutable(); // Check if the function is already in the set - if so, // we've already retranslated it, nothing to do here. if (!functionExecutables.add(executable).second) continue; ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec(); executable->recompile(exec); if (function->scope().globalObject()->debugger() == this) sourceProviders.add(executable->source().provider(), exec); } // Call sourceParsed() after reparsing all functions because it will execute // JavaScript in the inspector. SourceProviderMap::const_iterator end = sourceProviders.end(); for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter) sourceParsed(iter->second, SourceCode(iter->first), -1, UString()); }
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 sourceString = executable->source().toString(); insertSemicolonIfNeeded(sourceString, executable->bodyIncludesBraces()); return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "(", executable->paramString(), ") ", sourceString)); } 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); }
EncodedTiValue JSC_HOST_CALL functionProtoFuncToString(TiExcState* exec) { TiValue thisValue = exec->hostThisValue(); if (thisValue.inherits(&TiFunction::s_info)) { TiFunction* function = asFunction(thisValue); if (function->isHostFunction()) return TiValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}")); FunctionExecutable* executable = function->jsExecutable(); UString sourceString = executable->source().toString(); insertSemicolonIfNeeded(sourceString); return TiValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "(", executable->paramString(), ") ", sourceString)); } if (thisValue.inherits(&InternalFunction::s_info)) { InternalFunction* function = asInternalFunction(thisValue); return TiValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}")); } return throwVMTypeError(exec); }
FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, Optional<int> overrideLineNumber, Intrinsic intrinsic) { SourceCode source = m_sourceOverride ? SourceCode(m_sourceOverride) : ownerSource; unsigned firstLine = source.firstLine() + m_firstLineOffset; unsigned startOffset = source.startOffset() + m_startOffset; unsigned lineCount = m_lineCount; // Adjust to one-based indexing. bool startColumnIsOnFirstSourceLine = !m_firstLineOffset; unsigned startColumn = m_unlinkedBodyStartColumn + (startColumnIsOnFirstSourceLine ? source.startColumn() : 1); bool endColumnIsOnStartLine = !lineCount; unsigned endColumn = m_unlinkedBodyEndColumn + (endColumnIsOnStartLine ? startColumn : 1); SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); FunctionOverrides::OverrideInfo overrideInfo; bool hasFunctionOverride = false; if (UNLIKELY(Options::functionOverrides())) { hasFunctionOverride = FunctionOverrides::initializeOverrideFor(code, overrideInfo); if (hasFunctionOverride) { firstLine = overrideInfo.firstLine; lineCount = overrideInfo.lineCount; startColumn = overrideInfo.startColumn; endColumn = overrideInfo.endColumn; code = overrideInfo.sourceCode; } } FunctionExecutable* result = FunctionExecutable::create(vm, code, this, firstLine, firstLine + lineCount, startColumn, endColumn, intrinsic); if (overrideLineNumber) result->setOverrideLineNumber(*overrideLineNumber); if (UNLIKELY(hasFunctionOverride)) { result->overrideParameterAndTypeProfilingStartEndOffsets( overrideInfo.parametersStartOffset, overrideInfo.typeProfilingStartOffset, overrideInfo.typeProfilingEndOffset); } return result; }
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(); }
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(); }
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()); }
FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& passedParentSource, std::optional<int> overrideLineNumber, Intrinsic intrinsic) { const SourceCode& parentSource = m_parentSourceOverride.isNull() ? passedParentSource : m_parentSourceOverride; unsigned firstLine = parentSource.firstLine().oneBasedInt() + m_firstLineOffset; unsigned startOffset = parentSource.startOffset() + m_startOffset; unsigned lineCount = m_lineCount; unsigned startColumn = linkedStartColumn(parentSource.startColumn().oneBasedInt()); unsigned endColumn = linkedEndColumn(startColumn); SourceCode source(parentSource.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); FunctionOverrides::OverrideInfo overrideInfo; bool hasFunctionOverride = false; if (UNLIKELY(Options::functionOverrides())) { hasFunctionOverride = FunctionOverrides::initializeOverrideFor(source, overrideInfo); if (UNLIKELY(hasFunctionOverride)) { firstLine = overrideInfo.firstLine; lineCount = overrideInfo.lineCount; startColumn = overrideInfo.startColumn; endColumn = overrideInfo.endColumn; source = overrideInfo.sourceCode; } } FunctionExecutable* result = FunctionExecutable::create(vm, source, this, firstLine + lineCount, endColumn, intrinsic); if (overrideLineNumber) result->setOverrideLineNumber(*overrideLineNumber); if (UNLIKELY(hasFunctionOverride)) { result->overrideParameterAndTypeProfilingStartEndOffsets( overrideInfo.parametersStartOffset, overrideInfo.typeProfilingStartOffset, overrideInfo.typeProfilingEndOffset); } return result; }
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 }
void JSFunction::addNameScopeIfNeeded(VM& vm) { FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_executable.get()); if (!functionNameIsInScope(executable->name(), executable->functionMode())) return; if (!functionNameScopeIsDynamic(executable->usesEval(), executable->isStrictMode())) return; m_scope.set(vm, this, JSNameScope::create(vm, m_scope->globalObject(), executable->name(), this, ReadOnly | DontDelete, m_scope.get())); }
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()); }
void ExecutableBase::dump(PrintStream& out) const { ExecutableBase* realThis = const_cast<ExecutableBase*>(this); if (classInfo() == NativeExecutable::info()) { NativeExecutable* native = jsCast<NativeExecutable*>(realThis); out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor()))); return; } if (classInfo() == EvalExecutable::info()) { EvalExecutable* eval = jsCast<EvalExecutable*>(realThis); if (CodeBlock* codeBlock = eval->codeBlock()) out.print(*codeBlock); else out.print("EvalExecutable w/o CodeBlock"); return; } if (classInfo() == ProgramExecutable::info()) { ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis); if (CodeBlock* codeBlock = eval->codeBlock()) out.print(*codeBlock); else out.print("ProgramExecutable w/o CodeBlock"); return; } if (classInfo() == ModuleProgramExecutable::info()) { ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(realThis); if (CodeBlock* codeBlock = executable->codeBlock()) out.print(*codeBlock); else out.print("ModuleProgramExecutable w/o CodeBlock"); return; } FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis); if (!function->eitherCodeBlock()) out.print("FunctionExecutable w/o CodeBlock"); else { CommaPrinter comma("/"); if (function->codeBlockForCall()) out.print(comma, *function->codeBlockForCall()); if (function->codeBlockForConstruct()) out.print(comma, *function->codeBlockForConstruct()); } }
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()) 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())); } String functionHeader = executable->isArrowFunction() ? "" : "function "; StringView source = executable->source().provider()->getRange( executable->parametersStartOffset(), executable->parametersStartOffset() + executable->source().length()); return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source)); } if (thisValue.inherits(InternalFunction::info())) { InternalFunction* function = asInternalFunction(thisValue); 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()) return JSValue::encode(jsMakeNontrivialString(exec, "function ", classInfo->className, "() {\n [native code]\n}")); } } } return throwVMTypeError(exec, scope); }