OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/precompiler.h" | 5 #include "vm/precompiler.h" |
6 | 6 |
7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
10 #include "vm/branch_optimizer.h" | 10 #include "vm/branch_optimizer.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
71 DECLARE_FLAG(bool, verify_compiler); | 71 DECLARE_FLAG(bool, verify_compiler); |
72 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); | 72 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); |
73 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 73 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
74 DECLARE_FLAG(bool, trace_inlining_intervals); | 74 DECLARE_FLAG(bool, trace_inlining_intervals); |
75 DECLARE_FLAG(bool, trace_irregexp); | 75 DECLARE_FLAG(bool, trace_irregexp); |
76 | 76 |
77 #ifdef DART_PRECOMPILER | 77 #ifdef DART_PRECOMPILER |
78 | 78 |
79 class DartPrecompilationPipeline : public DartCompilationPipeline { | 79 class DartPrecompilationPipeline : public DartCompilationPipeline { |
80 public: | 80 public: |
81 DartPrecompilationPipeline() : result_type_(CompileType::None()) { } | 81 explicit DartPrecompilationPipeline(Zone* zone, |
82 FieldTypeMap* field_map = NULL) | |
83 : zone_(zone), | |
84 result_type_(CompileType::None()), | |
85 field_map_(field_map) { } | |
82 | 86 |
83 virtual void FinalizeCompilation(FlowGraph* flow_graph) { | 87 virtual void FinalizeCompilation(FlowGraph* flow_graph) { |
88 if ((field_map_ != NULL )&& | |
89 flow_graph->function().IsGenerativeConstructor()) { | |
90 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); | |
91 !block_it.Done(); | |
92 block_it.Advance()) { | |
93 ForwardInstructionIterator it(block_it.Current()); | |
94 for (; !it.Done(); it.Advance()) { | |
95 StoreInstanceFieldInstr* store = it.Current()->AsStoreInstanceField(); | |
96 if (store != NULL) { | |
97 if (!store->field().IsNull() && store->field().is_final()) { | |
98 if (FLAG_trace_precompiler) { | |
99 THR_Print("Found store to %s <- %s\n", | |
100 store->field().ToCString(), | |
101 store->value()->Type()->ToCString()); | |
102 } | |
103 FieldTypePair* entry = field_map_->Lookup(&store->field()); | |
104 if (entry == NULL) { | |
105 field_map_->Insert(FieldTypePair( | |
106 &Field::Handle(zone_, store->field().raw()), // Re-wrap. | |
107 store->value()->Type()->ToCid())); | |
108 if (FLAG_trace_precompiler) { | |
109 THR_Print(" initial type = %s\n", | |
110 store->value()->Type()->ToCString()); | |
111 } | |
112 continue; | |
113 } | |
114 CompileType type = CompileType::FromCid(entry->cid_); | |
115 if (FLAG_trace_precompiler) { | |
116 THR_Print(" old type = %s\n", type.ToCString()); | |
117 } | |
118 type.Union(store->value()->Type()); | |
119 if (FLAG_trace_precompiler) { | |
120 THR_Print(" new type = %s\n", type.ToCString()); | |
121 } | |
122 entry->cid_ = type.ToCid(); | |
123 } | |
124 } | |
125 } | |
126 } | |
127 } | |
128 | |
84 CompileType result_type = CompileType::None(); | 129 CompileType result_type = CompileType::None(); |
85 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); | 130 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); |
86 !block_it.Done(); | 131 !block_it.Done(); |
87 block_it.Advance()) { | 132 block_it.Advance()) { |
88 ForwardInstructionIterator it(block_it.Current()); | 133 ForwardInstructionIterator it(block_it.Current()); |
89 for (; !it.Done(); it.Advance()) { | 134 for (; !it.Done(); it.Advance()) { |
90 ReturnInstr* return_instr = it.Current()->AsReturn(); | 135 ReturnInstr* return_instr = it.Current()->AsReturn(); |
91 if (return_instr != NULL) { | 136 if (return_instr != NULL) { |
92 result_type.Union(return_instr->InputAt(0)->Type()); | 137 result_type.Union(return_instr->InputAt(0)->Type()); |
93 } | 138 } |
94 } | 139 } |
95 } | 140 } |
96 result_type_ = result_type; | 141 result_type_ = result_type; |
97 } | 142 } |
98 | 143 |
99 CompileType result_type() { return result_type_; } | 144 CompileType result_type() { return result_type_; } |
100 | 145 |
101 private: | 146 private: |
147 Zone* zone_; | |
102 CompileType result_type_; | 148 CompileType result_type_; |
149 FieldTypeMap* field_map_; | |
103 }; | 150 }; |
104 | 151 |
105 | 152 |
106 class PrecompileParsedFunctionHelper : public ValueObject { | 153 class PrecompileParsedFunctionHelper : public ValueObject { |
107 public: | 154 public: |
108 PrecompileParsedFunctionHelper(ParsedFunction* parsed_function, | 155 PrecompileParsedFunctionHelper(ParsedFunction* parsed_function, |
109 bool optimized) | 156 bool optimized) |
110 : parsed_function_(parsed_function), | 157 : parsed_function_(parsed_function), |
111 optimized_(optimized), | 158 optimized_(optimized), |
112 thread_(Thread::Current()) { | 159 thread_(Thread::Current()) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 pending_functions_( | 220 pending_functions_( |
174 GrowableObjectArray::Handle(GrowableObjectArray::New())), | 221 GrowableObjectArray::Handle(GrowableObjectArray::New())), |
175 sent_selectors_(), | 222 sent_selectors_(), |
176 enqueued_functions_(), | 223 enqueued_functions_(), |
177 fields_to_retain_(), | 224 fields_to_retain_(), |
178 functions_to_retain_(), | 225 functions_to_retain_(), |
179 classes_to_retain_(), | 226 classes_to_retain_(), |
180 typeargs_to_retain_(), | 227 typeargs_to_retain_(), |
181 types_to_retain_(), | 228 types_to_retain_(), |
182 consts_to_retain_(), | 229 consts_to_retain_(), |
230 field_type_map_(), | |
183 error_(Error::Handle()) { | 231 error_(Error::Handle()) { |
184 } | 232 } |
185 | 233 |
186 | 234 |
187 void Precompiler::DoCompileAll( | 235 void Precompiler::DoCompileAll( |
188 Dart_QualifiedFunctionName embedder_entry_points[]) { | 236 Dart_QualifiedFunctionName embedder_entry_points[]) { |
189 ASSERT(I->compilation_allowed()); | 237 ASSERT(I->compilation_allowed()); |
190 | 238 |
191 { | 239 { |
192 StackZone stack_zone(T); | 240 StackZone stack_zone(T); |
193 zone_ = stack_zone.GetZone(); | 241 zone_ = stack_zone.GetZone(); |
194 | 242 |
195 { HANDLESCOPE(T); | 243 { HANDLESCOPE(T); |
196 // Make sure class hierarchy is stable before compilation so that CHA | 244 // Make sure class hierarchy is stable before compilation so that CHA |
197 // can be used. Also ensures lookup of entry points won't miss functions | 245 // can be used. Also ensures lookup of entry points won't miss functions |
198 // because their class hasn't been finalized yet. | 246 // because their class hasn't been finalized yet. |
199 FinalizeAllClasses(); | 247 FinalizeAllClasses(); |
200 | 248 |
201 SortClasses(); | 249 SortClasses(); |
202 | 250 |
203 // Precompile static initializers to compute result type information. | 251 // Precompile static initializers to compute result type information. |
204 PrecompileStaticInitializers(); | 252 PrecompileStaticInitializers(); |
205 | 253 |
254 // Precompile constructors to compute type information for final fields. | |
255 ClearAllCode(); | |
256 PrecompileConstructors(); | |
257 | |
206 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { | 258 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { |
207 if (FLAG_trace_precompiler) { | 259 if (FLAG_trace_precompiler) { |
208 THR_Print("Precompiler round %" Pd "\n", round); | 260 THR_Print("Precompiler round %" Pd "\n", round); |
209 } | 261 } |
210 | 262 |
211 if (round > 0) { | 263 if (round > 0) { |
212 ResetPrecompilerState(); | 264 ResetPrecompilerState(); |
213 } | 265 } |
214 | 266 |
215 // TODO(rmacnak): We should be able to do a more thorough job and drop | 267 // TODO(rmacnak): We should be able to do a more thorough job and drop |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 Field& field_; | 384 Field& field_; |
333 Function& function_; | 385 Function& function_; |
334 }; | 386 }; |
335 | 387 |
336 HANDLESCOPE(T); | 388 HANDLESCOPE(T); |
337 StaticInitializerVisitor visitor(Z); | 389 StaticInitializerVisitor visitor(Z); |
338 VisitClasses(&visitor); | 390 VisitClasses(&visitor); |
339 } | 391 } |
340 | 392 |
341 | 393 |
394 void Precompiler::PrecompileConstructors() { | |
395 class ConstructorVisitor : public FunctionVisitor { | |
396 public: | |
397 explicit ConstructorVisitor(Zone* zone, FieldTypeMap* map) | |
398 : zone_(zone), field_type_map_(map) { | |
399 ASSERT(map != NULL); | |
400 } | |
401 void Visit(const Function& function) { | |
402 if (!function.IsGenerativeConstructor()) return; | |
403 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.
| |
404 if (FLAG_trace_precompiler) { | |
405 THR_Print("Precompiling constructor %s\n", function.ToCString()); | |
406 } | |
407 CompileFunction(Thread::Current(), | |
408 zone_, | |
409 function, | |
410 field_type_map_); | |
411 } | |
412 private: | |
413 Zone* zone_; | |
414 FieldTypeMap* field_type_map_; | |
415 }; | |
416 | |
417 HANDLESCOPE(T); | |
418 ConstructorVisitor visitor(zone_, &field_type_map_); | |
419 VisitFunctions(&visitor); | |
420 | |
421 FieldTypeMap::Iterator it(field_type_map_.GetIterator()); | |
422 for (FieldTypePair* current = it.Next(); | |
423 current != NULL; | |
424 current = it.Next()) { | |
425 const intptr_t cid = current->cid_; | |
426 current->field_->set_guarded_cid(cid); | |
427 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); | |
428 if (FLAG_trace_precompiler) { | |
429 THR_Print("Field %s <- Type %s\n", current->field_->ToCString(), | |
430 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); | |
431 } | |
432 } | |
433 } | |
434 | |
435 | |
342 void Precompiler::ClearAllCode() { | 436 void Precompiler::ClearAllCode() { |
343 class ClearCodeFunctionVisitor : public FunctionVisitor { | 437 class ClearCodeFunctionVisitor : public FunctionVisitor { |
344 void Visit(const Function& function) { | 438 void Visit(const Function& function) { |
345 function.ClearCode(); | 439 function.ClearCode(); |
346 function.ClearICDataArray(); | 440 function.ClearICDataArray(); |
347 } | 441 } |
348 }; | 442 }; |
349 ClearCodeFunctionVisitor function_visitor; | 443 ClearCodeFunctionVisitor function_visitor; |
350 VisitFunctions(&function_visitor); | 444 VisitFunctions(&function_visitor); |
351 | 445 |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 THR_Print("Precompiling %" Pd " %s (%s, %s)\n", | 696 THR_Print("Precompiling %" Pd " %s (%s, %s)\n", |
603 function_count_, | 697 function_count_, |
604 function.ToLibNamePrefixedQualifiedCString(), | 698 function.ToLibNamePrefixedQualifiedCString(), |
605 function.token_pos().ToCString(), | 699 function.token_pos().ToCString(), |
606 Function::KindToCString(function.kind())); | 700 Function::KindToCString(function.kind())); |
607 } | 701 } |
608 | 702 |
609 ASSERT(!function.is_abstract()); | 703 ASSERT(!function.is_abstract()); |
610 ASSERT(!function.IsRedirectingFactory()); | 704 ASSERT(!function.IsRedirectingFactory()); |
611 | 705 |
612 error_ = CompileFunction(thread_, function); | 706 error_ = CompileFunction(thread_, zone_, function); |
613 if (!error_.IsNull()) { | 707 if (!error_.IsNull()) { |
614 Jump(error_); | 708 Jump(error_); |
615 } | 709 } |
616 // Used in the JIT to save type-feedback across compilations. | 710 // Used in the JIT to save type-feedback across compilations. |
617 function.ClearICDataArray(); | 711 function.ClearICDataArray(); |
618 } else { | 712 } else { |
619 if (FLAG_trace_precompiler) { | 713 if (FLAG_trace_precompiler) { |
620 // This function was compiled from somewhere other than Precompiler, | 714 // This function was compiled from somewhere other than Precompiler, |
621 // such as const constructors compiled by the parser. | 715 // such as const constructors compiled by the parser. |
622 THR_Print("Already has code: %s (%s, %s)\n", | 716 THR_Print("Already has code: %s (%s, %s)\n", |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
939 | 1033 |
940 RawFunction* Precompiler::CompileStaticInitializer(const Field& field, | 1034 RawFunction* Precompiler::CompileStaticInitializer(const Field& field, |
941 bool compute_type) { | 1035 bool compute_type) { |
942 ASSERT(field.is_static()); | 1036 ASSERT(field.is_static()); |
943 Thread* thread = Thread::Current(); | 1037 Thread* thread = Thread::Current(); |
944 StackZone zone(thread); | 1038 StackZone zone(thread); |
945 | 1039 |
946 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); | 1040 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); |
947 | 1041 |
948 parsed_function->AllocateVariables(); | 1042 parsed_function->AllocateVariables(); |
949 DartPrecompilationPipeline pipeline; | 1043 DartPrecompilationPipeline pipeline(zone.GetZone()); |
950 PrecompileParsedFunctionHelper helper(parsed_function, | 1044 PrecompileParsedFunctionHelper helper(parsed_function, |
951 /* optimized = */ true); | 1045 /* optimized = */ true); |
952 bool success = helper.Compile(&pipeline); | 1046 bool success = helper.Compile(&pipeline); |
953 ASSERT(success); | 1047 ASSERT(success); |
954 | 1048 |
955 if (compute_type && field.is_final()) { | 1049 if (compute_type && field.is_final()) { |
956 intptr_t result_cid = pipeline.result_type().ToCid(); | 1050 intptr_t result_cid = pipeline.result_type().ToCid(); |
957 if (result_cid != kDynamicCid) { | 1051 if (result_cid != kDynamicCid) { |
958 if (FLAG_trace_precompiler && FLAG_support_il_printer) { | 1052 if (FLAG_trace_precompiler && FLAG_support_il_printer) { |
959 THR_Print("Setting guarded_cid of %s to %s\n", field.ToCString(), | 1053 THR_Print("Setting guarded_cid of %s to %s\n", field.ToCString(), |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1039 // would compile func automatically. We are checking fewer invariants | 1133 // would compile func automatically. We are checking fewer invariants |
1040 // here. | 1134 // here. |
1041 ParsedFunction* parsed_function = new ParsedFunction(thread, func); | 1135 ParsedFunction* parsed_function = new ParsedFunction(thread, func); |
1042 parsed_function->SetNodeSequence(fragment); | 1136 parsed_function->SetNodeSequence(fragment); |
1043 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); | 1137 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); |
1044 fragment->scope()->AddVariable( | 1138 fragment->scope()->AddVariable( |
1045 parsed_function->current_context_var()); | 1139 parsed_function->current_context_var()); |
1046 parsed_function->AllocateVariables(); | 1140 parsed_function->AllocateVariables(); |
1047 | 1141 |
1048 // Non-optimized code generator. | 1142 // Non-optimized code generator. |
1049 DartPrecompilationPipeline pipeline; | 1143 DartPrecompilationPipeline pipeline(Thread::Current()->zone()); |
1050 PrecompileParsedFunctionHelper helper(parsed_function, | 1144 PrecompileParsedFunctionHelper helper(parsed_function, |
1051 /* optimized = */ false); | 1145 /* optimized = */ false); |
1052 helper.Compile(&pipeline); | 1146 helper.Compile(&pipeline); |
1053 Code::Handle(func.unoptimized_code()).set_var_descriptors( | 1147 Code::Handle(func.unoptimized_code()).set_var_descriptors( |
1054 Object::empty_var_descriptors()); | 1148 Object::empty_var_descriptors()); |
1055 | 1149 |
1056 const Object& result = PassiveObject::Handle( | 1150 const Object& result = PassiveObject::Handle( |
1057 DartEntry::InvokeFunction(func, Object::empty_array())); | 1151 DartEntry::InvokeFunction(func, Object::empty_array())); |
1058 return result.raw(); | 1152 return result.raw(); |
1059 } else { | 1153 } else { |
(...skipping 2006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3066 // Do not attempt to optimize functions that can cause errors. | 3160 // Do not attempt to optimize functions that can cause errors. |
3067 function.set_is_optimizable(false); | 3161 function.set_is_optimizable(false); |
3068 return error.raw(); | 3162 return error.raw(); |
3069 } | 3163 } |
3070 UNREACHABLE(); | 3164 UNREACHABLE(); |
3071 return Error::null(); | 3165 return Error::null(); |
3072 } | 3166 } |
3073 | 3167 |
3074 | 3168 |
3075 RawError* Precompiler::CompileFunction(Thread* thread, | 3169 RawError* Precompiler::CompileFunction(Thread* thread, |
3076 const Function& function) { | 3170 Zone* zone, |
3171 const Function& function, | |
3172 FieldTypeMap* field_type_map) { | |
3077 VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId); | 3173 VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId); |
3078 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function); | 3174 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function); |
3079 | 3175 |
3080 CompilationPipeline* pipeline = | |
3081 CompilationPipeline::New(thread->zone(), function); | |
3082 | |
3083 ASSERT(FLAG_precompiled_mode); | 3176 ASSERT(FLAG_precompiled_mode); |
3084 const bool optimized = function.IsOptimizable(); // False for natives. | 3177 const bool optimized = function.IsOptimizable(); // False for natives. |
3085 return PrecompileFunctionHelper(pipeline, function, optimized); | 3178 DartPrecompilationPipeline pipeline(zone, field_type_map); |
3179 return PrecompileFunctionHelper(&pipeline, function, optimized); | |
3086 } | 3180 } |
3087 | 3181 |
3088 #endif // DART_PRECOMPILER | 3182 #endif // DART_PRECOMPILER |
3089 | 3183 |
3090 } // namespace dart | 3184 } // namespace dart |
OLD | NEW |