Chromium Code Reviews| 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; | 
| } |