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; }
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* 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; }
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()); }
PassRefPtr<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); recordParse(executable->m_unlinkedExecutable->features(), executable->m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn(), endColumn()); if (!unlinkedCodeBlock) { exception = vm->throwException( globalObject->globalExec(), error.toErrorObject(globalObject, executable->m_source)); return 0; } // Parsing reveals whether our function uses features that require a separate function name object in the scope chain. // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables. if (!executable->m_didParseForTheFirstTime) { executable->m_didParseForTheFirstTime = true; function->addNameScopeIfNeeded(*vm); *scope = function->scope(); } 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)); }