Chromium Code Reviews| Index: runtime/vm/precompiler.cc |
| diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc |
| index 11a7b3ba8bb4ede5b7c18c23155962d9f28fd269..7101513223961b506fa713f5190c728cef09e31d 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,48 @@ 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()) return; |
|
rmacnak
2016/09/06 20:38:41
This should only happen for const constructors rig
Florian Schneider
2016/09/06 21:00:31
Done. Yes, it happens for const-constructors.
|
| + 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 +703,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 +1040,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 +1140,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 +3167,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 |