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

Unified Diff: runtime/vm/precompiler.cc

Issue 1973553003: VM precompiler: Compute and use result type of static initializers of final fields. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: preprocess initializers Created 4 years, 7 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 | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/precompiler.cc
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 3ece322ca4df7b0cb5aa04bb94a289ac01c2dca9..ffc9f2066cccfd47ebe46141656dc0e7def8f10a 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -75,6 +75,33 @@ DECLARE_FLAG(bool, trace_irregexp);
#ifdef DART_PRECOMPILER
+class DartPrecompilationPipeline : public DartCompilationPipeline {
+ public:
+ DartPrecompilationPipeline() : result_type_(CompileType::None()) { }
+
+ virtual void FinalizeCompilation(FlowGraph* flow_graph) {
+ CompileType result_type = CompileType::None();
+ for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ ForwardInstructionIterator it(block_it.Current());
+ for (; !it.Done(); it.Advance()) {
+ ReturnInstr* return_instr = it.Current()->AsReturn();
+ if (return_instr != NULL) {
+ result_type.Union(return_instr->InputAt(0)->Type());
+ }
+ }
+ }
+ result_type_ = result_type;
+ }
+
+ CompileType result_type() { return result_type_; }
+
+ private:
+ CompileType result_type_;
+};
+
+
class PrecompileParsedFunctionHelper : public ValueObject {
public:
PrecompileParsedFunctionHelper(ParsedFunction* parsed_function,
@@ -169,6 +196,9 @@ void Precompiler::DoCompileAll(
// because their class hasn't been finalized yet.
FinalizeAllClasses();
+ // Precompile static initializers to compute result type information.
+ PrecompileStaticInitializers();
+
for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) {
if (FLAG_trace_precompiler) {
THR_Print("Precompiler round %" Pd "\n", round);
@@ -255,9 +285,52 @@ void Precompiler::DoCompileAll(
}
+static void CompileStaticInitializerIgnoreErrors(const Field& field) {
+ LongJumpScope jump;
+ if (setjmp(*jump.Set()) == 0) {
+ Precompiler::CompileStaticInitializer(field, /* compute_type = */ true);
+ } else {
+ // Ignore compile-time errors here. If the field is actually used,
+ // the error will be reported later during Iterate().
+ }
+}
+
+
+void Precompiler::PrecompileStaticInitializers() {
+ class StaticInitializerVisitor : public ClassVisitor {
+ public:
+ explicit StaticInitializerVisitor(Zone* zone)
+ : fields_(Array::Handle(zone)),
+ field_(Field::Handle(zone)),
+ function_(Function::Handle(zone)) { }
+ void Visit(const Class& cls) {
+ fields_ = cls.fields();
+ for (intptr_t j = 0; j < fields_.Length(); j++) {
+ field_ ^= fields_.At(j);
+ if (field_.is_static() &&
+ field_.is_final() &&
+ field_.has_initializer()) {
+ if (FLAG_trace_precompiler) {
+ THR_Print("Precompiling initializer for %s\n", field_.ToCString());
+ }
+ CompileStaticInitializerIgnoreErrors(field_);
+ }
+ }
+ }
+
+ private:
+ Array& fields_;
+ Field& field_;
+ Function& function_;
+ };
+ StaticInitializerVisitor visitor(Z);
+ VisitClasses(&visitor);
+}
+
+
void Precompiler::ClearAllCode() {
class ClearCodeFunctionVisitor : public FunctionVisitor {
- void VisitFunction(const Function& function) {
+ void Visit(const Function& function) {
function.ClearCode();
function.ClearICDataArray();
}
@@ -768,8 +841,8 @@ void Precompiler::AddField(const Field& field) {
THR_Print("Precompiling initializer for %s\n", field.ToCString());
}
ASSERT(Dart::snapshot_kind() != Snapshot::kAppNoJIT);
- const Function& initializer =
- Function::Handle(Z, CompileStaticInitializer(field));
+ const Function& initializer = Function::Handle(Z,
+ CompileStaticInitializer(field, /* compute_type = */ true));
ASSERT(!initializer.IsNull());
field.SetPrecompiledInitializer(initializer);
AddCalleesOf(initializer);
@@ -779,7 +852,8 @@ void Precompiler::AddField(const Field& field) {
}
-RawFunction* Precompiler::CompileStaticInitializer(const Field& field) {
+RawFunction* Precompiler::CompileStaticInitializer(const Field& field,
+ bool compute_type) {
ASSERT(field.is_static());
Thread* thread = Thread::Current();
StackZone zone(thread);
@@ -787,12 +861,23 @@ RawFunction* Precompiler::CompileStaticInitializer(const Field& field) {
ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
parsed_function->AllocateVariables();
- DartCompilationPipeline pipeline;
+ DartPrecompilationPipeline pipeline;
PrecompileParsedFunctionHelper helper(parsed_function,
/* optimized = */ true);
bool success = helper.Compile(&pipeline);
ASSERT(success);
+ if (compute_type && field.is_final()) {
+ intptr_t result_cid = pipeline.result_type().ToCid();
+ if (result_cid != kDynamicCid) {
+ if (FLAG_trace_precompiler) {
+ THR_Print("Setting guarded_cid of %s to %s\n", field.ToCString(),
+ pipeline.result_type().ToCString());
+ }
+ field.set_guarded_cid(result_cid);
+ }
+ }
+
if ((FLAG_disassemble || FLAG_disassemble_optimized) &&
FlowGraphPrinter::ShouldPrint(parsed_function->function())) {
Disassembler::DisassembleCode(parsed_function->function(),
@@ -815,7 +900,7 @@ RawObject* Precompiler::EvaluateStaticInitializer(const Field& field) {
// remembering it because it won't be used again.
Function& initializer = Function::Handle();
if (!field.HasPrecompiledInitializer()) {
- initializer = CompileStaticInitializer(field);
+ initializer = CompileStaticInitializer(field, /* compute_type = */ false);
} else {
initializer ^= field.PrecompiledInitializer();
}
@@ -876,7 +961,7 @@ RawObject* Precompiler::ExecuteOnce(SequenceNode* fragment) {
parsed_function->AllocateVariables();
// Non-optimized code generator.
- DartCompilationPipeline pipeline;
+ DartPrecompilationPipeline pipeline;
PrecompileParsedFunctionHelper helper(parsed_function,
/* optimized = */ false);
helper.Compile(&pipeline);
@@ -1672,7 +1757,7 @@ void Precompiler::BindStaticCalls() {
target_code_(Code::Handle(zone)) {
}
- void VisitFunction(const Function& function) {
+ void Visit(const Function& function) {
if (!function.HasCode()) {
return;
}
@@ -1741,7 +1826,7 @@ void Precompiler::SwitchICCalls() {
entry_point_(Smi::Handle(zone)) {
}
- void VisitFunction(const Function& function) {
+ void Visit(const Function& function) {
if (!function.HasCode()) {
return;
}
@@ -1810,7 +1895,7 @@ void Precompiler::DedupStackmaps() {
stackmap_(Stackmap::Handle(zone)) {
}
- void VisitFunction(const Function& function) {
+ void Visit(const Function& function) {
if (!function.HasCode()) {
return;
}
@@ -1860,7 +1945,7 @@ void Precompiler::DedupStackmapLists() {
stackmap_(Stackmap::Handle(zone)) {
}
- void VisitFunction(const Function& function) {
+ void Visit(const Function& function) {
if (!function.HasCode()) {
return;
}
@@ -1907,7 +1992,7 @@ void Precompiler::DedupInstructions() {
instructions_(Instructions::Handle(zone)) {
}
- void VisitFunction(const Function& function) {
+ void Visit(const Function& function) {
if (!function.HasCode()) {
ASSERT(function.HasImplicitClosureFunction());
return;
@@ -1943,6 +2028,25 @@ void Precompiler::DedupInstructions() {
VisitFunctions(&visitor);
}
+
+void Precompiler::VisitClasses(ClassVisitor* visitor) {
+ Library& lib = Library::Handle(Z);
+ Class& cls = Class::Handle(Z);
+
+ for (intptr_t i = 0; i < libraries_.Length(); i++) {
+ lib ^= libraries_.At(i);
+ ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+ while (it.HasNext()) {
+ cls = it.GetNextClass();
+ if (cls.IsDynamicClass()) {
+ continue; // class 'dynamic' is in the read-only VM isolate.
+ }
+ visitor->Visit(cls);
+ }
+ }
+}
+
+
void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
@@ -1965,10 +2069,10 @@ void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
functions = cls.functions();
for (intptr_t j = 0; j < functions.Length(); j++) {
function ^= functions.At(j);
- visitor->VisitFunction(function);
+ visitor->Visit(function);
if (function.HasImplicitClosureFunction()) {
function = function.ImplicitClosureFunction();
- visitor->VisitFunction(function);
+ visitor->Visit(function);
}
}
@@ -1977,7 +2081,7 @@ void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
object = functions.At(j);
if (object.IsFunction()) {
function ^= functions.At(j);
- visitor->VisitFunction(function);
+ visitor->Visit(function);
}
}
fields = cls.fields();
@@ -1985,7 +2089,7 @@ void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
field ^= fields.At(j);
if (field.is_static() && field.HasPrecompiledInitializer()) {
function ^= field.PrecompiledInitializer();
- visitor->VisitFunction(function);
+ visitor->Visit(function);
}
}
}
@@ -1993,7 +2097,7 @@ void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
closures = isolate()->object_store()->closure_functions();
for (intptr_t j = 0; j < closures.Length(); j++) {
function ^= closures.At(j);
- visitor->VisitFunction(function);
+ visitor->Visit(function);
ASSERT(!function.HasImplicitClosureFunction());
}
}
@@ -2579,7 +2683,7 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
"CompileGraph");
#endif // !PRODUCT
graph_compiler.CompileGraph();
- pipeline->FinalizeCompilation();
+ pipeline->FinalizeCompilation(flow_graph);
}
{
#ifndef PRODUCT
« no previous file with comments | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698