Index: runtime/vm/precompiler.cc |
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc |
index 11a7b3ba8bb4ede5b7c18c23155962d9f28fd269..7977f78b30fc07e5eddff38ace656c96ce4cc950 100644 |
--- a/runtime/vm/precompiler.cc |
+++ b/runtime/vm/precompiler.cc |
@@ -78,9 +78,54 @@ DECLARE_FLAG(bool, trace_irregexp); |
class DartPrecompilationPipeline : public DartCompilationPipeline { |
public: |
- DartPrecompilationPipeline() : result_type_(CompileType::None()) { } |
+ explicit DartPrecompilationPipeline(Zone* zone, |
+ FieldTypeMap* field_map = NULL) |
+ : zone_(zone), |
+ result_type_(CompileType::None()), |
+ field_map_(field_map) { } |
virtual void FinalizeCompilation(FlowGraph* flow_graph) { |
+ if ((field_map_ != NULL )&& |
+ flow_graph->function().IsGenerativeConstructor()) { |
+ 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()) { |
+ StoreInstanceFieldInstr* store = it.Current()->AsStoreInstanceField(); |
+ if (store != NULL) { |
+ if (!store->field().IsNull() && store->field().is_final()) { |
+ if (FLAG_trace_precompiler) { |
+ THR_Print("Found store to %s <- %s\n", |
+ store->field().ToCString(), |
+ store->value()->Type()->ToCString()); |
+ } |
+ FieldTypePair* entry = field_map_->Lookup(&store->field()); |
+ if (entry == NULL) { |
+ field_map_->Insert(FieldTypePair( |
+ &Field::Handle(zone_, store->field().raw()), // Re-wrap. |
+ store->value()->Type()->ToCid())); |
+ if (FLAG_trace_precompiler) { |
+ THR_Print(" initial type = %s\n", |
+ store->value()->Type()->ToCString()); |
+ } |
+ continue; |
+ } |
+ CompileType type = CompileType::FromCid(entry->cid_); |
+ if (FLAG_trace_precompiler) { |
+ THR_Print(" old type = %s\n", type.ToCString()); |
+ } |
+ type.Union(store->value()->Type()); |
+ if (FLAG_trace_precompiler) { |
+ THR_Print(" new type = %s\n", type.ToCString()); |
+ } |
+ entry->cid_ = type.ToCid(); |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
CompileType result_type = CompileType::None(); |
for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); |
!block_it.Done(); |
@@ -99,7 +144,9 @@ class DartPrecompilationPipeline : public DartCompilationPipeline { |
CompileType result_type() { return result_type_; } |
private: |
+ Zone* zone_; |
CompileType result_type_; |
+ FieldTypeMap* field_map_; |
}; |
@@ -180,6 +227,7 @@ Precompiler::Precompiler(Thread* thread, bool reset_fields) : |
typeargs_to_retain_(), |
types_to_retain_(), |
consts_to_retain_(), |
+ field_type_map_(), |
error_(Error::Handle()) { |
} |
@@ -203,6 +251,10 @@ void Precompiler::DoCompileAll( |
// Precompile static initializers to compute result type information. |
PrecompileStaticInitializers(); |
+ // Precompile constructors to compute type information for final fields. |
+ ClearAllCode(); |
+ PrecompileConstructors(); |
+ |
for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { |
if (FLAG_trace_precompiler) { |
THR_Print("Precompiler round %" Pd "\n", round); |
@@ -339,6 +391,52 @@ void Precompiler::PrecompileStaticInitializers() { |
} |
+void Precompiler::PrecompileConstructors() { |
+ class ConstructorVisitor : public FunctionVisitor { |
+ public: |
+ explicit ConstructorVisitor(Zone* zone, FieldTypeMap* map) |
+ : zone_(zone), field_type_map_(map) { |
+ ASSERT(map != NULL); |
+ } |
+ void Visit(const Function& function) { |
+ if (!function.IsGenerativeConstructor()) return; |
+ if (function.HasCode()) { |
+ // Const constructors may have been visited before. Recompile them here |
+ // to collect type information for final fields for them as well. |
+ function.ClearCode(); |
+ } |
+ if (FLAG_trace_precompiler) { |
+ THR_Print("Precompiling constructor %s\n", function.ToCString()); |
+ } |
+ CompileFunction(Thread::Current(), |
+ zone_, |
+ function, |
+ field_type_map_); |
+ } |
+ private: |
+ Zone* zone_; |
+ FieldTypeMap* field_type_map_; |
+ }; |
+ |
+ HANDLESCOPE(T); |
+ ConstructorVisitor visitor(zone_, &field_type_map_); |
+ VisitFunctions(&visitor); |
+ |
+ FieldTypeMap::Iterator it(field_type_map_.GetIterator()); |
+ for (FieldTypePair* current = it.Next(); |
+ current != NULL; |
+ current = it.Next()) { |
+ const intptr_t cid = current->cid_; |
+ current->field_->set_guarded_cid(cid); |
+ current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); |
+ if (FLAG_trace_precompiler) { |
+ THR_Print("Field %s <- Type %s\n", current->field_->ToCString(), |
+ Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); |
+ } |
+ } |
+} |
+ |
+ |
void Precompiler::ClearAllCode() { |
class ClearCodeFunctionVisitor : public FunctionVisitor { |
void Visit(const Function& function) { |
@@ -609,7 +707,7 @@ void Precompiler::ProcessFunction(const Function& function) { |
ASSERT(!function.is_abstract()); |
ASSERT(!function.IsRedirectingFactory()); |
- error_ = CompileFunction(thread_, function); |
+ error_ = CompileFunction(thread_, zone_, function); |
if (!error_.IsNull()) { |
Jump(error_); |
} |
@@ -946,7 +1044,7 @@ RawFunction* Precompiler::CompileStaticInitializer(const Field& field, |
ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); |
parsed_function->AllocateVariables(); |
- DartPrecompilationPipeline pipeline; |
+ DartPrecompilationPipeline pipeline(zone.GetZone()); |
PrecompileParsedFunctionHelper helper(parsed_function, |
/* optimized = */ true); |
bool success = helper.Compile(&pipeline); |
@@ -1046,7 +1144,7 @@ RawObject* Precompiler::ExecuteOnce(SequenceNode* fragment) { |
parsed_function->AllocateVariables(); |
// Non-optimized code generator. |
- DartPrecompilationPipeline pipeline; |
+ DartPrecompilationPipeline pipeline(Thread::Current()->zone()); |
PrecompileParsedFunctionHelper helper(parsed_function, |
/* optimized = */ false); |
helper.Compile(&pipeline); |
@@ -3073,16 +3171,16 @@ static RawError* PrecompileFunctionHelper(CompilationPipeline* pipeline, |
RawError* Precompiler::CompileFunction(Thread* thread, |
- const Function& function) { |
+ Zone* zone, |
+ const Function& function, |
+ FieldTypeMap* field_type_map) { |
VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId); |
TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function); |
- CompilationPipeline* pipeline = |
- CompilationPipeline::New(thread->zone(), function); |
- |
ASSERT(FLAG_precompiled_mode); |
const bool optimized = function.IsOptimizable(); // False for natives. |
- return PrecompileFunctionHelper(pipeline, function, optimized); |
+ DartPrecompilationPipeline pipeline(zone, field_type_map); |
+ return PrecompileFunctionHelper(&pipeline, function, optimized); |
} |
#endif // DART_PRECOMPILER |