Index: src/compiler.cc |
diff --git a/src/compiler.cc b/src/compiler.cc |
index ee89ba8fe869c582cc808a61050052a3277fdb26..6f6f9bf9d2d96ec6400cff2acd5ad702f23666a3 100644 |
--- a/src/compiler.cc |
+++ b/src/compiler.cc |
@@ -38,8 +38,6 @@ |
namespace v8 { |
namespace internal { |
- |
- |
// A wrapper around a CompilationInfo that detaches the Handles from |
// the underlying DeferredHandleScope and stores them in info_ on |
// destruction. |
@@ -377,8 +375,7 @@ bool ShouldUseIgnition(CompilationInfo* info) { |
return shared->PassesFilter(FLAG_ignition_filter); |
} |
-CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info, |
- LazyCompilationMode mode) { |
+CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { |
// Function should have been parsed and analyzed before creating a compilation |
// job. |
DCHECK_NOT_NULL(info->literal()); |
@@ -386,9 +383,9 @@ CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info, |
EnsureFeedbackMetadata(info); |
if (ShouldUseIgnition(info)) { |
- return interpreter::Interpreter::NewCompilationJob(info, mode); |
+ return interpreter::Interpreter::NewCompilationJob(info); |
} else { |
- return FullCodeGenerator::NewCompilationJob(info, mode); |
+ return FullCodeGenerator::NewCompilationJob(info); |
} |
} |
@@ -437,6 +434,26 @@ CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { |
return status; |
} |
+bool Renumber(ParseInfo* parse_info) { |
+ if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), |
+ parse_info->literal(), |
+ parse_info->eager_inner_function_literals())) { |
+ return false; |
+ } |
+ Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); |
+ if (!shared_info.is_null()) { |
+ FunctionLiteral* lit = parse_info->literal(); |
+ shared_info->set_ast_node_count(lit->ast_node_count()); |
+ if (lit->dont_optimize_reason() != kNoReason) { |
+ shared_info->DisableOptimization(lit->dont_optimize_reason()); |
+ } |
+ if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) { |
+ shared_info->set_must_use_ignition_turbo(true); |
+ } |
+ } |
+ return true; |
+} |
+ |
bool GenerateUnoptimizedCode(CompilationInfo* info) { |
if (FLAG_validate_asm && info->scope()->asm_module() && |
!info->shared_info()->is_asm_wasm_broken() && !info->is_debug()) { |
@@ -451,8 +468,7 @@ bool GenerateUnoptimizedCode(CompilationInfo* info) { |
} |
} |
- std::unique_ptr<CompilationJob> job( |
- GetUnoptimizedCompilationJob(info, LazyCompilationMode::kIfRequested)); |
+ 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()) != |
@@ -462,14 +478,72 @@ bool GenerateUnoptimizedCode(CompilationInfo* info) { |
return true; |
} |
+bool CompileUnoptimizedInnerFunctionsRecursively( |
+ ZoneVector<FunctionLiteral*>* literals, CompilationInfo* outer_info) { |
+ Isolate* isolate = outer_info->isolate(); |
+ Handle<Script> script = outer_info->script(); |
+ |
+ for (auto it = literals->begin(); it != literals->end(); it++) { |
+ FunctionLiteral* literal = *it; |
+ |
+ // Find any previously allocated shared function info for the given literal. |
+ Handle<SharedFunctionInfo> shared; |
+ MaybeHandle<SharedFunctionInfo> maybe_existing = |
+ script->FindSharedFunctionInfo(isolate, literal); |
+ if (maybe_existing.ToHandle(&shared)) { |
+ DCHECK(!shared->is_toplevel()); |
+ // If we found an existing shared function info with compiled code, |
+ // we are done. |
+ if (shared->is_compiled()) continue; |
+ } else { |
+ shared = |
+ isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); |
+ shared->set_is_toplevel(false); |
+ } |
+ |
+ Zone zone(isolate->allocator(), ZONE_NAME); |
+ ParseInfo parse_info(&zone, script); |
marja
2017/01/05 19:25:22
It's weird | surprising that we need to create a n
rmcilroy
2017/01/06 17:08:14
Yes I agree this is a bit weird (it is a copy of t
|
+ parse_info.set_literal(literal); |
+ parse_info.set_shared_info(shared); |
+ parse_info.set_function_literal_id(shared->function_literal_id()); |
+ 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); |
+ |
+ CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
+ if (outer_info->will_serialize()) info.PrepareForSerializing(); |
+ if (outer_info->is_debug()) info.MarkAsDebug(); |
+ |
+ if (!Renumber(&parse_info) || |
+ !CompileUnoptimizedInnerFunctionsRecursively( |
+ parse_info.eager_inner_function_literals(), &info) || |
+ !GenerateUnoptimizedCode(&info)) { |
+ if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
+ return false; |
+ } |
+ |
+ DCHECK(!info.code().is_null()); |
+ RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info); |
+ if (literal->should_be_used_once_hint()) { |
+ info.code()->MarkToBeExecutedOnce(isolate); |
+ } |
+ } |
+ return true; |
+} |
+ |
bool CompileUnoptimizedCode(CompilationInfo* info) { |
- DCHECK(AllowCompilation::IsAllowed(info->isolate())); |
+ Isolate* isolate = info->isolate(); |
+ DCHECK(AllowCompilation::IsAllowed(isolate)); |
+ |
if (!Compiler::Analyze(info->parse_info()) || |
+ !CompileUnoptimizedInnerFunctionsRecursively( |
+ info->parse_info()->eager_inner_function_literals(), info) || |
!GenerateUnoptimizedCode(info)) { |
- Isolate* isolate = info->isolate(); |
if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
return false; |
} |
+ |
return true; |
} |
@@ -552,25 +626,6 @@ void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { |
literals, info->osr_ast_id()); |
} |
-bool Renumber(ParseInfo* parse_info) { |
- if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), |
- parse_info->literal())) { |
- return false; |
- } |
- Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); |
- if (!shared_info.is_null()) { |
- FunctionLiteral* lit = parse_info->literal(); |
- shared_info->set_ast_node_count(lit->ast_node_count()); |
- if (lit->dont_optimize_reason() != kNoReason) { |
- shared_info->DisableOptimization(lit->dont_optimize_reason()); |
- } |
- if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) { |
- shared_info->set_must_use_ignition_turbo(true); |
- } |
- } |
- return true; |
-} |
- |
bool GetOptimizedCodeNow(CompilationJob* job) { |
CompilationInfo* info = job->info(); |
Isolate* isolate = info->isolate(); |
@@ -1008,8 +1063,6 @@ Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { |
EnsureSharedFunctionInfosArrayOnScript(parse_info); |
- FunctionLiteral* lit = parse_info->literal(); |
- |
// Measure how long it takes to do the compilation; only take the |
// rest of the function into account to avoid overlap with the |
// parsing statistics. |
@@ -1024,6 +1077,7 @@ Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { |
parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile"); |
// Allocate a shared function info object. |
+ FunctionLiteral* lit = parse_info->literal(); |
DCHECK_EQ(kNoSourcePosition, lit->function_token_position()); |
result = isolate->factory()->NewSharedFunctionInfoForLiteral(lit, script); |
result->set_is_toplevel(true); |
@@ -1587,7 +1641,7 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript( |
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( |
FunctionLiteral* literal, Handle<Script> script, |
- CompilationInfo* outer_info, LazyCompilationMode mode) { |
+ CompilationInfo* outer_info) { |
// Precondition: code has been parsed and scopes have been analyzed. |
Isolate* isolate = outer_info->isolate(); |
MaybeHandle<SharedFunctionInfo> maybe_existing; |
@@ -1595,80 +1649,21 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( |
// Find any previously allocated shared function info for the given literal. |
maybe_existing = script->FindSharedFunctionInfo(isolate, literal); |
- // We found an existing shared function info. If it has any sort of code |
- // attached, don't worry about compiling and simply return it. Otherwise, |
- // continue to decide whether to eagerly compile. |
- // Note that we also carry on if we are compiling eager to obtain code for |
- // debugging, unless we already have code with debug break slots. |
+ // If we found an existing shared function info, return it. |
Handle<SharedFunctionInfo> existing; |
if (maybe_existing.ToHandle(&existing)) { |
DCHECK(!existing->is_toplevel()); |
- if (existing->HasBaselineCode() || existing->HasBytecodeArray()) { |
- if (!outer_info->is_debug() || existing->HasDebugCode()) { |
- return existing; |
- } |
- } |
- } |
- |
- // Allocate a shared function info object. |
- Handle<SharedFunctionInfo> result; |
- if (!maybe_existing.ToHandle(&result)) { |
- result = |
- isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); |
- result->set_is_toplevel(false); |
- } |
- |
- 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_function_literal_id(result->function_literal_id()); |
- 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(); |
- |
- // 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 (mode == LazyCompilationMode::kAlways || |
- !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(); |
- } |
- } |
+ return existing; |
jochen (gone - plz use gerrit)
2017/01/05 15:53:12
this might be wrong if we want debug code, but the
rmcilroy
2017/01/05 16:02:42
The debug code logic didn't do anything any longer
|
} |
- if (maybe_existing.is_null()) { |
- RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info); |
+ // Allocate a shared function info object which will be compiled lazily. |
+ Handle<SharedFunctionInfo> result = |
+ isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); |
jochen (gone - plz use gerrit)
2017/01/05 15:53:12
why don't you need to put the compile lazy builtin
rmcilroy
2017/01/05 16:02:42
I was confused by this too, but NewSharedFunctionI
|
+ result->set_is_toplevel(false); |
+ Scope* outer_scope = literal->scope()->GetOuterScopeWithContext(); |
+ if (outer_scope) { |
+ result->set_outer_scope_info(*outer_scope->scope_info()); |
} |
- |
return result; |
} |
@@ -1713,9 +1708,9 @@ MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, |
} |
CompilationJob* Compiler::PrepareUnoptimizedCompilationJob( |
- CompilationInfo* info, LazyCompilationMode mode) { |
+ CompilationInfo* info) { |
VMState<COMPILER> state(info->isolate()); |
- std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info, mode)); |
+ std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); |
if (job->PrepareJob() != CompilationJob::SUCCEEDED) { |
return nullptr; |
} |