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

Unified Diff: runtime/vm/compiler.cc

Issue 1663163003: Initial split of precompilation code from compiler.cc (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 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
Index: runtime/vm/compiler.cc
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index c98bfe3074f91fadc80fd892922f9594419b7ab6..122a9dc1888de9ca501aa88bab162ba264e0fd09 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -30,9 +30,9 @@
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/parser.h"
+#include "vm/precompiler.h"
#include "vm/regexp_parser.h"
#include "vm/regexp_assembler.h"
-#include "vm/scanner.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/thread_registry.h"
@@ -66,8 +66,6 @@ DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler.");
DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining");
DEFINE_FLAG(bool, verify_compiler, false,
"Enable compiler verification assertions");
-DEFINE_FLAG(int, max_speculative_inlining_attempts, 1,
- "Max number of attempts with speculative inlining (precompilation only)");
DECLARE_FLAG(bool, background_compilation);
DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
@@ -80,91 +78,65 @@ DECLARE_FLAG(bool, precompilation);
#ifndef DART_PRECOMPILED_RUNTIME
-// TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove
-// separate helpers functions & `optimizing` args.
-class CompilationPipeline : public ZoneAllocated {
- public:
- static CompilationPipeline* New(Zone* zone, const Function& function);
-
- virtual void ParseFunction(ParsedFunction* parsed_function) = 0;
- virtual FlowGraph* BuildFlowGraph(
- Zone* zone,
- ParsedFunction* parsed_function,
- const ZoneGrowableArray<const ICData*>& ic_data_array,
- intptr_t osr_id) = 0;
- virtual void FinalizeCompilation() = 0;
- virtual ~CompilationPipeline() { }
-};
-
+void DartCompilationPipeline::ParseFunction(ParsedFunction* parsed_function) {
+ Parser::ParseFunction(parsed_function);
+ parsed_function->AllocateVariables();
+}
-class DartCompilationPipeline : public CompilationPipeline {
- public:
- virtual void ParseFunction(ParsedFunction* parsed_function) {
- Parser::ParseFunction(parsed_function);
- parsed_function->AllocateVariables();
- }
- virtual FlowGraph* BuildFlowGraph(
- Zone* zone,
- ParsedFunction* parsed_function,
- const ZoneGrowableArray<const ICData*>& ic_data_array,
- intptr_t osr_id) {
- // Build the flow graph.
- FlowGraphBuilder builder(*parsed_function,
- ic_data_array,
- NULL, // NULL = not inlining.
- osr_id);
-
- return builder.BuildGraph();
- }
+FlowGraph* DartCompilationPipeline::BuildFlowGraph(
+ Zone* zone,
+ ParsedFunction* parsed_function,
+ const ZoneGrowableArray<const ICData*>& ic_data_array,
+ intptr_t osr_id) {
+ // Build the flow graph.
+ FlowGraphBuilder builder(*parsed_function,
+ ic_data_array,
+ NULL, // NULL = not inlining.
+ osr_id);
- virtual void FinalizeCompilation() { }
-};
+ return builder.BuildGraph();
+}
-class IrregexpCompilationPipeline : public CompilationPipeline {
- public:
- IrregexpCompilationPipeline() : backtrack_goto_(NULL) { }
+void DartCompilationPipeline::FinalizeCompilation() { }
- virtual void ParseFunction(ParsedFunction* parsed_function) {
- RegExpParser::ParseFunction(parsed_function);
- // Variables are allocated after compilation.
- }
- virtual FlowGraph* BuildFlowGraph(
- Zone* zone,
- ParsedFunction* parsed_function,
- const ZoneGrowableArray<const ICData*>& ic_data_array,
- intptr_t osr_id) {
- // Compile to the dart IR.
- RegExpEngine::CompilationResult result =
- RegExpEngine::CompileIR(parsed_function->regexp_compile_data(),
- parsed_function,
- ic_data_array);
- backtrack_goto_ = result.backtrack_goto;
-
- // Allocate variables now that we know the number of locals.
- parsed_function->AllocateIrregexpVariables(result.num_stack_locals);
-
- // Build the flow graph.
- FlowGraphBuilder builder(*parsed_function,
- ic_data_array,
- NULL, // NULL = not inlining.
- osr_id);
-
- return new(zone) FlowGraph(*parsed_function,
- result.graph_entry,
- result.num_blocks);
- }
-
- virtual void FinalizeCompilation() {
- backtrack_goto_->ComputeOffsetTable();
- }
+void IrregexpCompilationPipeline::ParseFunction(
+ ParsedFunction* parsed_function) {
+ RegExpParser::ParseFunction(parsed_function);
+ // Variables are allocated after compilation.
+}
- private:
- IndirectGotoInstr* backtrack_goto_;
-};
+FlowGraph* IrregexpCompilationPipeline::BuildFlowGraph(
+ Zone* zone,
+ ParsedFunction* parsed_function,
+ const ZoneGrowableArray<const ICData*>& ic_data_array,
+ intptr_t osr_id) {
+ // Compile to the dart IR.
+ RegExpEngine::CompilationResult result =
+ RegExpEngine::CompileIR(parsed_function->regexp_compile_data(),
+ parsed_function,
+ ic_data_array);
+ backtrack_goto_ = result.backtrack_goto;
+
+ // Allocate variables now that we know the number of locals.
+ parsed_function->AllocateIrregexpVariables(result.num_stack_locals);
+
+ // Build the flow graph.
+ FlowGraphBuilder builder(*parsed_function,
+ ic_data_array,
+ NULL, // NULL = not inlining.
+ osr_id);
+
+ return new(zone) FlowGraph(*parsed_function,
+ result.graph_entry,
+ result.num_blocks);
+}
+void IrregexpCompilationPipeline::FinalizeCompilation() {
+ backtrack_goto_->ComputeOffsetTable();
+}
CompilationPipeline* CompilationPipeline::New(Zone* zone,
const Function& function) {
@@ -448,6 +420,7 @@ void CompileParsedFunctionHelper::FinalizeCompilation(
Assembler* assembler,
FlowGraphCompiler* graph_compiler,
FlowGraph* flow_graph) {
+ ASSERT(!FLAG_precompilation);
const Function& function = parsed_function()->function();
Zone* const zone = thread()->zone();
@@ -546,35 +519,31 @@ void CompileParsedFunctionHelper::FinalizeCompilation(
}
// Register code with the classes it depends on because of CHA and
- // fields it depends on because of store guards, unless we cannot
- // deopt.
- if (!FLAG_precompilation) {
- // Deoptimize field dependent code first, before registering
- // this yet uninstalled code as dependent on a field.
- // TODO(srdjan): Debugging dart2js crashes;
- // FlowGraphOptimizer::VisitStoreInstanceField populates
- // deoptimize_dependent_code() list, currently disabled.
- for (intptr_t i = 0;
- i < flow_graph->deoptimize_dependent_code().length();
- i++) {
- const Field* field = flow_graph->deoptimize_dependent_code()[i];
- field->DeoptimizeDependentCode();
- }
- for (intptr_t i = 0;
- i < thread()->cha()->leaf_classes().length();
- ++i) {
- thread()->cha()->leaf_classes()[i]->RegisterCHACode(code);
- }
- for (intptr_t i = 0;
- i < flow_graph->guarded_fields()->length();
- i++) {
- const Field* field = (*flow_graph->guarded_fields())[i];
- field->RegisterDependentCode(code);
- }
+ // fields it depends on because of store guards.
+ // Deoptimize field dependent code first, before registering
+ // this yet uninstalled code as dependent on a field.
+ // TODO(srdjan): Debugging dart2js crashes;
+ // FlowGraphOptimizer::VisitStoreInstanceField populates
+ // deoptimize_dependent_code() list, currently disabled.
+ for (intptr_t i = 0;
+ i < flow_graph->deoptimize_dependent_code().length();
+ i++) {
+ const Field* field = flow_graph->deoptimize_dependent_code()[i];
+ field->DeoptimizeDependentCode();
+ }
+ for (intptr_t i = 0;
+ i < thread()->cha()->leaf_classes().length();
+ ++i) {
+ thread()->cha()->leaf_classes()[i]->RegisterCHACode(code);
+ }
+ for (intptr_t i = 0;
+ i < flow_graph->guarded_fields()->length();
+ i++) {
+ const Field* field = (*flow_graph->guarded_fields())[i];
+ field->RegisterDependentCode(code);
}
} else { // not optimized.
- if (!FLAG_precompilation &&
- (function.ic_data_array() == Array::null())) {
+ if (function.ic_data_array() == Array::null()) {
function.SaveICDataMap(
graph_compiler->deopt_id_to_ic_data(),
Array::Handle(zone, graph_compiler->edge_counters_array()));
@@ -597,6 +566,7 @@ void CompileParsedFunctionHelper::FinalizeCompilation(
// If optimized_result_code is not NULL then it is caller's responsibility
// to install code.
bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
+ ASSERT(!FLAG_precompilation);
const Function& function = parsed_function()->function();
if (optimized() && !function.IsOptimizable()) {
return false;
@@ -616,9 +586,7 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
bool done = false;
// volatile because the variable may be clobbered by a longjmp.
volatile bool use_far_branches = false;
- volatile bool use_speculative_inlining =
- FLAG_max_speculative_inlining_attempts > 0;
- GrowableArray<intptr_t> inlining_black_list;
+ volatile bool use_speculative_inlining = false;
rmacnak 2016/02/04 00:36:39 volatile -> const
Florian Schneider 2016/02/05 01:55:52 Done.
while (!done) {
const intptr_t prev_deopt_id = thread()->deopt_id();
@@ -723,16 +691,7 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
FlowGraphOptimizer optimizer(flow_graph,
use_speculative_inlining,
- &inlining_black_list);
- if (FLAG_precompilation) {
- optimizer.PopulateWithICData();
-
- optimizer.ApplyClassIds();
- DEBUG_ASSERT(flow_graph->VerifyUseLists());
-
- FlowGraphTypePropagator::Propagate(flow_graph);
- DEBUG_ASSERT(flow_graph->VerifyUseLists());
- }
+ NULL);
optimizer.ApplyICData();
DEBUG_ASSERT(flow_graph->VerifyUseLists());
@@ -761,7 +720,7 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
&inline_id_to_function,
&caller_inline_id,
use_speculative_inlining,
- &inlining_black_list);
+ NULL);
inliner.Inline();
// Use lists are maintained and validated by the inliner.
DEBUG_ASSERT(flow_graph->VerifyUseLists());
@@ -1085,25 +1044,8 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
ASSERT(!use_far_branches);
use_far_branches = true;
} else if (error.raw() == Object::speculative_inlining_error().raw()) {
- // The return value of setjmp is the deopt id of the check instruction
- // that caused the bailout.
- done = false;
-#if defined(DEBUG)
- ASSERT(FLAG_precompilation);
- ASSERT(use_speculative_inlining);
- for (intptr_t i = 0; i < inlining_black_list.length(); ++i) {
- ASSERT(inlining_black_list[i] != val);
- }
-#endif
- inlining_black_list.Add(val);
- const intptr_t max_attempts = FLAG_max_speculative_inlining_attempts;
- if (inlining_black_list.length() >= max_attempts) {
- use_speculative_inlining = false;
- if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) {
- THR_Print("Disabled speculative inlining after %" Pd " attempts.\n",
- inlining_black_list.length());
- }
- }
+ // Can only happen with precompilation.
+ UNREACHABLE();
} else {
// If the error isn't due to an out of range branch offset, we don't
// try again (done = true), and indicate that we did not finish
@@ -1128,7 +1070,7 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
}
-static void DisassembleCode(const Function& function, bool optimized) {
+void Compiler::DisassembleCode(const Function& function, bool optimized) {
const char* function_fullname = function.ToFullyQualifiedCString();
THR_Print("Code for %sfunction '%s' {\n",
optimized ? "optimized " : "",
@@ -1294,11 +1236,7 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
const Function& function,
bool optimized,
intptr_t osr_id) {
- // Check that we optimize if 'FLAG_precompilation' is set to true,
- // except if the function is marked as not optimizable.
- ASSERT(!function.IsOptimizable() ||
- !FLAG_precompilation || optimized);
- ASSERT(!FLAG_precompilation || !function.HasCode());
+ ASSERT(!FLAG_precompilation);
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
Thread* const thread = Thread::Current();
@@ -1340,7 +1278,7 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
CompileParsedFunctionHelper helper(parsed_function, optimized, osr_id);
const bool success = helper.Compile(pipeline);
if (!success) {
- if (optimized && !FLAG_precompilation) {
+ if (optimized) {
// Optimizer bailed out. Disable optimizations and never try again.
if (trace_compiler) {
THR_Print("--> disabling optimizations for '%s'\n",
@@ -1376,13 +1314,13 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
isolate->debugger()->NotifyCompilation(function);
if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
- DisassembleCode(function, optimized);
+ Compiler::DisassembleCode(function, optimized);
} else if (FLAG_disassemble_optimized &&
optimized &&
FlowGraphPrinter::ShouldPrint(function)) {
// TODO(fschneider): Print unoptimized code along with the optimized code.
THR_Print("*** BEGIN CODE\n");
- DisassembleCode(function, true);
+ Compiler::DisassembleCode(function, true);
THR_Print("*** END CODE\n");
}
#if defined(DEBUG)
@@ -1397,9 +1335,9 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
// We got an error during compilation.
error = isolate->object_store()->sticky_error();
isolate->object_store()->clear_sticky_error();
- // Unoptimized compilation or precompilation may encounter compile-time
+ // Unoptimized compilation may encounter compile-time
// errors, but regular optimized compilation should not.
- ASSERT(!optimized || FLAG_precompilation);
+ ASSERT(!optimized);
// Do not attempt to optimize functions that can cause errors.
function.set_is_optimizable(false);
return error.raw();
@@ -1411,6 +1349,11 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
RawError* Compiler::CompileFunction(Thread* thread,
const Function& function) {
+#ifdef DART_PRECOMPILER
+ if (FLAG_precompilation) {
+ return Precompiler::CompileFunction(thread, function);
+ }
+#endif
Isolate* isolate = thread->isolate();
VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "Function", function);
@@ -1425,12 +1368,9 @@ RawError* Compiler::CompileFunction(Thread* thread,
CompilationPipeline* pipeline =
CompilationPipeline::New(thread->zone(), function);
- const bool optimized =
- FLAG_precompilation && function.IsOptimizable();
-
return CompileFunctionHelper(pipeline,
function,
- optimized,
+ /* optimized = */ false,
kNoOSRDeoptId);
}
@@ -1565,58 +1505,35 @@ RawError* Compiler::CompileAllFunctions(const Class& cls) {
}
-void Compiler::CompileStaticInitializer(const Field& field) {
- ASSERT(field.is_static());
- if (field.HasPrecompiledInitializer()) {
- // TODO(rmacnak): Investigate why this happens for _enum_names.
- OS::Print("Warning: Ignoring repeated request for initializer for %s\n",
- field.ToCString());
- return;
- }
- Thread* thread = Thread::Current();
- StackZone zone(thread);
-
- ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
-
- parsed_function->AllocateVariables();
- // Non-optimized code generator.
- DartCompilationPipeline pipeline;
- CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
- helper.Compile(&pipeline);
- const Function& initializer = parsed_function->function();
- field.SetPrecompiledInitializer(initializer);
-}
-
-
RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
+#ifdef DART_PRECOMPILER
+ if (FLAG_precompilation) {
+ return Precompiler::EvaluateStaticInitializer(field);
+ }
+#endif
ASSERT(field.is_static());
// The VM sets the field's value to transiton_sentinel prior to
// evaluating the initializer value.
ASSERT(field.StaticValue() == Object::transition_sentinel().raw());
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
- // Under precompilation, the initializer may have already been compiled, in
- // which case use it. Under lazy compilation or early in precompilation, the
- // initializer has not yet been created, so create it now, but don't bother
- // remembering it because it won't be used again.
- Function& initializer = Function::Handle();
- if (!field.HasPrecompiledInitializer()) {
- Thread* const thread = Thread::Current();
- StackZone zone(thread);
- ParsedFunction* parsed_function =
- Parser::ParseStaticFieldInitializer(field);
-
- parsed_function->AllocateVariables();
- // Non-optimized code generator.
- DartCompilationPipeline pipeline;
- CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
- helper.Compile(&pipeline);
- initializer = parsed_function->function().raw();
- Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
- Object::empty_var_descriptors());
- } else {
- initializer ^= field.PrecompiledInitializer();
- }
+ // Under lazy compilation initializer has not yet been created, so create
+ // it now, but don't bother remembering it because it won't be used again.
+ ASSERT(!field.HasPrecompiledInitializer());
+ Thread* const thread = Thread::Current();
+ StackZone zone(thread);
+ ParsedFunction* parsed_function =
+ Parser::ParseStaticFieldInitializer(field);
+
+ parsed_function->AllocateVariables();
+ // Non-optimized code generator.
+ DartCompilationPipeline pipeline;
+ CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+ helper.Compile(&pipeline);
+ const Function& initializer =
+ Function::Handle(parsed_function->function().raw());
+ Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
+ Object::empty_var_descriptors());
// Invoke the function to evaluate the expression.
return DartEntry::InvokeFunction(initializer, Object::empty_array());
} else {
@@ -1635,6 +1552,11 @@ RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
+#ifdef DART_PRECOMPILER
+ if (FLAG_precompilation) {
+ return Precompiler::ExecuteOnce(fragment);
+ }
+#endif
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
Thread* const thread = Thread::Current();
@@ -2005,11 +1927,6 @@ RawError* Compiler::CompileAllFunctions(const Class& cls) {
}
-void Compiler::CompileStaticInitializer(const Field& field) {
- UNREACHABLE();
-}
-
-
RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
ASSERT(field.HasPrecompiledInitializer());
const Function& initializer =
@@ -2018,7 +1935,6 @@ RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
}
-
RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
UNREACHABLE();
return Object::null();
« no previous file with comments | « runtime/vm/compiler.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | runtime/vm/precompiler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698