diff options
Diffstat (limited to 'deps/v8/src/codegen/compiler.cc')
-rw-r--r-- | deps/v8/src/codegen/compiler.cc | 489 |
1 files changed, 364 insertions, 125 deletions
diff --git a/deps/v8/src/codegen/compiler.cc b/deps/v8/src/codegen/compiler.cc index 04e80f5a6e..595e59f551 100644 --- a/deps/v8/src/codegen/compiler.cc +++ b/deps/v8/src/codegen/compiler.cc @@ -11,12 +11,14 @@ #include "src/asmjs/asm-js.h" #include "src/ast/prettyprinter.h" #include "src/ast/scopes.h" +#include "src/base/logging.h" #include "src/base/optional.h" #include "src/codegen/assembler-inl.h" #include "src/codegen/compilation-cache.h" #include "src/codegen/optimized-compilation-info.h" #include "src/codegen/pending-optimization-table.h" #include "src/codegen/unoptimized-compilation-info.h" +#include "src/common/assert-scope.h" #include "src/common/globals.h" #include "src/common/message-template.h" #include "src/compiler-dispatcher/compiler-dispatcher.h" @@ -24,16 +26,22 @@ #include "src/compiler/pipeline.h" #include "src/debug/debug.h" #include "src/debug/liveedit.h" +#include "src/diagnostics/code-tracer.h" #include "src/execution/frames-inl.h" #include "src/execution/isolate-inl.h" +#include "src/execution/isolate.h" #include "src/execution/runtime-profiler.h" #include "src/execution/vm-state-inl.h" +#include "src/handles/maybe-handles.h" #include "src/heap/heap-inl.h" +#include "src/heap/off-thread-factory-inl.h" #include "src/init/bootstrapper.h" #include "src/interpreter/interpreter.h" #include "src/logging/log-inl.h" #include "src/objects/feedback-cell-inl.h" #include "src/objects/map.h" +#include "src/objects/object-list-macros.h" +#include "src/objects/shared-function-info.h" #include "src/parsing/parse-info.h" #include "src/parsing/parser.h" #include "src/parsing/parsing.h" @@ -161,6 +169,16 @@ CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob( return UpdateState(FinalizeJobImpl(shared_info, isolate), State::kSucceeded); } +CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob( + Handle<SharedFunctionInfo> shared_info, OffThreadIsolate* isolate) { + DisallowHeapAccess no_heap_access; + + // Delegate to the underlying implementation. + DCHECK_EQ(state(), State::kReadyToFinalize); + ScopedTimer t(&time_taken_to_finalize_); + return UpdateState(FinalizeJobImpl(shared_info, isolate), State::kSucceeded); +} + void UnoptimizedCompilationJob::RecordCompilationStats(Isolate* isolate) const { int code_size; if (compilation_info()->has_bytecode_array()) { @@ -208,7 +226,8 @@ CompilationJob::Status OptimizedCompilationJob::PrepareJob(Isolate* isolate) { DisallowJavascriptExecution no_js(isolate); if (FLAG_trace_opt && compilation_info()->IsOptimizing()) { - StdoutStream os; + CodeTracer::Scope scope(isolate->GetCodeTracer()); + OFStream os(scope.file()); os << "[compiling method " << Brief(*compilation_info()->closure()) << " using " << compiler_name_; if (compilation_info()->is_osr()) os << " OSR"; @@ -262,10 +281,11 @@ void OptimizedCompilationJob::RecordCompilationStats(CompilationMode mode, double ms_optimize = time_taken_to_execute_.InMillisecondsF(); double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); if (FLAG_trace_opt) { - PrintF("[optimizing "); - function->ShortPrint(); - PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, - ms_codegen); + CodeTracer::Scope scope(isolate->GetCodeTracer()); + PrintF(scope.file(), "[optimizing "); + function->ShortPrint(scope.file()); + PrintF(scope.file(), " - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, + ms_optimize, ms_codegen); } if (FLAG_trace_opt_stats) { static double compilation_time = 0.0; @@ -442,9 +462,40 @@ void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info, } } +void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info, + Handle<SharedFunctionInfo> shared_info, + ParseInfo* parse_info, OffThreadIsolate* isolate) { + DCHECK_EQ(shared_info->language_mode(), + compilation_info->literal()->language_mode()); + + // Update the shared function info with the scope info. + Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info(); + shared_info->set_scope_info(*scope_info); + + DCHECK(compilation_info->has_bytecode_array()); + DCHECK(!shared_info->HasBytecodeArray()); // Only compiled once. + DCHECK(!compilation_info->has_asm_wasm_data()); + DCHECK(!shared_info->HasFeedbackMetadata()); + + // If the function failed asm-wasm compilation, mark asm_wasm as broken + // to ensure we don't try to compile as asm-wasm. + if (compilation_info->literal()->scope()->IsAsmModule()) { + shared_info->set_is_asm_wasm_broken(true); + } + + shared_info->set_bytecode_array(*compilation_info->bytecode_array()); + + Handle<FeedbackMetadata> feedback_metadata = + FeedbackMetadata::New(isolate, compilation_info->feedback_vector_spec()); + shared_info->set_feedback_metadata(*feedback_metadata); + + DCHECK(!compilation_info->has_coverage_info()); +} + +template <typename LocalIsolate> void EnsureSharedFunctionInfosArrayOnScript(Handle<Script> script, ParseInfo* parse_info, - Isolate* isolate) { + LocalIsolate* isolate) { DCHECK(parse_info->is_toplevel()); if (script->shared_function_infos().length() > 0) { DCHECK_EQ(script->shared_function_infos().length(), @@ -452,21 +503,25 @@ void EnsureSharedFunctionInfosArrayOnScript(Handle<Script> script, return; } Handle<WeakFixedArray> infos(isolate->factory()->NewWeakFixedArray( - parse_info->max_function_literal_id() + 1)); + parse_info->max_function_literal_id() + 1, AllocationType::kOld)); script->set_shared_function_infos(*infos); } void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal, - Handle<SharedFunctionInfo> shared_info) { - shared_info->set_has_duplicate_parameters( - literal->has_duplicate_parameters()); - shared_info->set_is_oneshot_iife(literal->is_oneshot_iife()); - shared_info->UpdateAndFinalizeExpectedNofPropertiesFromEstimate(literal); + SharedFunctionInfo shared_info) { + shared_info.set_has_duplicate_parameters(literal->has_duplicate_parameters()); + shared_info.set_is_oneshot_iife(literal->is_oneshot_iife()); + shared_info.UpdateAndFinalizeExpectedNofPropertiesFromEstimate(literal); if (literal->dont_optimize_reason() != BailoutReason::kNoReason) { - shared_info->DisableOptimization(literal->dont_optimize_reason()); + shared_info.DisableOptimization(literal->dont_optimize_reason()); } - shared_info->set_is_safe_to_skip_arguments_adaptor( + + shared_info.set_class_scope_has_private_brand( + literal->class_scope_has_private_brand()); + shared_info.set_is_safe_to_skip_arguments_adaptor( literal->SafeToSkipArgumentsAdaptor()); + shared_info.set_has_static_private_methods_or_accessors( + literal->has_static_private_methods_or_accessors()); } CompilationJob::Status FinalizeUnoptimizedCompilationJob( @@ -475,7 +530,7 @@ CompilationJob::Status FinalizeUnoptimizedCompilationJob( UnoptimizedCompilationInfo* compilation_info = job->compilation_info(); ParseInfo* parse_info = job->parse_info(); - SetSharedFunctionFlagsFromLiteral(compilation_info->literal(), shared_info); + SetSharedFunctionFlagsFromLiteral(compilation_info->literal(), *shared_info); CompilationJob::Status status = job->FinalizeJob(shared_info, isolate); if (status == CompilationJob::SUCCEEDED) { @@ -485,7 +540,8 @@ CompilationJob::Status FinalizeUnoptimizedCompilationJob( // background compile was started in which the compiled bytecode will not be // missing source positions (for instance by enabling the cpu profiler). So // force source position collection now in that case. - if (isolate->NeedsDetailedOptimizedCodeLineInfo()) { + if (!parse_info->collect_source_positions() && + isolate->NeedsDetailedOptimizedCodeLineInfo()) { SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate, shared_info); } @@ -503,6 +559,23 @@ CompilationJob::Status FinalizeUnoptimizedCompilationJob( return status; } +CompilationJob::Status FinalizeUnoptimizedCompilationJob( + UnoptimizedCompilationJob* job, Handle<SharedFunctionInfo> shared_info, + OffThreadIsolate* isolate) { + UnoptimizedCompilationInfo* compilation_info = job->compilation_info(); + ParseInfo* parse_info = job->parse_info(); + + SetSharedFunctionFlagsFromLiteral(compilation_info->literal(), *shared_info); + + CompilationJob::Status status = job->FinalizeJob(shared_info, isolate); + if (status == CompilationJob::SUCCEEDED) { + InstallUnoptimizedCode(compilation_info, shared_info, parse_info, isolate); + + // TODO(leszeks): Record the function compilation and compilation stats. + } + return status; +} + std::unique_ptr<UnoptimizedCompilationJob> ExecuteUnoptimizedCompileJobs( ParseInfo* parse_info, FunctionLiteral* literal, AccountingAllocator* allocator, @@ -564,7 +637,7 @@ MaybeHandle<SharedFunctionInfo> GenerateUnoptimizedCodeForToplevel( Isolate* isolate, Handle<Script> script, ParseInfo* parse_info, AccountingAllocator* allocator, IsCompiledScope* is_compiled_scope) { EnsureSharedFunctionInfosArrayOnScript(script, parse_info, isolate); - parse_info->ast_value_factory()->Internalize(isolate->factory()); + parse_info->ast_value_factory()->Internalize(isolate); if (!Compiler::Analyze(parse_info)) return MaybeHandle<SharedFunctionInfo>(); DeclarationScope::AllocateScopeInfos(parse_info, isolate); @@ -629,12 +702,14 @@ MaybeHandle<SharedFunctionInfo> GenerateUnoptimizedCodeForToplevel( return top_level; } +template <typename LocalIsolate> bool FinalizeUnoptimizedCode( - ParseInfo* parse_info, Isolate* isolate, + ParseInfo* parse_info, LocalIsolate* isolate, Handle<SharedFunctionInfo> shared_info, UnoptimizedCompilationJob* outer_function_job, UnoptimizedCompilationJobList* inner_function_jobs) { - DCHECK(AllowCompilation::IsAllowed(isolate)); + // TODO(leszeks): Re-enable. + // DCHECK(AllowCompilation::IsAllowed(isolate)); // TODO(rmcilroy): Clear native context in debug once AsmJS generates doesn't // rely on accessing native context during finalization. @@ -649,6 +724,7 @@ bool FinalizeUnoptimizedCode( } Handle<Script> script(Script::cast(shared_info->script()), isolate); + parse_info->CheckFlagsForFunctionFromScript(*script); // Finalize the inner functions' compilation jobs. for (auto&& inner_job : *inner_function_jobs) { @@ -752,9 +828,10 @@ bool GetOptimizedCodeNow(OptimizedCompilationJob* job, Isolate* isolate) { CompilationJob::SUCCEEDED || job->FinalizeJob(isolate) != CompilationJob::SUCCEEDED) { if (FLAG_trace_opt) { - PrintF("[aborted optimizing "); - compilation_info->closure()->ShortPrint(); - PrintF(" because: %s]\n", + CodeTracer::Scope scope(isolate->GetCodeTracer()); + PrintF(scope.file(), "[aborted optimizing "); + compilation_info->closure()->ShortPrint(scope.file()); + PrintF(scope.file(), " because: %s]\n", GetBailoutReason(compilation_info->bailout_reason())); } return false; @@ -838,12 +915,13 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function, if (GetCodeFromOptimizedCodeCache(function, osr_offset) .ToHandle(&cached_code)) { if (FLAG_trace_opt) { - PrintF("[found optimized code for "); - function->ShortPrint(); + CodeTracer::Scope scope(isolate->GetCodeTracer()); + PrintF(scope.file(), "[found optimized code for "); + function->ShortPrint(scope.file()); if (!osr_offset.IsNone()) { - PrintF(" at OSR AST id %d", osr_offset.ToInt()); + PrintF(scope.file(), " at OSR AST id %d", osr_offset.ToInt()); } - PrintF("]\n"); + PrintF(scope.file(), "]\n"); } return cached_code; } @@ -932,6 +1010,13 @@ bool FailWithPendingException(Isolate* isolate, Handle<Script> script, return false; } +bool FailWithPendingException(OffThreadIsolate* isolate, Handle<Script> script, + ParseInfo* parse_info, + Compiler::ClearExceptionFlag flag) { + // TODO(leszeks): Implement. + UNREACHABLE(); +} + void FinalizeScriptCompilation(Isolate* isolate, Handle<Script> script, ParseInfo* parse_info) { script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); @@ -954,12 +1039,19 @@ void FinalizeScriptCompilation(Isolate* isolate, Handle<Script> script, } } +void FinalizeScriptCompilation(OffThreadIsolate* isolate, Handle<Script> script, + ParseInfo* parse_info) { + script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); + DCHECK(!parse_info->parallel_tasks()); +} + +template <typename LocalIsolate> MaybeHandle<SharedFunctionInfo> FinalizeTopLevel( - ParseInfo* parse_info, Handle<Script> script, Isolate* isolate, + ParseInfo* parse_info, Handle<Script> script, LocalIsolate* isolate, UnoptimizedCompilationJob* outer_function_job, UnoptimizedCompilationJobList* inner_function_jobs) { // Internalize ast values onto the heap. - parse_info->ast_value_factory()->Internalize(isolate->factory()); + parse_info->ast_value_factory()->Internalize(isolate); // Create shared function infos for top level and shared function infos array // for inner functions. @@ -984,7 +1076,8 @@ MaybeHandle<SharedFunctionInfo> FinalizeTopLevel( } MaybeHandle<SharedFunctionInfo> CompileToplevel( - ParseInfo* parse_info, Handle<Script> script, Isolate* isolate, + ParseInfo* parse_info, Handle<Script> script, + MaybeHandle<ScopeInfo> maybe_outer_scope_info, Isolate* isolate, IsCompiledScope* is_compiled_scope) { TimerEventScope<TimerEventCompileCode> top_level_timer(isolate); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); @@ -997,7 +1090,8 @@ MaybeHandle<SharedFunctionInfo> CompileToplevel( : RuntimeCallCounterId::kCompileScript); VMState<BYTECODE_COMPILER> state(isolate); if (parse_info->literal() == nullptr && - !parsing::ParseProgram(parse_info, script, isolate)) { + !parsing::ParseProgram(parse_info, script, maybe_outer_scope_info, + isolate)) { return MaybeHandle<SharedFunctionInfo>(); } // Measure how long it takes to do the compilation; only take the @@ -1044,34 +1138,43 @@ std::unique_ptr<UnoptimizedCompilationJob> CompileOnBackgroundThread( return outer_function_job; } +MaybeHandle<SharedFunctionInfo> CompileToplevel( + ParseInfo* parse_info, Handle<Script> script, Isolate* isolate, + IsCompiledScope* is_compiled_scope) { + return CompileToplevel(parse_info, script, kNullMaybeHandle, isolate, + is_compiled_scope); +} + } // namespace BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data, Isolate* isolate) : info_(new ParseInfo(isolate)), + off_thread_isolate_(FLAG_finalize_streaming_on_background + ? new OffThreadIsolate(isolate, info_->zone()) + : nullptr), stack_size_(i::FLAG_stack_size), worker_thread_runtime_call_stats_( isolate->counters()->worker_thread_runtime_call_stats()), allocator_(isolate->allocator()), - timer_(isolate->counters()->compile_script_on_background()) { + timer_(isolate->counters()->compile_script_on_background()), + collected_source_positions_(false) { VMState<PARSER> state(isolate); // Prepare the data for the internalization phase and compilation phase, which // will happen in the main thread after parsing. LOG(isolate, ScriptEvent(Logger::ScriptEventType::kStreamingCompile, info_->script_id())); - info_->set_toplevel(); - info_->set_allow_lazy_parsing(); - if (V8_UNLIKELY(info_->block_coverage_enabled())) { - info_->AllocateSourceRangeMap(); - } - LanguageMode language_mode = construct_language_mode(FLAG_use_strict); - info_->set_language_mode( - stricter_language_mode(info_->language_mode(), language_mode)); + info_->SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(), true, + construct_language_mode(FLAG_use_strict), + REPLMode::kNo); + language_mode_ = info_->language_mode(); std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For( streamed_data->source_stream.get(), streamed_data->encoding)); info_->set_character_stream(std::move(stream)); + + finalize_on_background_thread_ = FLAG_finalize_streaming_on_background; } BackgroundCompileTask::BackgroundCompileTask( @@ -1084,7 +1187,10 @@ BackgroundCompileTask::BackgroundCompileTask( stack_size_(max_stack_size), worker_thread_runtime_call_stats_(worker_thread_runtime_stats), allocator_(allocator), - timer_(timer) { + timer_(timer), + language_mode_(info_->language_mode()), + collected_source_positions_(false), + finalize_on_background_thread_(false) { DCHECK(outer_parse_info->is_toplevel()); DCHECK(!function_literal->is_toplevel()); @@ -1124,6 +1230,7 @@ class OffThreadParseInfoScope { } ~OffThreadParseInfoScope() { + DCHECK_NOT_NULL(parse_info_); parse_info_->set_stack_limit(original_stack_limit_); parse_info_->set_runtime_call_stats(original_runtime_call_stats_); } @@ -1145,8 +1252,9 @@ void BackgroundCompileTask::Run() { DisallowHeapAccess no_heap_access; TimedHistogramScope timer(timer_); - OffThreadParseInfoScope off_thread_scope( - info_.get(), worker_thread_runtime_call_stats_, stack_size_); + base::Optional<OffThreadParseInfoScope> off_thread_scope( + base::in_place, info_.get(), worker_thread_runtime_call_stats_, + stack_size_); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "BackgroundCompileTask::Run"); RuntimeCallTimerScope runtimeTimer( @@ -1167,6 +1275,52 @@ void BackgroundCompileTask::Run() { // Parsing has succeeded, compile. outer_function_job_ = CompileOnBackgroundThread(info_.get(), allocator_, &inner_function_jobs_); + // Save the language mode and record whether we collected source positions. + language_mode_ = info_->language_mode(); + collected_source_positions_ = info_->collect_source_positions(); + + if (finalize_on_background_thread_) { + DCHECK(info_->is_toplevel()); + + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), + "V8.FinalizeCodeBackground"); + + off_thread_isolate_->PinToCurrentThread(); + + OffThreadHandleScope handle_scope(off_thread_isolate_.get()); + + // We don't have the script source or the script origin yet, so use a few + // default values for them. These will be fixed up during the main-thread + // merge. + Handle<Script> script = + info_->CreateScript(off_thread_isolate_.get(), + off_thread_isolate_->factory()->empty_string(), + ScriptOriginOptions(), NOT_NATIVES_CODE); + + Handle<SharedFunctionInfo> outer_function_sfi = + FinalizeTopLevel(info_.get(), script, off_thread_isolate_.get(), + outer_function_job_.get(), &inner_function_jobs_) + .ToHandleChecked(); + + parser_->HandleSourceURLComments(off_thread_isolate_.get(), script); + + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), + "V8.FinalizeCodeBackground.Finish"); + off_thread_isolate_->FinishOffThread(); + + // Off-thread handles will become invalid after the handle scope closes, + // so save the raw object here. + outer_function_sfi_ = *outer_function_sfi; + + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), + "V8.FinalizeCodeBackground.ReleaseParser"); + DCHECK_EQ(language_mode_, info_->language_mode()); + off_thread_scope.reset(); + parser_.reset(); + info_.reset(); + outer_function_job_.reset(); + inner_function_jobs_.clear(); + } } } @@ -1357,7 +1511,7 @@ bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info, } // Internalize ast values onto the heap. - parse_info.ast_value_factory()->Internalize(isolate->factory()); + parse_info.ast_value_factory()->Internalize(isolate); // Finalize compilation of the unoptimized bytecode or asm-js data. if (!FinalizeUnoptimizedCode(&parse_info, isolate, shared_info, @@ -1422,9 +1576,10 @@ bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag, // Optimize now if --always-opt is enabled. if (FLAG_always_opt && !function->shared().HasAsmWasmData()) { if (FLAG_trace_opt) { - PrintF("[optimizing "); - function->ShortPrint(); - PrintF(" because --always-opt]\n"); + CodeTracer::Scope scope(isolate->GetCodeTracer()); + PrintF(scope.file(), "[optimizing "); + function->ShortPrint(scope.file()); + PrintF(scope.file(), " because --always-opt]\n"); } Handle<Code> opt_code; if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent) @@ -1456,9 +1611,7 @@ bool Compiler::FinalizeBackgroundCompileTask( DCHECK(!shared_info->is_compiled()); Handle<Script> script(Script::cast(shared_info->script()), isolate); - // TODO(leszeks): We can probably remove this, the parse_info flags should - // already match the script's. - parse_info->SetFlagsFromScript(isolate, *script); + parse_info->CheckFlagsForFunctionFromScript(*script); task->parser()->UpdateStatistics(isolate, script); task->parser()->HandleSourceURLComments(isolate, script); @@ -1469,7 +1622,7 @@ bool Compiler::FinalizeBackgroundCompileTask( } // Parsing has succeeded - finalize compilation. - parse_info->ast_value_factory()->Internalize(isolate->factory()); + parse_info->ast_value_factory()->Internalize(isolate); if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info, task->outer_function_job(), task->inner_function_jobs())) { @@ -1565,9 +1718,21 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( allow_eval_cache = true; } else { ParseInfo parse_info(isolate); + parse_info.SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(), + true, language_mode, REPLMode::kNo); + + parse_info.set_eval(); + parse_info.set_parse_restriction(restriction); + parse_info.set_parameters_end_pos(parameters_end_pos); + DCHECK(!parse_info.is_module()); + + MaybeHandle<ScopeInfo> maybe_outer_scope_info; + if (!context->IsNativeContext()) { + maybe_outer_scope_info = handle(context->scope_info(), isolate); + } + script = parse_info.CreateScript( isolate, source, OriginOptionsForEval(outer_info->script())); - script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); script->set_eval_from_shared(*outer_info); if (eval_position == kNoSourcePosition) { // If the position is missing, attempt to get the code offset by @@ -1586,16 +1751,8 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( } script->set_eval_from_position(eval_position); - parse_info.set_eval(); - parse_info.set_language_mode(language_mode); - parse_info.set_parse_restriction(restriction); - parse_info.set_parameters_end_pos(parameters_end_pos); - if (!context->IsNativeContext()) { - parse_info.set_outer_scope_info(handle(context->scope_info(), isolate)); - } - DCHECK(!parse_info.is_module()); - - if (!CompileToplevel(&parse_info, script, isolate, &is_compiled_scope) + if (!CompileToplevel(&parse_info, script, maybe_outer_scope_info, isolate, + &is_compiled_scope) .ToHandle(&shared_info)) { return MaybeHandle<JSFunction>(); } @@ -1981,32 +2138,51 @@ struct ScriptCompileTimerScope { } }; -Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info, - Handle<String> source, - Compiler::ScriptDetails script_details, - ScriptOriginOptions origin_options, - NativesFlag natives) { - // Create a script object describing the script to be compiled. - Handle<Script> script = parse_info->CreateScript( - isolate, source, origin_options, script_details.repl_mode, natives); +void SetScriptFieldsFromDetails(Script script, + Compiler::ScriptDetails script_details) { Handle<Object> script_name; if (script_details.name_obj.ToHandle(&script_name)) { - script->set_name(*script_name); - script->set_line_offset(script_details.line_offset); - script->set_column_offset(script_details.column_offset); + script.set_name(*script_name); + script.set_line_offset(script_details.line_offset); + script.set_column_offset(script_details.column_offset); } Handle<Object> source_map_url; if (script_details.source_map_url.ToHandle(&source_map_url)) { - script->set_source_mapping_url(*source_map_url); + script.set_source_mapping_url(*source_map_url); } Handle<FixedArray> host_defined_options; if (script_details.host_defined_options.ToHandle(&host_defined_options)) { - script->set_host_defined_options(*host_defined_options); + script.set_host_defined_options(*host_defined_options); } +} + +Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info, + Handle<String> source, + Compiler::ScriptDetails script_details, + ScriptOriginOptions origin_options, + NativesFlag natives) { + // Create a script object describing the script to be compiled. + Handle<Script> script = + parse_info->CreateScript(isolate, source, origin_options, natives); + SetScriptFieldsFromDetails(*script, script_details); LOG(isolate, ScriptDetails(*script)); return script; } +void FixUpOffThreadAllocatedScript(Isolate* isolate, Handle<Script> script, + Handle<String> source, + Compiler::ScriptDetails script_details, + ScriptOriginOptions origin_options, + NativesFlag natives) { + DisallowHeapAllocation no_gc; + DCHECK_EQ(natives, NOT_NATIVES_CODE); + DCHECK_EQ(script_details.repl_mode, REPLMode::kNo); + script->set_origin_options(origin_options); + script->set_source(*source); + SetScriptFieldsFromDetails(*script, script_details); + LOG(isolate, ScriptDetails(*script)); +} + } // namespace MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript( @@ -2077,19 +2253,24 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript( } if (maybe_result.is_null()) { - ParseInfo parse_info(isolate); // No cache entry found compile the script. + ParseInfo parse_info(isolate); + + parse_info.SetFlagsForToplevelCompile( + isolate->is_collecting_type_profile(), natives == NOT_NATIVES_CODE, + language_mode, script_details.repl_mode); + + parse_info.set_module(origin_options.IsModule()); + parse_info.set_extension(extension); + parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile); + Handle<Script> script = NewScript(isolate, &parse_info, source, script_details, origin_options, natives); + DCHECK_IMPLIES(parse_info.collect_type_profile(), + script->IsUserJavaScript()); DCHECK_EQ(parse_info.is_repl_mode(), script->is_repl_mode()); // Compile the function and add it to the isolate cache. - if (origin_options.IsModule()) parse_info.set_module(); - parse_info.set_extension(extension); - parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile); - - parse_info.set_language_mode( - stricter_language_mode(parse_info.language_mode(), language_mode)); maybe_result = CompileToplevel(&parse_info, script, isolate, &is_compiled_scope); Handle<SharedFunctionInfo> result; @@ -2151,27 +2332,30 @@ MaybeHandle<JSFunction> Compiler::GetWrappedFunction( IsCompiledScope is_compiled_scope; if (!maybe_result.ToHandle(&wrapped)) { ParseInfo parse_info(isolate); - script = NewScript(isolate, &parse_info, source, script_details, - origin_options, NOT_NATIVES_CODE); - script->set_wrapped_arguments(*arguments); + parse_info.SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(), + true, language_mode, + script_details.repl_mode); parse_info.set_eval(); // Use an eval scope as declaration scope. parse_info.set_function_syntax_kind(FunctionSyntaxKind::kWrapped); - parse_info.set_wrapped_arguments(arguments); // TODO(delphick): Remove this and instead make the wrapped and wrapper // functions fully non-lazy instead thus preventing source positions from // being omitted. parse_info.set_collect_source_positions(true); // parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile); + + MaybeHandle<ScopeInfo> maybe_outer_scope_info; if (!context->IsNativeContext()) { - parse_info.set_outer_scope_info(handle(context->scope_info(), isolate)); + maybe_outer_scope_info = handle(context->scope_info(), isolate); } - parse_info.set_language_mode( - stricter_language_mode(parse_info.language_mode(), language_mode)); + + script = NewScript(isolate, &parse_info, source, script_details, + origin_options, NOT_NATIVES_CODE); + script->set_wrapped_arguments(*arguments); Handle<SharedFunctionInfo> top_level; - maybe_result = - CompileToplevel(&parse_info, script, isolate, &is_compiled_scope); + maybe_result = CompileToplevel(&parse_info, script, maybe_outer_scope_info, + isolate, &is_compiled_scope); if (maybe_result.is_null()) isolate->ReportPendingMessages(); ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level, maybe_result, JSFunction); @@ -2208,59 +2392,107 @@ Compiler::GetSharedFunctionInfoForStreamedScript( isolate->counters()->total_compile_size()->Increment(source_length); BackgroundCompileTask* task = streaming_data->task.get(); - ParseInfo* parse_info = task->info(); - DCHECK(parse_info->is_toplevel()); + + MaybeHandle<SharedFunctionInfo> maybe_result; // Check if compile cache already holds the SFI, if so no need to finalize // the code compiled on the background thread. CompilationCache* compilation_cache = isolate->compilation_cache(); - MaybeHandle<SharedFunctionInfo> maybe_result = - compilation_cache->LookupScript( - source, script_details.name_obj, script_details.line_offset, - script_details.column_offset, origin_options, - isolate->native_context(), parse_info->language_mode()); - if (!maybe_result.is_null()) { - compile_timer.set_hit_isolate_cache(); + { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), + "V8.StreamingFinalization.CheckCache"); + maybe_result = compilation_cache->LookupScript( + source, script_details.name_obj, script_details.line_offset, + script_details.column_offset, origin_options, isolate->native_context(), + task->language_mode()); + if (!maybe_result.is_null()) { + compile_timer.set_hit_isolate_cache(); + } } if (maybe_result.is_null()) { - // No cache entry found, finalize compilation of the script and add it to - // the isolate cache. - Handle<Script> script = - NewScript(isolate, parse_info, source, script_details, origin_options, - NOT_NATIVES_CODE); - task->parser()->UpdateStatistics(isolate, script); - task->parser()->HandleSourceURLComments(isolate, script); - - if (parse_info->literal() == nullptr || !task->outer_function_job()) { - // Parsing has failed - report error messages. - FailWithPendingException(isolate, script, parse_info, - Compiler::ClearExceptionFlag::KEEP_EXCEPTION); + if (task->finalize_on_background_thread()) { + RuntimeCallTimerScope runtimeTimerScope( + isolate, RuntimeCallCounterId::kCompilePublishBackgroundFinalization); + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), + "V8.OffThreadFinalization.Publish"); + + Handle<SharedFunctionInfo> sfi(task->outer_function_sfi(), isolate); + Handle<Script> script(Script::cast(sfi->script()), isolate); + task->off_thread_isolate()->factory()->Publish(isolate); + + FixUpOffThreadAllocatedScript(isolate, script, source, script_details, + origin_options, NOT_NATIVES_CODE); + + // It's possible that source position collection was enabled after the + // background compile was started (for instance by enabling the cpu + // profiler), and the compiled bytecode is missing source positions. So, + // walk all the SharedFunctionInfos in the script and force source + // position collection. + if (!task->collected_source_positions() && + isolate->NeedsDetailedOptimizedCodeLineInfo()) { + Handle<WeakFixedArray> shared_function_infos( + script->shared_function_infos(isolate), isolate); + int length = shared_function_infos->length(); + FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i++, { + Object entry = shared_function_infos->Get(isolate, i) + .GetHeapObjectOrSmi(isolate); + if (entry.IsSharedFunctionInfo(isolate)) { + SharedFunctionInfo::EnsureSourcePositionsAvailable( + isolate, handle(SharedFunctionInfo::cast(entry), isolate)); + } + }); + } + + maybe_result = sfi; } else { - // Parsing has succeeded - finalize compilation. - maybe_result = FinalizeTopLevel(parse_info, script, isolate, - task->outer_function_job(), - task->inner_function_jobs()); - if (maybe_result.is_null()) { - // Finalization failed - throw an exception. + ParseInfo* parse_info = task->info(); + DCHECK(parse_info->is_toplevel()); + + // No cache entry found, finalize compilation of the script and add it to + // the isolate cache. + Handle<Script> script = + NewScript(isolate, parse_info, source, script_details, origin_options, + NOT_NATIVES_CODE); + task->parser()->UpdateStatistics(isolate, script); + task->parser()->HandleSourceURLComments(isolate, script); + + if (parse_info->literal() == nullptr || !task->outer_function_job()) { + // Parsing has failed - report error messages. FailWithPendingException(isolate, script, parse_info, Compiler::ClearExceptionFlag::KEEP_EXCEPTION); + } else { + // Parsing has succeeded - finalize compilation. + maybe_result = FinalizeTopLevel(parse_info, script, isolate, + task->outer_function_job(), + task->inner_function_jobs()); + if (maybe_result.is_null()) { + // Finalization failed - throw an exception. + FailWithPendingException( + isolate, script, parse_info, + Compiler::ClearExceptionFlag::KEEP_EXCEPTION); + } } } // Add compiled code to the isolate cache. Handle<SharedFunctionInfo> result; if (maybe_result.ToHandle(&result)) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), + "V8.StreamingFinalization.AddToCache"); compilation_cache->PutScript(source, isolate->native_context(), - parse_info->language_mode(), result); + task->language_mode(), result); } } + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), + "V8.StreamingFinalization.Release"); streaming_data->Release(); return maybe_result; } +template <typename LocalIsolate> Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( - FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) { + FunctionLiteral* literal, Handle<Script> script, LocalIsolate* isolate) { // Precondition: code has been parsed and scopes have been analyzed. MaybeHandle<SharedFunctionInfo> maybe_existing; @@ -2303,6 +2535,11 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( return result; } +template Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( + FunctionLiteral* literal, Handle<Script> script, Isolate* isolate); +template Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( + FunctionLiteral* literal, Handle<Script> script, OffThreadIsolate* isolate); + MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, BailoutId osr_offset, JavaScriptFrame* osr_frame) { @@ -2347,9 +2584,10 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job, isolate); InsertCodeIntoOptimizedCodeCache(compilation_info); if (FLAG_trace_opt) { - PrintF("[completed optimizing "); - compilation_info->closure()->ShortPrint(); - PrintF("]\n"); + CodeTracer::Scope scope(isolate->GetCodeTracer()); + PrintF(scope.file(), "[completed optimizing "); + compilation_info->closure()->ShortPrint(scope.file()); + PrintF(scope.file(), "]\n"); } compilation_info->closure()->set_code(*compilation_info->code()); return CompilationJob::SUCCEEDED; @@ -2358,9 +2596,10 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job, DCHECK_EQ(job->state(), CompilationJob::State::kFailed); if (FLAG_trace_opt) { - PrintF("[aborted optimizing "); - compilation_info->closure()->ShortPrint(); - PrintF(" because: %s]\n", + CodeTracer::Scope scope(isolate->GetCodeTracer()); + PrintF(scope.file(), "[aborted optimizing "); + compilation_info->closure()->ShortPrint(scope.file()); + PrintF(scope.file(), " because: %s]\n", GetBailoutReason(compilation_info->bailout_reason())); } compilation_info->closure()->set_code(shared->GetCode()); |