Chromium Code Reviews| 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 |