Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Unified Diff: src/compiler.cc

Issue 1809403002: [compiler] Readability refactor of comilation pipeline. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler.cc
diff --git a/src/compiler.cc b/src/compiler.cc
index 6275fcc45cc1c28a362aec20fa546d36915d16a6..b124e2b90e3800cd7d9f1ef8c7407191a33e79c2 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -101,6 +101,8 @@ class CompilationInfoWithZone : public CompilationInfo {
Zone zone_;
};
+// ----------------------------------------------------------------------------
+// Implementation of CompilationInfo
bool CompilationInfo::has_shared_info() const {
return parse_info_ && !parse_info_->shared_info().is_null();
@@ -329,6 +331,15 @@ bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
return is_sloppy(language_mode()) && !is_native();
}
+#if DEBUG
+void CompilationInfo::PrintAstForTesting() {
+ PrintF("--- Source from AST ---\n%s\n",
+ PrettyPrinter(isolate()).PrintProgram(literal()));
+}
+#endif
+
+// ----------------------------------------------------------------------------
+// Implementation of OptimizedCompileJob
class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
public:
@@ -713,6 +724,10 @@ void OptimizedCompileJob::RecordOptimizationStats() {
}
}
+// ----------------------------------------------------------------------------
+// Local helper methods that make up the compilation pipeline.
+
+namespace {
// Sets the expected number of properties based on estimate from compiler.
void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
@@ -735,18 +750,16 @@ void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
shared->set_expected_nof_properties(estimate);
}
-
-static void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info,
- BailoutReason bailout_reason) {
+void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info,
+ BailoutReason bailout_reason) {
if (bailout_reason != kNoReason) {
shared_info->DisableOptimization(bailout_reason);
}
}
-
-static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
- CompilationInfo* info,
- Handle<SharedFunctionInfo> shared) {
+void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
+ CompilationInfo* info,
+ Handle<SharedFunctionInfo> shared) {
// SharedFunctionInfo is passed separately, because if CompilationInfo
// was created using Script object, it will not have it.
@@ -774,7 +787,7 @@ static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
}
}
-static bool CompileUnoptimizedCode(CompilationInfo* info) {
+bool CompileUnoptimizedCode(CompilationInfo* info) {
DCHECK(AllowCompilation::IsAllowed(info->isolate()));
if (!Compiler::Analyze(info->parse_info()) ||
!FullCodeGenerator::MakeCode(info)) {
@@ -785,7 +798,7 @@ static bool CompileUnoptimizedCode(CompilationInfo* info) {
return true;
}
-static bool UseIgnition(CompilationInfo* info) {
+bool UseIgnition(CompilationInfo* info) {
// TODO(4681): Generator functions are not yet supported.
if ((info->has_shared_info() && info->shared_info()->is_generator()) ||
(info->has_literal() && IsGeneratorFunction(info->literal()->kind()))) {
@@ -810,7 +823,7 @@ static bool UseIgnition(CompilationInfo* info) {
return info->closure()->PassesFilter(FLAG_ignition_filter);
}
-static int CodeAndMetadataSize(CompilationInfo* info) {
+int CodeAndMetadataSize(CompilationInfo* info) {
int size = 0;
if (info->has_bytecode_array()) {
Handle<BytecodeArray> bytecode_array = info->bytecode_array();
@@ -828,8 +841,7 @@ static int CodeAndMetadataSize(CompilationInfo* info) {
return size;
}
-
-static bool GenerateBaselineCode(CompilationInfo* info) {
+bool GenerateBaselineCode(CompilationInfo* info) {
bool success;
if (FLAG_ignition && UseIgnition(info)) {
success = interpreter::Interpreter::MakeBytecode(info);
@@ -845,8 +857,7 @@ static bool GenerateBaselineCode(CompilationInfo* info) {
return success;
}
-
-static bool CompileBaselineCode(CompilationInfo* info) {
+bool CompileBaselineCode(CompilationInfo* info) {
DCHECK(AllowCompilation::IsAllowed(info->isolate()));
if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) {
Isolate* isolate = info->isolate();
@@ -856,9 +867,9 @@ static bool CompileBaselineCode(CompilationInfo* info) {
return true;
}
-static void InstallBaselineCompilationResult(CompilationInfo* info,
- Handle<SharedFunctionInfo> shared,
- Handle<ScopeInfo> scope_info) {
+void InstallBaselineCompilationResult(CompilationInfo* info,
+ Handle<SharedFunctionInfo> shared,
+ Handle<ScopeInfo> scope_info) {
// Assert that we are not overwriting (possibly patched) debug code.
DCHECK(!shared->HasDebugCode());
DCHECK(!info->code().is_null());
@@ -871,7 +882,7 @@ static void InstallBaselineCompilationResult(CompilationInfo* info,
}
}
-MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
+MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCodeCommon(
CompilationInfo* info) {
VMState<COMPILER> state(info->isolate());
PostponeInterruptsScope postpone(info->isolate());
@@ -899,8 +910,7 @@ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
return info->code();
}
-
-MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
+MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
Handle<JSFunction> function, BailoutId osr_ast_id) {
Handle<SharedFunctionInfo> shared(function->shared());
DisallowHeapAllocation no_gc;
@@ -916,8 +926,7 @@ MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
return MaybeHandle<Code>();
}
-
-static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
+void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
Handle<Code> code = info->code();
if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
@@ -948,8 +957,7 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
}
}
-
-static bool Renumber(ParseInfo* parse_info) {
+bool Renumber(ParseInfo* parse_info) {
if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
parse_info->literal())) {
return false;
@@ -966,24 +974,6 @@ static bool Renumber(ParseInfo* parse_info) {
return true;
}
-
-bool Compiler::Analyze(ParseInfo* info) {
- DCHECK_NOT_NULL(info->literal());
- if (!Rewriter::Rewrite(info)) return false;
- if (!Scope::Analyze(info)) return false;
- if (!Renumber(info)) return false;
- DCHECK_NOT_NULL(info->scope());
- return true;
-}
-
-
-bool Compiler::ParseAndAnalyze(ParseInfo* info) {
- if (!Parser::ParseStatic(info)) return false;
- return Compiler::Analyze(info);
-}
-
-namespace {
-
bool GetOptimizedCodeNow(CompilationInfo* info) {
Isolate* isolate = info->isolate();
CanonicalHandleScope canonical(isolate);
@@ -1182,98 +1172,6 @@ MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
return result;
}
-} // namespace
-
-bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
- if (function->is_compiled()) return true;
- MaybeHandle<Code> maybe_code = GetLazyCode(function);
- Handle<Code> code;
- if (!maybe_code.ToHandle(&code)) {
- if (flag == CLEAR_EXCEPTION) {
- function->GetIsolate()->clear_pending_exception();
- }
- return false;
- }
- DCHECK(code->IsJavaScriptCode());
- function->ReplaceCode(*code);
- DCHECK(function->is_compiled());
- return true;
-}
-
-bool Compiler::CompileOptimized(Handle<JSFunction> function,
- ConcurrencyMode mode) {
- Handle<Code> code;
- if (GetOptimizedCode(function, mode).ToHandle(&code)) {
- // Optimization succeeded, return optimized code.
- function->ReplaceCode(*code);
- } else {
- // Optimization failed, get unoptimized code.
- Isolate* isolate = function->GetIsolate();
- if (isolate->has_pending_exception()) { // Possible stack overflow.
- return false;
- }
- code = Handle<Code>(function->shared()->code(), isolate);
- if (code->kind() != Code::FUNCTION &&
- code->kind() != Code::OPTIMIZED_FUNCTION) {
- if (!GetUnoptimizedCode(function).ToHandle(&code)) {
- return false;
- }
- }
- function->ReplaceCode(*code);
- }
-
- DCHECK(function->code()->kind() == Code::FUNCTION ||
- function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
- (function->code()->is_interpreter_entry_trampoline() &&
- function->shared()->HasBytecodeArray()) ||
- function->IsInOptimizationQueue());
- return true;
-}
-
-// TODO(turbofan): In the future, unoptimized code with deopt support could
-// be generated lazily once deopt is triggered.
-bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
- DCHECK_NOT_NULL(info->literal());
- DCHECK(info->has_scope());
- Handle<SharedFunctionInfo> shared = info->shared_info();
- if (!shared->has_deoptimization_support()) {
- // TODO(titzer): just reuse the ParseInfo for the unoptimized compile.
- CompilationInfoWithZone unoptimized(info->closure());
- // Note that we use the same AST that we will use for generating the
- // optimized code.
- ParseInfo* parse_info = unoptimized.parse_info();
- parse_info->set_literal(info->literal());
- parse_info->set_scope(info->scope());
- parse_info->set_context(info->context());
- unoptimized.EnableDeoptimizationSupport();
- // If the current code has reloc info for serialization, also include
- // reloc info for serialization for the new code, so that deopt support
- // can be added without losing IC state.
- if (shared->code()->kind() == Code::FUNCTION &&
- shared->code()->has_reloc_info_for_serialization()) {
- unoptimized.PrepareForSerializing();
- }
- if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
-
- shared->EnableDeoptimizationSupport(*unoptimized.code());
- shared->set_feedback_vector(*unoptimized.feedback_vector());
-
- info->MarkAsCompiled();
-
- // The scope info might not have been set if a lazily compiled
- // function is inlined before being called for the first time.
- if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
- Handle<ScopeInfo> target_scope_info =
- ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
- shared->set_scope_info(*target_scope_info);
- }
-
- // The existing unoptimized code was replaced with the new one.
- RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
- }
- return true;
-}
-
bool CompileEvalForDebugging(Handle<JSFunction> function,
Handle<SharedFunctionInfo> shared) {
@@ -1322,60 +1220,13 @@ bool CompileForDebugging(CompilationInfo* info) {
return true;
}
-
-static inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
+inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
return shared->is_toplevel() && shared->script()->IsScript() &&
Script::cast(shared->script())->compilation_type() ==
Script::COMPILATION_TYPE_EVAL;
}
-
-bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
- Handle<SharedFunctionInfo> shared(function->shared());
- if (IsEvalToplevel(shared)) {
- return CompileEvalForDebugging(function, shared);
- } else {
- CompilationInfoWithZone info(function);
- return CompileForDebugging(&info);
- }
-}
-
-
-bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
- DCHECK(shared->allows_lazy_compilation_without_context());
- DCHECK(!IsEvalToplevel(shared));
- Zone zone;
- ParseInfo parse_info(&zone, shared);
- CompilationInfo info(&parse_info);
- return CompileForDebugging(&info);
-}
-
-
-void Compiler::CompileForLiveEdit(Handle<Script> script) {
- // TODO(635): support extensions.
- Zone zone;
- ParseInfo parse_info(&zone, script);
- CompilationInfo info(&parse_info);
- PostponeInterruptsScope postpone(info.isolate());
- VMState<COMPILER> state(info.isolate());
-
- // Get rid of old list of shared function infos.
- info.MarkAsFirstCompile();
- info.MarkAsDebug();
- info.parse_info()->set_global();
- if (!Parser::ParseStatic(info.parse_info())) return;
-
- LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal());
- if (!CompileUnoptimizedCode(&info)) return;
- if (info.has_shared_info()) {
- Handle<ScopeInfo> scope_info =
- ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
- info.shared_info()->set_scope_info(*scope_info);
- }
- tracker.RecordRootFunctionInfo(info.code());
-}
-
-static Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
+Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) {
Handle<Code> code = isolate->builtins()->CompileLazy();
Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate));
@@ -1387,7 +1238,7 @@ static Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
return result;
}
-static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
+Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
Isolate* isolate = info->isolate();
TimerEventScope<TimerEventCompileCode> timer(isolate);
TRACE_EVENT0("v8", "V8.CompileCode");
@@ -1500,6 +1351,157 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
return result;
}
+} // namespace
+
+// ----------------------------------------------------------------------------
+// Implementation of Compiler
+
+bool Compiler::Analyze(ParseInfo* info) {
+ DCHECK_NOT_NULL(info->literal());
+ if (!Rewriter::Rewrite(info)) return false;
+ if (!Scope::Analyze(info)) return false;
+ if (!Renumber(info)) return false;
+ DCHECK_NOT_NULL(info->scope());
+ return true;
+}
+
+bool Compiler::ParseAndAnalyze(ParseInfo* info) {
+ if (!Parser::ParseStatic(info)) return false;
+ return Compiler::Analyze(info);
+}
+
+bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
+ if (function->is_compiled()) return true;
+ MaybeHandle<Code> maybe_code = GetLazyCode(function);
+ Handle<Code> code;
+ if (!maybe_code.ToHandle(&code)) {
+ if (flag == CLEAR_EXCEPTION) {
+ function->GetIsolate()->clear_pending_exception();
+ }
+ return false;
+ }
+ DCHECK(code->IsJavaScriptCode());
+ function->ReplaceCode(*code);
+ DCHECK(function->is_compiled());
+ return true;
+}
+
+bool Compiler::CompileOptimized(Handle<JSFunction> function,
+ ConcurrencyMode mode) {
+ Handle<Code> code;
+ if (GetOptimizedCode(function, mode).ToHandle(&code)) {
+ // Optimization succeeded, return optimized code.
+ function->ReplaceCode(*code);
+ } else {
+ // Optimization failed, get unoptimized code.
+ Isolate* isolate = function->GetIsolate();
+ if (isolate->has_pending_exception()) { // Possible stack overflow.
+ return false;
+ }
+ code = Handle<Code>(function->shared()->code(), isolate);
+ if (code->kind() != Code::FUNCTION &&
+ code->kind() != Code::OPTIMIZED_FUNCTION) {
+ if (!GetUnoptimizedCode(function).ToHandle(&code)) {
+ return false;
+ }
+ }
+ function->ReplaceCode(*code);
+ }
+
+ DCHECK(function->code()->kind() == Code::FUNCTION ||
+ function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
+ (function->code()->is_interpreter_entry_trampoline() &&
+ function->shared()->HasBytecodeArray()) ||
+ function->IsInOptimizationQueue());
+ return true;
+}
+
+bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
+ Handle<SharedFunctionInfo> shared(function->shared());
+ if (IsEvalToplevel(shared)) {
+ return CompileEvalForDebugging(function, shared);
+ } else {
+ CompilationInfoWithZone info(function);
+ return CompileForDebugging(&info);
+ }
+}
+
+bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
+ DCHECK(shared->allows_lazy_compilation_without_context());
+ DCHECK(!IsEvalToplevel(shared));
+ Zone zone;
+ ParseInfo parse_info(&zone, shared);
+ CompilationInfo info(&parse_info);
+ return CompileForDebugging(&info);
+}
+
+// TODO(turbofan): In the future, unoptimized code with deopt support could
+// be generated lazily once deopt is triggered.
+bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
+ DCHECK_NOT_NULL(info->literal());
+ DCHECK(info->has_scope());
+ Handle<SharedFunctionInfo> shared = info->shared_info();
+ if (!shared->has_deoptimization_support()) {
+ // TODO(titzer): just reuse the ParseInfo for the unoptimized compile.
+ CompilationInfoWithZone unoptimized(info->closure());
+ // Note that we use the same AST that we will use for generating the
+ // optimized code.
+ ParseInfo* parse_info = unoptimized.parse_info();
+ parse_info->set_literal(info->literal());
+ parse_info->set_scope(info->scope());
+ parse_info->set_context(info->context());
+ unoptimized.EnableDeoptimizationSupport();
+ // If the current code has reloc info for serialization, also include
+ // reloc info for serialization for the new code, so that deopt support
+ // can be added without losing IC state.
+ if (shared->code()->kind() == Code::FUNCTION &&
+ shared->code()->has_reloc_info_for_serialization()) {
+ unoptimized.PrepareForSerializing();
+ }
+ if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
+
+ shared->EnableDeoptimizationSupport(*unoptimized.code());
+ shared->set_feedback_vector(*unoptimized.feedback_vector());
+
+ info->MarkAsCompiled();
+
+ // The scope info might not have been set if a lazily compiled
+ // function is inlined before being called for the first time.
+ if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
+ Handle<ScopeInfo> target_scope_info =
+ ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
+ shared->set_scope_info(*target_scope_info);
+ }
+
+ // The existing unoptimized code was replaced with the new one.
+ RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
+ }
+ return true;
+}
+
+void Compiler::CompileForLiveEdit(Handle<Script> script) {
+ // TODO(635): support extensions.
+ Zone zone;
+ ParseInfo parse_info(&zone, script);
+ CompilationInfo info(&parse_info);
+ PostponeInterruptsScope postpone(info.isolate());
+ VMState<COMPILER> state(info.isolate());
+
+ // Get rid of old list of shared function infos.
+ info.MarkAsFirstCompile();
+ info.MarkAsDebug();
+ info.parse_info()->set_global();
+ if (!Parser::ParseStatic(info.parse_info())) return;
+
+ LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal());
+ if (!CompileUnoptimizedCode(&info)) return;
+ if (info.has_shared_info()) {
+ Handle<ScopeInfo> scope_info =
+ ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
+ info.shared_info()->set_scope_info(*scope_info);
+ }
+ tracker.RecordRootFunctionInfo(info.code());
+}
MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
@@ -1953,12 +1955,5 @@ void Compiler::PostInstantiation(Handle<JSFunction> function,
}
}
-#if DEBUG
-void CompilationInfo::PrintAstForTesting() {
- PrintF("--- Source from AST ---\n%s\n",
- PrettyPrinter(isolate()).PrintProgram(literal()));
-}
-#endif
-
} // namespace internal
} // namespace v8
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698