summaryrefslogtreecommitdiff
path: root/deps/v8/src/codegen/compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/codegen/compiler.cc')
-rw-r--r--deps/v8/src/codegen/compiler.cc489
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());