| 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
|
|
|