aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-02-14 11:27:26 +0100
committerMichaël Zasso <targos@protonmail.com>2017-02-22 15:55:42 +0100
commit7a77daf24344db7942e34c962b0f1ee729ab7af5 (patch)
treee7cbe7bf4e2f4b802a8f5bc18336c546cd6a0d7f /deps/v8/src/compiler.cc
parent5f08871ee93ea739148cc49e0f7679e33c70295a (diff)
downloadandroid-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.gz
android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.bz2
android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.zip
deps: update V8 to 5.6.326.55
PR-URL: https://github.com/nodejs/node/pull/10992 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/compiler.cc')
-rw-r--r--deps/v8/src/compiler.cc590
1 files changed, 199 insertions, 391 deletions
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
index ec402fa822..3435f530c2 100644
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -20,7 +20,6 @@
#include "src/crankshaft/hydrogen.h"
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
-#include "src/deoptimizer.h"
#include "src/frames-inl.h"
#include "src/full-codegen/full-codegen.h"
#include "src/globals.h"
@@ -251,22 +250,6 @@ void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
namespace {
-bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
- return shared->is_toplevel() && shared->script()->IsScript() &&
- Script::cast(shared->script())->compilation_type() ==
- Script::COMPILATION_TYPE_EVAL;
-}
-
-bool Parse(ParseInfo* info) {
- // Create a canonical handle scope if compiling ignition bytecode. This is
- // required by the constant array builder to de-duplicate objects without
- // dereferencing handles.
- std::unique_ptr<CanonicalHandleScope> canonical;
- if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info->isolate()));
-
- return Parser::ParseStatic(info);
-}
-
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
CompilationInfo* info) {
// Log the code generation. If source information is available include
@@ -320,21 +303,46 @@ void EnsureFeedbackMetadata(CompilationInfo* info) {
info->literal()->feedback_vector_spec()));
}
-bool ShouldUseIgnition(CompilationInfo* info) {
- if (!FLAG_ignition) return false;
+bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
+ bool optimization_disabled = shared->optimization_disabled();
+ bool dont_crankshaft = shared->dont_crankshaft();
+
+ // Check the enabling conditions for Turbofan.
+ // 1. "use asm" code.
+ bool is_turbofanable_asm =
+ FLAG_turbo_asm && shared->asm_function() && !optimization_disabled;
+ // 2. Fallback for features unsupported by Crankshaft.
+ bool is_unsupported_by_crankshaft_but_turbofanable =
+ dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
+ !optimization_disabled;
+
+ // 3. Explicitly enabled by the command-line filter.
+ bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);
+
+ return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
+ passes_turbo_filter;
+}
+
+bool ShouldUseIgnition(CompilationInfo* info) {
DCHECK(info->has_shared_info());
+ // Skip Ignition for asm.js functions.
+ if (info->shared_info()->asm_function()) {
+ return false;
+ }
+
// When requesting debug code as a replacement for existing code, we provide
// the same kind as the existing code (to prevent implicit tier-change).
if (info->is_debug() && info->shared_info()->is_compiled()) {
return !info->shared_info()->HasBaselineCode();
}
- // Since we can't OSR from Ignition, skip Ignition for asm.js functions.
- if (info->shared_info()->asm_function()) {
- return false;
- }
+ // Code destined for TurboFan should be compiled with Ignition first.
+ if (UseTurboFan(info->shared_info())) return true;
+
+ // Only use Ignition for any other function if FLAG_ignition is true.
+ if (!FLAG_ignition) return false;
// Checks whether top level functions should be passed by the filter.
if (info->shared_info()->is_toplevel()) {
@@ -360,38 +368,6 @@ CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) {
}
}
-bool GenerateUnoptimizedCode(CompilationInfo* info) {
- if (FLAG_validate_asm && info->scope()->asm_module() &&
- !info->shared_info()->is_asm_wasm_broken()) {
- EnsureFeedbackMetadata(info);
- MaybeHandle<FixedArray> wasm_data;
- wasm_data = AsmJs::ConvertAsmToWasm(info->parse_info());
- if (!wasm_data.is_null()) {
- info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked());
- info->SetCode(info->isolate()->builtins()->InstantiateAsmJs());
- return true;
- }
- }
-
- std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info));
- if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
- if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false;
- if (job->FinalizeJob() != CompilationJob::SUCCEEDED) return false;
- job->RecordUnoptimizedCompilationStats();
- return true;
-}
-
-bool CompileUnoptimizedCode(CompilationInfo* info) {
- DCHECK(AllowCompilation::IsAllowed(info->isolate()));
- if (!Compiler::Analyze(info->parse_info()) ||
- !GenerateUnoptimizedCode(info)) {
- Isolate* isolate = info->isolate();
- if (!isolate->has_pending_exception()) isolate->StackOverflow();
- return false;
- }
- return true;
-}
-
void InstallSharedScopeInfo(CompilationInfo* info,
Handle<SharedFunctionInfo> shared) {
Handle<ScopeInfo> scope_info = info->scope()->scope_info();
@@ -426,9 +402,50 @@ void InstallUnoptimizedCode(CompilationInfo* info) {
// Install compilation result on the shared function info
InstallSharedCompilationResult(info, shared);
+}
- // Record the function compilation event.
- RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
+CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) {
+ CompilationJob::Status status = job->FinalizeJob();
+ if (status == CompilationJob::SUCCEEDED) {
+ InstallUnoptimizedCode(job->info());
+ job->RecordUnoptimizedCompilationStats();
+ }
+ return status;
+}
+
+bool GenerateUnoptimizedCode(CompilationInfo* info) {
+ if (FLAG_validate_asm && info->scope()->asm_module() &&
+ !info->shared_info()->is_asm_wasm_broken() && !info->is_debug()) {
+ EnsureFeedbackMetadata(info);
+ MaybeHandle<FixedArray> wasm_data;
+ wasm_data = AsmJs::ConvertAsmToWasm(info->parse_info());
+ if (!wasm_data.is_null()) {
+ info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked());
+ info->SetCode(info->isolate()->builtins()->InstantiateAsmJs());
+ InstallUnoptimizedCode(info);
+ return true;
+ }
+ }
+
+ std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info));
+ if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
+ if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false;
+ if (FinalizeUnoptimizedCompilationJob(job.get()) !=
+ CompilationJob::SUCCEEDED) {
+ return false;
+ }
+ return true;
+}
+
+bool CompileUnoptimizedCode(CompilationInfo* info) {
+ DCHECK(AllowCompilation::IsAllowed(info->isolate()));
+ if (!Compiler::Analyze(info->parse_info()) ||
+ !GenerateUnoptimizedCode(info)) {
+ Isolate* isolate = info->isolate();
+ if (!isolate->has_pending_exception()) isolate->StackOverflow();
+ return false;
+ }
+ return true;
}
MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) {
@@ -436,28 +453,19 @@ MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) {
PostponeInterruptsScope postpone(info->isolate());
// Parse and update CompilationInfo with the results.
- if (!Parse(info->parse_info())) return MaybeHandle<Code>();
+ if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
DCHECK_EQ(info->shared_info()->language_mode(),
info->literal()->language_mode());
// Compile either unoptimized code or bytecode for the interpreter.
if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>();
- InstallUnoptimizedCode(info);
+ // Record the function compilation event.
+ RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
return info->code();
}
-CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) {
- CompilationJob::Status status = job->FinalizeJob();
- if (status == CompilationJob::SUCCEEDED) {
- DCHECK(!job->info()->shared_info()->is_compiled());
- InstallUnoptimizedCode(job->info());
- job->RecordUnoptimizedCompilationStats();
- }
- return status;
-}
-
MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
Handle<JSFunction> function, BailoutId osr_ast_id) {
Handle<SharedFunctionInfo> shared(function->shared());
@@ -495,29 +503,9 @@ void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
Handle<Context> native_context(function->context()->native_context());
SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
literals, info->osr_ast_id());
-
- // Do not cache (native) context-independent code compiled for OSR.
- if (code->is_turbofanned() && info->is_osr()) return;
-
- // Cache optimized (native) context-independent code.
- if (FLAG_turbo_cache_shared_code && code->is_turbofanned() &&
- !info->is_native_context_specializing()) {
- DCHECK(!info->is_function_context_specializing());
- DCHECK(info->osr_ast_id().IsNone());
- Handle<SharedFunctionInfo> shared(function->shared());
- SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code);
- }
}
bool Renumber(ParseInfo* parse_info) {
- // Create a canonical handle scope if compiling ignition bytecode. This is
- // required by the constant array builder to de-duplicate objects without
- // dereferencing handles.
- std::unique_ptr<CanonicalHandleScope> canonical;
- if (FLAG_ignition) {
- canonical.reset(new CanonicalHandleScope(parse_info->isolate()));
- }
-
if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
parse_info->literal())) {
return false;
@@ -536,27 +524,6 @@ bool Renumber(ParseInfo* parse_info) {
return true;
}
-bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
- bool optimization_disabled = shared->optimization_disabled();
- bool dont_crankshaft = shared->dont_crankshaft();
-
- // Check the enabling conditions for Turbofan.
- // 1. "use asm" code.
- bool is_turbofanable_asm =
- FLAG_turbo_asm && shared->asm_function() && !optimization_disabled;
-
- // 2. Fallback for features unsupported by Crankshaft.
- bool is_unsupported_by_crankshaft_but_turbofanable =
- dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
- !optimization_disabled;
-
- // 3. Explicitly enabled by the command-line filter.
- bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);
-
- return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
- passes_turbo_filter;
-}
-
bool GetOptimizedCodeNow(CompilationJob* job) {
CompilationInfo* info = job->info();
Isolate* isolate = info->isolate();
@@ -652,8 +619,8 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
DCHECK_IMPLIES(ignition_osr, !osr_ast_id.IsNone());
DCHECK_IMPLIES(ignition_osr, FLAG_ignition_osr);
- // Flag combination --ignition-osr --no-turbo-from-bytecode is unsupported.
- if (ignition_osr && !FLAG_turbo_from_bytecode) return MaybeHandle<Code>();
+ // Shared function no longer needs to be tiered up
+ shared->set_marked_for_tier_up(false);
Handle<Code> cached_code;
// TODO(4764): When compiling for OSR from bytecode, BailoutId might derive
@@ -673,8 +640,10 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
}
// Reset profiler ticks, function is no longer considered hot.
- if (shared->is_compiled()) {
+ if (shared->HasBaselineCode()) {
shared->code()->set_profiler_ticks(0);
+ } else if (shared->HasBytecodeArray()) {
+ shared->set_profiler_ticks(0);
}
VMState<COMPILER> state(isolate);
@@ -708,7 +677,7 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
// TurboFan can optimize directly from existing bytecode.
- if (FLAG_turbo_from_bytecode && use_turbofan && ShouldUseIgnition(info)) {
+ if (use_turbofan && ShouldUseIgnition(info)) {
if (info->is_osr() && !ignition_osr) return MaybeHandle<Code>();
if (!Compiler::EnsureBytecode(info)) {
if (isolate->has_pending_exception()) isolate->clear_pending_exception();
@@ -717,14 +686,6 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
info->MarkAsOptimizeFromBytecode();
}
- if (IsEvalToplevel(shared)) {
- parse_info->set_eval();
- if (function->context()->IsNativeContext()) parse_info->set_global();
- parse_info->set_toplevel();
- parse_info->set_allow_lazy_parsing(false);
- parse_info->set_lazy(false);
- }
-
// Verify that OSR compilations are delegated to the correct graph builder.
// Depending on the underlying frame the semantics of the {BailoutId} differ
// and the various graph builders hard-code a certain semantic:
@@ -775,7 +736,13 @@ CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) {
"V8.RecompileSynchronous");
Handle<SharedFunctionInfo> shared = info->shared_info();
- shared->code()->set_profiler_ticks(0);
+
+ // Reset profiler ticks, function is no longer considered hot.
+ if (shared->HasBaselineCode()) {
+ shared->code()->set_profiler_ticks(0);
+ } else if (shared->HasBytecodeArray()) {
+ shared->set_profiler_ticks(0);
+ }
DCHECK(!shared->HasDebugInfo());
@@ -818,84 +785,17 @@ CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) {
return CompilationJob::FAILED;
}
-class InterpreterActivationsFinder : public ThreadVisitor,
- public OptimizedFunctionVisitor {
- public:
- explicit InterpreterActivationsFinder(SharedFunctionInfo* shared)
- : shared_(shared), has_activations_(false) {}
-
- void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
- Address* activation_pc_address = nullptr;
- JavaScriptFrameIterator it(isolate, top);
- for (; !it.done(); it.Advance()) {
- JavaScriptFrame* frame = it.frame();
- if (FLAG_turbo_from_bytecode && FLAG_ignition_osr &&
- frame->is_optimized() && frame->function()->shared() == shared_) {
- // If we are able to optimize functions directly from bytecode, then
- // there might be optimized OSR code active on the stack that is not
- // reachable through a function. We count this as an activation.
- has_activations_ = true;
- }
- if (frame->is_interpreted() && frame->function()->shared() == shared_) {
- has_activations_ = true;
- activation_pc_address = frame->pc_address();
- }
- }
-
- if (activation_pc_address) {
- activation_pc_addresses_.push_back(activation_pc_address);
- }
- }
-
- void VisitFunction(JSFunction* function) {
- if (function->Inlines(shared_)) has_activations_ = true;
- }
-
- void EnterContext(Context* context) {}
- void LeaveContext(Context* context) {}
-
- bool MarkActivationsForBaselineOnReturn(Isolate* isolate) {
- if (activation_pc_addresses_.empty()) return false;
-
- for (Address* activation_pc_address : activation_pc_addresses_) {
- DCHECK(isolate->inner_pointer_to_code_cache()
- ->GetCacheEntry(*activation_pc_address)
- ->code->is_interpreter_trampoline_builtin());
- *activation_pc_address =
- isolate->builtins()->InterpreterMarkBaselineOnReturn()->entry();
- }
- return true;
- }
-
- bool has_activations() { return has_activations_; }
-
- private:
- SharedFunctionInfo* shared_;
- bool has_activations_;
- std::vector<Address*> activation_pc_addresses_;
-};
-
-bool HasInterpreterActivations(
- Isolate* isolate, InterpreterActivationsFinder* activations_finder) {
- activations_finder->VisitThread(isolate, isolate->thread_local_top());
- isolate->thread_manager()->IterateArchivedThreads(activations_finder);
- if (FLAG_turbo_from_bytecode) {
- // If we are able to optimize functions directly from bytecode, then there
- // might be optimized functions that rely on bytecode being around. We need
- // to prevent switching the given function to baseline code in those cases.
- Deoptimizer::VisitAllOptimizedFunctions(isolate, activations_finder);
- }
- return activations_finder->has_activations();
-}
-
MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
Isolate* isolate = function->GetIsolate();
VMState<COMPILER> state(isolate);
PostponeInterruptsScope postpone(isolate);
- Zone zone(isolate->allocator());
- ParseInfo parse_info(&zone, function);
+ Zone zone(isolate->allocator(), ZONE_NAME);
+ ParseInfo parse_info(&zone, handle(function->shared()));
CompilationInfo info(&parse_info, function);
+ // Function no longer needs to be tiered up
+ function->shared()->set_marked_for_tier_up(false);
+
// Reset profiler ticks, function is no longer considered hot.
if (function->shared()->HasBytecodeArray()) {
function->shared()->set_profiler_ticks(0);
@@ -920,31 +820,6 @@ MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
return MaybeHandle<Code>();
}
- // TODO(4280): For now we disable switching to baseline code in the presence
- // of interpreter activations of the given function. The reasons is that the
- // underlying bytecode is cleared below. Note that this only applies in case
- // the --ignition-preserve-bytecode flag is not passed.
- if (!FLAG_ignition_preserve_bytecode) {
- InterpreterActivationsFinder activations_finder(function->shared());
- if (HasInterpreterActivations(isolate, &activations_finder)) {
- if (FLAG_trace_opt) {
- OFStream os(stdout);
- os << "[unable to switch " << Brief(*function) << " due to activations]"
- << std::endl;
- }
-
- if (activations_finder.MarkActivationsForBaselineOnReturn(isolate)) {
- if (FLAG_trace_opt) {
- OFStream os(stdout);
- os << "[marking " << Brief(function->shared())
- << " for baseline recompilation on return]" << std::endl;
- }
- }
-
- return MaybeHandle<Code>();
- }
- }
-
if (FLAG_trace_opt) {
OFStream os(stdout);
os << "[switching method " << Brief(*function) << " to baseline code]"
@@ -952,7 +827,7 @@ MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
}
// Parse and update CompilationInfo with the results.
- if (!Parse(info.parse_info())) return MaybeHandle<Code>();
+ if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>();
Handle<SharedFunctionInfo> shared = info.shared_info();
DCHECK_EQ(shared->language_mode(), info.literal()->language_mode());
@@ -963,12 +838,6 @@ MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
return MaybeHandle<Code>();
}
- // TODO(4280): For now we play it safe and remove the bytecode array when we
- // switch to baseline code. We might consider keeping around the bytecode so
- // that it can be used as the "source of truth" eventually. Note that this
- // only applies in case the --ignition-preserve-bytecode flag is not passed.
- if (!FLAG_ignition_preserve_bytecode) shared->ClearBytecodeArray();
-
// Update the shared function info with the scope info.
InstallSharedScopeInfo(&info, shared);
@@ -1003,6 +872,46 @@ MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
return cached_code;
}
+ if (function->shared()->marked_for_tier_up()) {
+ DCHECK(FLAG_mark_shared_functions_for_tier_up);
+
+ function->shared()->set_marked_for_tier_up(false);
+
+ switch (Compiler::NextCompilationTier(*function)) {
+ case Compiler::BASELINE: {
+ if (FLAG_trace_opt) {
+ PrintF("[recompiling function ");
+ function->ShortPrint();
+ PrintF(
+ " to baseline eagerly (shared function marked for tier up)]\n");
+ }
+
+ Handle<Code> code;
+ if (GetBaselineCode(function).ToHandle(&code)) {
+ return code;
+ }
+ break;
+ }
+ case Compiler::OPTIMIZED: {
+ if (FLAG_trace_opt) {
+ PrintF("[optimizing method ");
+ function->ShortPrint();
+ PrintF(" eagerly (shared function marked for tier up)]\n");
+ }
+
+ Handle<Code> code;
+ // TODO(leszeks): Look into performing this compilation concurrently.
+ if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
+ .ToHandle(&code)) {
+ return code;
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+
if (function->shared()->is_compiled()) {
return Handle<Code>(function->shared()->code());
}
@@ -1013,8 +922,8 @@ MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
return entry;
}
- Zone zone(isolate->allocator());
- ParseInfo parse_info(&zone, function);
+ Zone zone(isolate->allocator(), ZONE_NAME);
+ ParseInfo parse_info(&zone, handle(function->shared()));
CompilationInfo info(&parse_info, function);
Handle<Code> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCode(&info), Code);
@@ -1059,50 +968,13 @@ Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
isolate->debug()->OnBeforeCompile(script);
- DCHECK(parse_info->is_eval() || parse_info->is_global() ||
- parse_info->is_module());
-
- parse_info->set_toplevel();
-
Handle<SharedFunctionInfo> result;
{ VMState<COMPILER> state(info->isolate());
- if (parse_info->literal() == NULL) {
- // Parse the script if needed (if it's already parsed, literal() is
- // non-NULL). If compiling for debugging, we may eagerly compile inner
- // functions, so do not parse lazily in that case.
- ScriptCompiler::CompileOptions options = parse_info->compile_options();
- bool parse_allow_lazy = (options == ScriptCompiler::kConsumeParserCache ||
- String::cast(script->source())->length() >
- FLAG_min_preparse_length) &&
- !info->is_debug();
-
- // Consider parsing eagerly when targeting the code cache.
- parse_allow_lazy &= !(FLAG_serialize_eager && info->will_serialize());
-
- // Consider parsing eagerly when targeting Ignition.
- parse_allow_lazy &= !(FLAG_ignition && FLAG_ignition_eager &&
- !isolate->serializer_enabled());
-
- parse_info->set_allow_lazy_parsing(parse_allow_lazy);
- if (!parse_allow_lazy &&
- (options == ScriptCompiler::kProduceParserCache ||
- options == ScriptCompiler::kConsumeParserCache)) {
- // We are going to parse eagerly, but we either 1) have cached data
- // produced by lazy parsing or 2) are asked to generate cached data.
- // Eager parsing cannot benefit from cached data, and producing cached
- // data while parsing eagerly is not implemented.
- parse_info->set_cached_data(nullptr);
- parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions);
- }
-
- if (!Parse(parse_info)) {
- return Handle<SharedFunctionInfo>::null();
- }
+ if (parse_info->literal() == nullptr && !Parser::ParseStatic(parse_info)) {
+ return Handle<SharedFunctionInfo>::null();
}
- DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing());
-
FunctionLiteral* lit = parse_info->literal();
// Measure how long it takes to do the compilation; only take the
@@ -1122,10 +994,6 @@ Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
DCHECK_EQ(kNoSourcePosition, lit->function_token_position());
result = NewSharedFunctionInfoForLiteral(isolate, lit, script);
result->set_is_toplevel(true);
- if (parse_info->is_eval()) {
- // Eval scripts cannot be (re-)compiled without context.
- result->set_allows_lazy_compilation_without_context(false);
- }
parse_info->set_shared_info(result);
// Compile the code.
@@ -1133,12 +1001,6 @@ Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
return Handle<SharedFunctionInfo>::null();
}
- // Update the shared function info with the scope info.
- InstallSharedScopeInfo(info, result);
-
- // Install compilation result on the shared function info
- InstallSharedCompilationResult(info, result);
-
Handle<String> script_name =
script->name()->IsString()
? Handle<String>(String::cast(script->name()))
@@ -1173,7 +1035,7 @@ bool Compiler::Analyze(ParseInfo* info) {
}
bool Compiler::ParseAndAnalyze(ParseInfo* info) {
- if (!Parse(info)) return false;
+ if (!Parser::ParseStatic(info)) return false;
if (!Compiler::Analyze(info)) return false;
DCHECK_NOT_NULL(info->literal());
DCHECK_NOT_NULL(info->scope());
@@ -1246,8 +1108,8 @@ bool Compiler::CompileOptimized(Handle<JSFunction> function,
code = isolate->builtins()->InterpreterEntryTrampoline();
function->shared()->ReplaceCode(*code);
} else {
- Zone zone(isolate->allocator());
- ParseInfo parse_info(&zone, function);
+ Zone zone(isolate->allocator(), ZONE_NAME);
+ ParseInfo parse_info(&zone, handle(function->shared()));
CompilationInfo info(&parse_info, function);
if (!GetUnoptimizedCode(&info).ToHandle(&code)) {
return false;
@@ -1266,44 +1128,14 @@ bool Compiler::CompileOptimized(Handle<JSFunction> function,
return true;
}
-bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
- Isolate* isolate = function->GetIsolate();
- DCHECK(AllowCompilation::IsAllowed(isolate));
-
- // Start a compilation.
- Zone zone(isolate->allocator());
- ParseInfo parse_info(&zone, function);
- CompilationInfo info(&parse_info, Handle<JSFunction>::null());
- if (IsEvalToplevel(handle(function->shared()))) {
- parse_info.set_eval();
- if (function->context()->IsNativeContext()) parse_info.set_global();
- parse_info.set_toplevel();
- parse_info.set_allow_lazy_parsing(false);
- parse_info.set_lazy(false);
- }
- info.MarkAsDebug();
- if (GetUnoptimizedCode(&info).is_null()) {
- isolate->clear_pending_exception();
- return false;
- }
-
- // Check postconditions on success.
- DCHECK(!isolate->has_pending_exception());
- DCHECK(function->shared()->is_compiled());
- DCHECK(function->shared()->HasDebugCode());
- return true;
-}
-
bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
Isolate* isolate = shared->GetIsolate();
DCHECK(AllowCompilation::IsAllowed(isolate));
// Start a compilation.
- Zone zone(isolate->allocator());
+ Zone zone(isolate->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, shared);
CompilationInfo info(&parse_info, Handle<JSFunction>::null());
- DCHECK(shared->allows_lazy_compilation_without_context());
- DCHECK(!IsEvalToplevel(shared));
info.MarkAsDebug();
if (GetUnoptimizedCode(&info).is_null()) {
isolate->clear_pending_exception();
@@ -1325,13 +1157,12 @@ MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
// generated shared function infos, clear the script's list temporarily
// and restore it at the end of this method.
Handle<Object> old_function_infos(script->shared_function_infos(), isolate);
- script->set_shared_function_infos(Smi::FromInt(0));
+ script->set_shared_function_infos(Smi::kZero);
// Start a compilation.
- Zone zone(isolate->allocator());
+ Zone zone(isolate->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, script);
CompilationInfo info(&parse_info, Handle<JSFunction>::null());
- parse_info.set_global();
info.MarkAsDebug();
// TODO(635): support extensions.
@@ -1377,7 +1208,7 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
DCHECK_NOT_NULL(info->scope());
Handle<SharedFunctionInfo> shared = info->shared_info();
if (!shared->has_deoptimization_support()) {
- Zone zone(info->isolate()->allocator());
+ Zone zone(info->isolate()->allocator(), ZONE_NAME);
CompilationInfo unoptimized(info->parse_info(), info->closure());
unoptimized.EnableDeoptimizationSupport();
@@ -1387,18 +1218,9 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
// TurboFan in this case.
if (IsResumableFunction(shared->kind())) return false;
- // TODO(4280): For now we disable switching to baseline code in the presence
- // of interpreter activations of the given function. The reasons is that the
- // underlying bytecode is cleared below. The expensive check for activations
- // only needs to be done when the given function has bytecode, otherwise we
- // can be sure there are no activations. Note that this only applies in case
- // the --ignition-preserve-bytecode flag is not passed.
- if (!FLAG_ignition_preserve_bytecode && shared->HasBytecodeArray()) {
- InterpreterActivationsFinder activations_finder(*shared);
- if (HasInterpreterActivations(info->isolate(), &activations_finder)) {
- return false;
- }
- }
+ // When we call PrepareForSerializing below, we will change the shared
+ // ParseInfo. Make sure to reset it.
+ bool old_will_serialize_value = info->parse_info()->will_serialize();
// If the current code has reloc info for serialization, also include
// reloc info for serialization for the new code, so that deopt support
@@ -1410,13 +1232,7 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
EnsureFeedbackMetadata(&unoptimized);
if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
- // TODO(4280): For now we play it safe and remove the bytecode array when we
- // switch to baseline code. We might consider keeping around the bytecode so
- // that it can be used as the "source of truth" eventually. Note that this
- // only applies in case the --ignition-preserve-bytecode flag is not passed.
- if (!FLAG_ignition_preserve_bytecode && shared->HasBytecodeArray()) {
- shared->ClearBytecodeArray();
- }
+ info->parse_info()->set_will_serialize(old_will_serialize_value);
// The scope info might not have been set if a lazily compiled
// function is inlined before being called for the first time.
@@ -1437,8 +1253,8 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
// static
Compiler::CompilationTier Compiler::NextCompilationTier(JSFunction* function) {
Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
- if (shared->code()->is_interpreter_trampoline_builtin()) {
- if (FLAG_turbo_from_bytecode && UseTurboFan(shared)) {
+ if (shared->IsInterpreted()) {
+ if (UseTurboFan(shared)) {
return OPTIMIZED;
} else {
return BASELINE;
@@ -1468,6 +1284,7 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
Handle<Script> script;
if (!maybe_shared_info.ToHandle(&shared_info)) {
script = isolate->factory()->NewScript(source);
+ if (FLAG_trace_deopt) Script::InitLineEnds(script);
if (!script_name.is_null()) {
script->set_name(*script_name);
script->set_line_offset(line_offset);
@@ -1477,11 +1294,10 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
Script::SetEvalOrigin(script, outer_info, eval_position);
- Zone zone(isolate->allocator());
+ Zone zone(isolate->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, script);
CompilationInfo info(&parse_info, Handle<JSFunction>::null());
parse_info.set_eval();
- if (context->IsNativeContext()) parse_info.set_global();
parse_info.set_language_mode(language_mode);
parse_info.set_parse_restriction(restriction);
if (!context->IsNativeContext()) {
@@ -1628,6 +1444,7 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
// Create a script object describing the script to be compiled.
Handle<Script> script = isolate->factory()->NewScript(source);
+ if (FLAG_trace_deopt) Script::InitLineEnds(script);
if (natives == NATIVES_CODE) {
script->set_type(Script::TYPE_NATIVE);
script->set_hide_source(true);
@@ -1646,14 +1463,10 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
}
// Compile the function and add it to the cache.
- Zone zone(isolate->allocator());
+ Zone zone(isolate->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, script);
CompilationInfo info(&parse_info, Handle<JSFunction>::null());
- if (is_module) {
- parse_info.set_module();
- } else {
- parse_info.set_global();
- }
+ if (is_module) parse_info.set_module();
if (compile_options != ScriptCompiler::kNoCompileOptions) {
parse_info.set_cached_data(cached_data);
}
@@ -1766,59 +1579,49 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
result->set_never_compiled(outer_info->shared_info()->never_compiled());
}
- Zone zone(isolate->allocator());
+ Zone zone(isolate->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, script);
CompilationInfo info(&parse_info, Handle<JSFunction>::null());
parse_info.set_literal(literal);
parse_info.set_shared_info(result);
parse_info.set_language_mode(literal->scope()->language_mode());
+ parse_info.set_ast_value_factory(
+ outer_info->parse_info()->ast_value_factory());
+ parse_info.set_ast_value_factory_owned(false);
+
if (outer_info->will_serialize()) info.PrepareForSerializing();
if (outer_info->is_debug()) info.MarkAsDebug();
- // Determine if the function can be lazily compiled. This is necessary to
- // allow some of our builtin JS files to be lazily compiled. These
- // builtins cannot be handled lazily by the parser, since we have to know
- // if a function uses the special natives syntax, which is something the
- // parser records.
- // If the debugger requests compilation for break points, we cannot be
- // aggressive about lazy compilation, because it might trigger compilation
- // of functions without an outer context when setting a breakpoint through
- // Debug::FindSharedFunctionInfoInScript.
- bool allow_lazy = literal->AllowsLazyCompilation() && !info.is_debug();
- bool lazy = FLAG_lazy && allow_lazy && !literal->should_eager_compile();
-
- // Consider compiling eagerly when targeting the code cache.
- lazy &= !(FLAG_serialize_eager && info.will_serialize());
-
- // Consider compiling eagerly when compiling bytecode for Ignition.
- lazy &=
- !(FLAG_ignition && FLAG_ignition_eager && !isolate->serializer_enabled());
-
- // Generate code
- TimerEventScope<TimerEventCompileCode> timer(isolate);
- RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode);
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
-
- if (lazy) {
- info.SetCode(isolate->builtins()->CompileLazy());
- Scope* outer_scope = literal->scope()->GetOuterScopeWithContext();
- if (outer_scope) {
- result->set_outer_scope_info(*outer_scope->scope_info());
- }
- } else if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) {
- // Code generation will ensure that the feedback vector is present and
- // appropriately sized.
- DCHECK(!info.code().is_null());
- if (literal->should_eager_compile() &&
- literal->should_be_used_once_hint()) {
- info.code()->MarkToBeExecutedOnce(isolate);
+ // If this inner function is already compiled, we don't need to compile
+ // again. When compiling for debug, we are not interested in having debug
+ // break slots in inner functions, neither for setting break points nor
+ // for revealing inner functions.
+ // This is especially important for generators. We must not replace the
+ // code for generators, as there may be suspended generator objects.
+ if (!result->is_compiled()) {
+ if (!literal->ShouldEagerCompile()) {
+ info.SetCode(isolate->builtins()->CompileLazy());
+ Scope* outer_scope = literal->scope()->GetOuterScopeWithContext();
+ if (outer_scope) {
+ result->set_outer_scope_info(*outer_scope->scope_info());
+ }
+ } else {
+ // Generate code
+ TimerEventScope<TimerEventCompileCode> timer(isolate);
+ RuntimeCallTimerScope runtimeTimer(isolate,
+ &RuntimeCallStats::CompileCode);
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
+ if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) {
+ // Code generation will ensure that the feedback vector is present and
+ // appropriately sized.
+ DCHECK(!info.code().is_null());
+ if (literal->should_be_used_once_hint()) {
+ info.code()->MarkToBeExecutedOnce(isolate);
+ }
+ } else {
+ return Handle<SharedFunctionInfo>::null();
+ }
}
- // Update the shared function info with the scope info.
- InstallSharedScopeInfo(&info, result);
- // Install compilation result on the shared function info.
- InstallSharedCompilationResult(&info, result);
- } else {
- return Handle<SharedFunctionInfo>::null();
}
if (maybe_existing.is_null()) {
@@ -1887,8 +1690,13 @@ bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
return FinalizeOptimizedCompilationJob(job.get()) ==
CompilationJob::SUCCEEDED;
} else {
- return FinalizeUnoptimizedCompilationJob(job.get()) ==
- CompilationJob::SUCCEEDED;
+ if (FinalizeUnoptimizedCompilationJob(job.get()) ==
+ CompilationJob::SUCCEEDED) {
+ RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
+ job->info());
+ return true;
+ }
+ return false;
}
}