+
+void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
+{
+ RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
+ RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
+
+ if (Options::verboseOSR())
+ dataLog("Installing ", *genericCodeBlock, "\n");
+
+ VM& vm = *genericCodeBlock->vm();
+
+ if (vm.m_perBytecodeProfiler)
+ vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
+
+ ASSERT(vm.heap.isDeferred());
+
+ CodeSpecializationKind kind = genericCodeBlock->specializationKind();
+
+ RefPtr<CodeBlock> oldCodeBlock;
+
+ switch (kind) {
+ case CodeForCall:
+ m_jitCodeForCall = genericCodeBlock->jitCode();
+ m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
+ m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
+ m_numParametersForCall = genericCodeBlock->numParameters();
+ break;
+ case CodeForConstruct:
+ m_jitCodeForConstruct = genericCodeBlock->jitCode();
+ m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
+ m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
+ m_numParametersForConstruct = genericCodeBlock->numParameters();
+ break;
+ }
+
+ switch (genericCodeBlock->codeType()) {
+ case GlobalCode: {
+ ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
+ ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
+
+ ASSERT(kind == CodeForCall);
+
+ oldCodeBlock = executable->m_programCodeBlock;
+ executable->m_programCodeBlock = codeBlock;
+ break;
+ }
+
+ case EvalCode: {
+ EvalExecutable* executable = jsCast<EvalExecutable*>(this);
+ EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
+
+ ASSERT(kind == CodeForCall);
+
+ oldCodeBlock = executable->m_evalCodeBlock;
+ executable->m_evalCodeBlock = codeBlock;
+ break;
+ }
+
+ case FunctionCode: {
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
+ FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
+
+ switch (kind) {
+ case CodeForCall:
+ oldCodeBlock = executable->m_codeBlockForCall;
+ executable->m_codeBlockForCall = codeBlock;
+ break;
+ case CodeForConstruct:
+ oldCodeBlock = executable->m_codeBlockForConstruct;
+ executable->m_codeBlockForConstruct = codeBlock;
+ break;
+ }
+ break;
+ } }
+
+ if (oldCodeBlock)
+ oldCodeBlock->unlinkIncomingCalls();
+
+ Debugger* debugger = genericCodeBlock->globalObject()->debugger();
+ if (debugger)
+ debugger->registerCodeBlock(genericCodeBlock);
+
+ Heap::heap(this)->writeBarrier(this);
+}
+
+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);
+ 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;
+ }
+
+ // 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 (functionNameIsInScope(executable->name(), executable->functionMode())
+ && functionNameScopeIsDynamic(executable->usesEval(), executable->isStrictMode())) {
+ // We shouldn't have to do this. But we do, because bytecode linking requires a real scope
+ // chain.
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141885
+ SymbolTable* symbolTable =
+ SymbolTable::createNameScopeTable(*vm, executable->name(), ReadOnly | DontDelete);
+ scope = JSFunctionNameScope::create(
+ *vm, scope->globalObject(), scope, symbolTable, function);
+ }
+
+ 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));
+}
+
+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;
+}
+
+static void setupLLInt(VM& vm, CodeBlock* codeBlock)
+{
+ LLInt::setEntrypoint(vm, codeBlock);
+}
+
+static void setupJIT(VM& vm, CodeBlock* codeBlock)
+{
+#if ENABLE(JIT)
+ CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
+ RELEASE_ASSERT(result == CompilationSuccessful);
+#else
+ UNUSED_PARAM(vm);
+ UNUSED_PARAM(codeBlock);
+ UNREACHABLE_FOR_PLATFORM();