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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 namespace dart { | 46 namespace dart { |
47 | 47 |
48 | 48 |
49 #define T (thread()) | 49 #define T (thread()) |
50 #define I (isolate()) | 50 #define I (isolate()) |
51 #define Z (zone()) | 51 #define Z (zone()) |
52 | 52 |
53 | 53 |
54 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); | 54 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); |
55 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); | 55 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); |
56 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, | 56 DEFINE_FLAG( |
| 57 int, |
| 58 max_speculative_inlining_attempts, |
| 59 1, |
57 "Max number of attempts with speculative inlining (precompilation only)"); | 60 "Max number of attempts with speculative inlining (precompilation only)"); |
58 DEFINE_FLAG(int, precompiler_rounds, 1, "Number of precompiler iterations"); | 61 DEFINE_FLAG(int, precompiler_rounds, 1, "Number of precompiler iterations"); |
59 | 62 |
60 DECLARE_FLAG(bool, allocation_sinking); | 63 DECLARE_FLAG(bool, allocation_sinking); |
61 DECLARE_FLAG(bool, common_subexpression_elimination); | 64 DECLARE_FLAG(bool, common_subexpression_elimination); |
62 DECLARE_FLAG(bool, constant_propagation); | 65 DECLARE_FLAG(bool, constant_propagation); |
63 DECLARE_FLAG(bool, loop_invariant_code_motion); | 66 DECLARE_FLAG(bool, loop_invariant_code_motion); |
64 DECLARE_FLAG(bool, print_flow_graph); | 67 DECLARE_FLAG(bool, print_flow_graph); |
65 DECLARE_FLAG(bool, print_flow_graph_optimized); | 68 DECLARE_FLAG(bool, print_flow_graph_optimized); |
66 DECLARE_FLAG(bool, range_analysis); | 69 DECLARE_FLAG(bool, range_analysis); |
67 DECLARE_FLAG(bool, trace_compiler); | 70 DECLARE_FLAG(bool, trace_compiler); |
68 DECLARE_FLAG(bool, trace_optimizing_compiler); | 71 DECLARE_FLAG(bool, trace_optimizing_compiler); |
69 DECLARE_FLAG(bool, trace_bailout); | 72 DECLARE_FLAG(bool, trace_bailout); |
70 DECLARE_FLAG(bool, use_inlining); | 73 DECLARE_FLAG(bool, use_inlining); |
71 DECLARE_FLAG(bool, verify_compiler); | 74 DECLARE_FLAG(bool, verify_compiler); |
72 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); | 75 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); |
73 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 76 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
74 DECLARE_FLAG(bool, trace_inlining_intervals); | 77 DECLARE_FLAG(bool, trace_inlining_intervals); |
75 DECLARE_FLAG(bool, trace_irregexp); | 78 DECLARE_FLAG(bool, trace_irregexp); |
76 | 79 |
77 #ifdef DART_PRECOMPILER | 80 #ifdef DART_PRECOMPILER |
78 | 81 |
79 class DartPrecompilationPipeline : public DartCompilationPipeline { | 82 class DartPrecompilationPipeline : public DartCompilationPipeline { |
80 public: | 83 public: |
81 explicit DartPrecompilationPipeline(Zone* zone, | 84 explicit DartPrecompilationPipeline(Zone* zone, |
82 FieldTypeMap* field_map = NULL) | 85 FieldTypeMap* field_map = NULL) |
83 : zone_(zone), | 86 : zone_(zone), result_type_(CompileType::None()), field_map_(field_map) {} |
84 result_type_(CompileType::None()), | |
85 field_map_(field_map) { } | |
86 | 87 |
87 virtual void FinalizeCompilation(FlowGraph* flow_graph) { | 88 virtual void FinalizeCompilation(FlowGraph* flow_graph) { |
88 if ((field_map_ != NULL )&& | 89 if ((field_map_ != NULL) && |
89 flow_graph->function().IsGenerativeConstructor()) { | 90 flow_graph->function().IsGenerativeConstructor()) { |
90 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); | 91 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); |
91 !block_it.Done(); | 92 !block_it.Done(); block_it.Advance()) { |
92 block_it.Advance()) { | |
93 ForwardInstructionIterator it(block_it.Current()); | 93 ForwardInstructionIterator it(block_it.Current()); |
94 for (; !it.Done(); it.Advance()) { | 94 for (; !it.Done(); it.Advance()) { |
95 StoreInstanceFieldInstr* store = it.Current()->AsStoreInstanceField(); | 95 StoreInstanceFieldInstr* store = it.Current()->AsStoreInstanceField(); |
96 if (store != NULL) { | 96 if (store != NULL) { |
97 if (!store->field().IsNull() && store->field().is_final()) { | 97 if (!store->field().IsNull() && store->field().is_final()) { |
98 if (FLAG_trace_precompiler && FLAG_support_il_printer) { | 98 if (FLAG_trace_precompiler && FLAG_support_il_printer) { |
99 THR_Print("Found store to %s <- %s\n", | 99 THR_Print("Found store to %s <- %s\n", |
100 store->field().ToCString(), | 100 store->field().ToCString(), |
101 store->value()->Type()->ToCString()); | 101 store->value()->Type()->ToCString()); |
102 } | 102 } |
103 FieldTypePair* entry = field_map_->Lookup(&store->field()); | 103 FieldTypePair* entry = field_map_->Lookup(&store->field()); |
104 if (entry == NULL) { | 104 if (entry == NULL) { |
105 field_map_->Insert(FieldTypePair( | 105 field_map_->Insert(FieldTypePair( |
106 &Field::Handle(zone_, store->field().raw()), // Re-wrap. | 106 &Field::Handle(zone_, store->field().raw()), // Re-wrap. |
107 store->value()->Type()->ToCid())); | 107 store->value()->Type()->ToCid())); |
108 if (FLAG_trace_precompiler && FLAG_support_il_printer) { | 108 if (FLAG_trace_precompiler && FLAG_support_il_printer) { |
109 THR_Print(" initial type = %s\n", | 109 THR_Print(" initial type = %s\n", |
110 store->value()->Type()->ToCString()); | 110 store->value()->Type()->ToCString()); |
111 } | 111 } |
112 continue; | 112 continue; |
113 } | 113 } |
114 CompileType type = CompileType::FromCid(entry->cid_); | 114 CompileType type = CompileType::FromCid(entry->cid_); |
115 if (FLAG_trace_precompiler && FLAG_support_il_printer) { | 115 if (FLAG_trace_precompiler && FLAG_support_il_printer) { |
116 THR_Print(" old type = %s\n", type.ToCString()); | 116 THR_Print(" old type = %s\n", type.ToCString()); |
117 } | 117 } |
118 type.Union(store->value()->Type()); | 118 type.Union(store->value()->Type()); |
119 if (FLAG_trace_precompiler && FLAG_support_il_printer) { | 119 if (FLAG_trace_precompiler && FLAG_support_il_printer) { |
120 THR_Print(" new type = %s\n", type.ToCString()); | 120 THR_Print(" new type = %s\n", type.ToCString()); |
121 } | 121 } |
122 entry->cid_ = type.ToCid(); | 122 entry->cid_ = type.ToCid(); |
123 } | 123 } |
124 } | 124 } |
125 } | 125 } |
126 } | 126 } |
127 } | 127 } |
128 | 128 |
129 CompileType result_type = CompileType::None(); | 129 CompileType result_type = CompileType::None(); |
130 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); | 130 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); |
131 !block_it.Done(); | 131 !block_it.Done(); block_it.Advance()) { |
132 block_it.Advance()) { | |
133 ForwardInstructionIterator it(block_it.Current()); | 132 ForwardInstructionIterator it(block_it.Current()); |
134 for (; !it.Done(); it.Advance()) { | 133 for (; !it.Done(); it.Advance()) { |
135 ReturnInstr* return_instr = it.Current()->AsReturn(); | 134 ReturnInstr* return_instr = it.Current()->AsReturn(); |
136 if (return_instr != NULL) { | 135 if (return_instr != NULL) { |
137 result_type.Union(return_instr->InputAt(0)->Type()); | 136 result_type.Union(return_instr->InputAt(0)->Type()); |
138 } | 137 } |
139 } | 138 } |
140 } | 139 } |
141 result_type_ = result_type; | 140 result_type_ = result_type; |
142 } | 141 } |
143 | 142 |
144 CompileType result_type() { return result_type_; } | 143 CompileType result_type() { return result_type_; } |
145 | 144 |
146 private: | 145 private: |
147 Zone* zone_; | 146 Zone* zone_; |
148 CompileType result_type_; | 147 CompileType result_type_; |
149 FieldTypeMap* field_map_; | 148 FieldTypeMap* field_map_; |
150 }; | 149 }; |
151 | 150 |
152 | 151 |
153 class PrecompileParsedFunctionHelper : public ValueObject { | 152 class PrecompileParsedFunctionHelper : public ValueObject { |
154 public: | 153 public: |
155 PrecompileParsedFunctionHelper(Precompiler* precompiler, | 154 PrecompileParsedFunctionHelper(Precompiler* precompiler, |
156 ParsedFunction* parsed_function, | 155 ParsedFunction* parsed_function, |
157 bool optimized) | 156 bool optimized) |
158 : precompiler_(precompiler), | 157 : precompiler_(precompiler), |
159 parsed_function_(parsed_function), | 158 parsed_function_(parsed_function), |
160 optimized_(optimized), | 159 optimized_(optimized), |
161 thread_(Thread::Current()) { | 160 thread_(Thread::Current()) {} |
162 } | |
163 | 161 |
164 bool Compile(CompilationPipeline* pipeline); | 162 bool Compile(CompilationPipeline* pipeline); |
165 | 163 |
166 private: | 164 private: |
167 ParsedFunction* parsed_function() const { return parsed_function_; } | 165 ParsedFunction* parsed_function() const { return parsed_function_; } |
168 bool optimized() const { return optimized_; } | 166 bool optimized() const { return optimized_; } |
169 Thread* thread() const { return thread_; } | 167 Thread* thread() const { return thread_; } |
170 Isolate* isolate() const { return thread_->isolate(); } | 168 Isolate* isolate() const { return thread_->isolate(); } |
171 | 169 |
172 void FinalizeCompilation(Assembler* assembler, | 170 void FinalizeCompilation(Assembler* assembler, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 intptr_t* upper_limit) { | 207 intptr_t* upper_limit) { |
210 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); | 208 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); |
211 | 209 |
212 if (!type.IsInstantiated()) return false; | 210 if (!type.IsInstantiated()) return false; |
213 if (type.IsFunctionType()) return false; | 211 if (type.IsFunctionType()) return false; |
214 | 212 |
215 Zone* zone = thread_->zone(); | 213 Zone* zone = thread_->zone(); |
216 const TypeArguments& type_arguments = | 214 const TypeArguments& type_arguments = |
217 TypeArguments::Handle(zone, type.arguments()); | 215 TypeArguments::Handle(zone, type.arguments()); |
218 if (!type_arguments.IsNull() && | 216 if (!type_arguments.IsNull() && |
219 !type_arguments.IsRaw(0, type_arguments.Length())) return false; | 217 !type_arguments.IsRaw(0, type_arguments.Length())) |
| 218 return false; |
220 | 219 |
221 | 220 |
222 intptr_t type_cid = type.type_class_id(); | 221 intptr_t type_cid = type.type_class_id(); |
223 if (lower_limits_[type_cid] == kNotContiguous) return false; | 222 if (lower_limits_[type_cid] == kNotContiguous) return false; |
224 if (lower_limits_[type_cid] != kNotComputed) { | 223 if (lower_limits_[type_cid] != kNotComputed) { |
225 *lower_limit = lower_limits_[type_cid]; | 224 *lower_limit = lower_limits_[type_cid]; |
226 *upper_limit = upper_limits_[type_cid]; | 225 *upper_limit = upper_limits_[type_cid]; |
227 return true; | 226 return true; |
228 } | 227 } |
229 | 228 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 THR_Print("Type check for %s is cid range [%" Pd ", %" Pd "]\n", | 282 THR_Print("Type check for %s is cid range [%" Pd ", %" Pd "]\n", |
284 type.ToCString(), *lower_limit, *upper_limit); | 283 type.ToCString(), *lower_limit, *upper_limit); |
285 } | 284 } |
286 | 285 |
287 lower_limits_[type_cid] = *lower_limit; | 286 lower_limits_[type_cid] = *lower_limit; |
288 upper_limits_[type_cid] = *upper_limit; | 287 upper_limits_[type_cid] = *upper_limit; |
289 return true; | 288 return true; |
290 } | 289 } |
291 | 290 |
292 | 291 |
293 Precompiler::Precompiler(Thread* thread, bool reset_fields) : | 292 Precompiler::Precompiler(Thread* thread, bool reset_fields) |
294 thread_(thread), | 293 : thread_(thread), |
295 zone_(NULL), | 294 zone_(NULL), |
296 isolate_(thread->isolate()), | 295 isolate_(thread->isolate()), |
297 reset_fields_(reset_fields), | 296 reset_fields_(reset_fields), |
298 changed_(false), | 297 changed_(false), |
299 function_count_(0), | 298 function_count_(0), |
300 class_count_(0), | 299 class_count_(0), |
301 selector_count_(0), | 300 selector_count_(0), |
302 dropped_function_count_(0), | 301 dropped_function_count_(0), |
303 dropped_field_count_(0), | 302 dropped_field_count_(0), |
304 dropped_class_count_(0), | 303 dropped_class_count_(0), |
305 dropped_typearg_count_(0), | 304 dropped_typearg_count_(0), |
306 dropped_type_count_(0), | 305 dropped_type_count_(0), |
307 dropped_library_count_(0), | 306 dropped_library_count_(0), |
308 libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())), | 307 libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())), |
309 pending_functions_( | 308 pending_functions_( |
310 GrowableObjectArray::Handle(GrowableObjectArray::New())), | 309 GrowableObjectArray::Handle(GrowableObjectArray::New())), |
311 sent_selectors_(), | 310 sent_selectors_(), |
312 enqueued_functions_(), | 311 enqueued_functions_(), |
313 fields_to_retain_(), | 312 fields_to_retain_(), |
314 functions_to_retain_(), | 313 functions_to_retain_(), |
315 classes_to_retain_(), | 314 classes_to_retain_(), |
316 typeargs_to_retain_(), | 315 typeargs_to_retain_(), |
317 types_to_retain_(), | 316 types_to_retain_(), |
318 consts_to_retain_(), | 317 consts_to_retain_(), |
319 field_type_map_(), | 318 field_type_map_(), |
320 error_(Error::Handle()), | 319 error_(Error::Handle()), |
321 get_runtime_type_is_unique_(false) { | 320 get_runtime_type_is_unique_(false) {} |
322 } | |
323 | 321 |
324 | 322 |
325 void Precompiler::DoCompileAll( | 323 void Precompiler::DoCompileAll( |
326 Dart_QualifiedFunctionName embedder_entry_points[]) { | 324 Dart_QualifiedFunctionName embedder_entry_points[]) { |
327 ASSERT(I->compilation_allowed()); | 325 ASSERT(I->compilation_allowed()); |
328 | 326 |
329 { | 327 { |
330 StackZone stack_zone(T); | 328 StackZone stack_zone(T); |
331 zone_ = stack_zone.GetZone(); | 329 zone_ = stack_zone.GetZone(); |
332 | 330 |
333 { HANDLESCOPE(T); | 331 { |
| 332 HANDLESCOPE(T); |
334 // Make sure class hierarchy is stable before compilation so that CHA | 333 // Make sure class hierarchy is stable before compilation so that CHA |
335 // can be used. Also ensures lookup of entry points won't miss functions | 334 // can be used. Also ensures lookup of entry points won't miss functions |
336 // because their class hasn't been finalized yet. | 335 // because their class hasn't been finalized yet. |
337 FinalizeAllClasses(); | 336 FinalizeAllClasses(); |
338 | 337 |
339 SortClasses(); | 338 SortClasses(); |
340 TypeRangeCache trc(T, I->class_table()->NumCids()); | 339 TypeRangeCache trc(T, I->class_table()->NumCids()); |
341 | 340 |
342 // Precompile static initializers to compute result type information. | 341 // Precompile static initializers to compute result type information. |
343 PrecompileStaticInitializers(); | 342 PrecompileStaticInitializers(); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 // Ignore compile-time errors here. If the field is actually used, | 446 // Ignore compile-time errors here. If the field is actually used, |
448 // the error will be reported later during Iterate(). | 447 // the error will be reported later during Iterate(). |
449 } | 448 } |
450 } | 449 } |
451 | 450 |
452 | 451 |
453 void Precompiler::PrecompileStaticInitializers() { | 452 void Precompiler::PrecompileStaticInitializers() { |
454 class StaticInitializerVisitor : public ClassVisitor { | 453 class StaticInitializerVisitor : public ClassVisitor { |
455 public: | 454 public: |
456 explicit StaticInitializerVisitor(Zone* zone) | 455 explicit StaticInitializerVisitor(Zone* zone) |
457 : fields_(Array::Handle(zone)), | 456 : fields_(Array::Handle(zone)), |
458 field_(Field::Handle(zone)), | 457 field_(Field::Handle(zone)), |
459 function_(Function::Handle(zone)) { } | 458 function_(Function::Handle(zone)) {} |
460 void Visit(const Class& cls) { | 459 void Visit(const Class& cls) { |
461 fields_ = cls.fields(); | 460 fields_ = cls.fields(); |
462 for (intptr_t j = 0; j < fields_.Length(); j++) { | 461 for (intptr_t j = 0; j < fields_.Length(); j++) { |
463 field_ ^= fields_.At(j); | 462 field_ ^= fields_.At(j); |
464 if (field_.is_static() && | 463 if (field_.is_static() && field_.is_final() && |
465 field_.is_final() && | |
466 field_.has_initializer()) { | 464 field_.has_initializer()) { |
467 if (FLAG_trace_precompiler) { | 465 if (FLAG_trace_precompiler) { |
468 THR_Print("Precompiling initializer for %s\n", field_.ToCString()); | 466 THR_Print("Precompiling initializer for %s\n", field_.ToCString()); |
469 } | 467 } |
470 CompileStaticInitializerIgnoreErrors(field_); | 468 CompileStaticInitializerIgnoreErrors(field_); |
471 } | 469 } |
472 } | 470 } |
473 } | 471 } |
474 | 472 |
475 private: | 473 private: |
476 Array& fields_; | 474 Array& fields_; |
477 Field& field_; | 475 Field& field_; |
478 Function& function_; | 476 Function& function_; |
479 }; | 477 }; |
480 | 478 |
481 HANDLESCOPE(T); | 479 HANDLESCOPE(T); |
482 StaticInitializerVisitor visitor(Z); | 480 StaticInitializerVisitor visitor(Z); |
483 VisitClasses(&visitor); | 481 VisitClasses(&visitor); |
484 } | 482 } |
485 | 483 |
486 | 484 |
487 void Precompiler::PrecompileConstructors() { | 485 void Precompiler::PrecompileConstructors() { |
488 class ConstructorVisitor : public FunctionVisitor { | 486 class ConstructorVisitor : public FunctionVisitor { |
489 public: | 487 public: |
490 explicit ConstructorVisitor(Precompiler* precompiler, Zone* zone) | 488 explicit ConstructorVisitor(Precompiler* precompiler, Zone* zone) |
491 : precompiler_(precompiler), zone_(zone) { | 489 : precompiler_(precompiler), zone_(zone) {} |
492 } | |
493 void Visit(const Function& function) { | 490 void Visit(const Function& function) { |
494 if (!function.IsGenerativeConstructor()) return; | 491 if (!function.IsGenerativeConstructor()) return; |
495 if (function.HasCode()) { | 492 if (function.HasCode()) { |
496 // Const constructors may have been visited before. Recompile them here | 493 // Const constructors may have been visited before. Recompile them here |
497 // to collect type information for final fields for them as well. | 494 // to collect type information for final fields for them as well. |
498 function.ClearCode(); | 495 function.ClearCode(); |
499 } | 496 } |
500 if (FLAG_trace_precompiler) { | 497 if (FLAG_trace_precompiler) { |
501 THR_Print("Precompiling constructor %s\n", function.ToCString()); | 498 THR_Print("Precompiling constructor %s\n", function.ToCString()); |
502 } | 499 } |
503 CompileFunction(precompiler_, | 500 CompileFunction(precompiler_, Thread::Current(), zone_, function, |
504 Thread::Current(), | |
505 zone_, | |
506 function, | |
507 precompiler_->field_type_map()); | 501 precompiler_->field_type_map()); |
508 } | 502 } |
509 | 503 |
510 private: | 504 private: |
511 Precompiler* precompiler_; | 505 Precompiler* precompiler_; |
512 Zone* zone_; | 506 Zone* zone_; |
513 }; | 507 }; |
514 | 508 |
515 HANDLESCOPE(T); | 509 HANDLESCOPE(T); |
516 ConstructorVisitor visitor(this, zone_); | 510 ConstructorVisitor visitor(this, zone_); |
517 VisitFunctions(&visitor); | 511 VisitFunctions(&visitor); |
518 | 512 |
519 FieldTypeMap::Iterator it(field_type_map_.GetIterator()); | 513 FieldTypeMap::Iterator it(field_type_map_.GetIterator()); |
520 for (FieldTypePair* current = it.Next(); | 514 for (FieldTypePair* current = it.Next(); current != NULL; |
521 current != NULL; | |
522 current = it.Next()) { | 515 current = it.Next()) { |
523 const intptr_t cid = current->cid_; | 516 const intptr_t cid = current->cid_; |
524 current->field_->set_guarded_cid(cid); | 517 current->field_->set_guarded_cid(cid); |
525 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); | 518 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); |
526 if (FLAG_trace_precompiler) { | 519 if (FLAG_trace_precompiler) { |
527 THR_Print("Field %s <- Type %s\n", current->field_->ToCString(), | 520 THR_Print( |
| 521 "Field %s <- Type %s\n", current->field_->ToCString(), |
528 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); | 522 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); |
529 } | 523 } |
530 } | 524 } |
531 } | 525 } |
532 | 526 |
533 | 527 |
534 void Precompiler::ClearAllCode() { | 528 void Precompiler::ClearAllCode() { |
535 class ClearCodeFunctionVisitor : public FunctionVisitor { | 529 class ClearCodeFunctionVisitor : public FunctionVisitor { |
536 void Visit(const Function& function) { | 530 void Visit(const Function& function) { |
537 function.ClearCode(); | 531 function.ClearCode(); |
538 function.ClearICDataArray(); | 532 function.ClearICDataArray(); |
539 } | 533 } |
540 }; | 534 }; |
541 ClearCodeFunctionVisitor function_visitor; | 535 ClearCodeFunctionVisitor function_visitor; |
542 VisitFunctions(&function_visitor); | 536 VisitFunctions(&function_visitor); |
543 | 537 |
544 class ClearCodeClassVisitor : public ClassVisitor { | 538 class ClearCodeClassVisitor : public ClassVisitor { |
545 void Visit(const Class& cls) { | 539 void Visit(const Class& cls) { cls.DisableAllocationStub(); } |
546 cls.DisableAllocationStub(); | |
547 } | |
548 }; | 540 }; |
549 ClearCodeClassVisitor class_visitor; | 541 ClearCodeClassVisitor class_visitor; |
550 VisitClasses(&class_visitor); | 542 VisitClasses(&class_visitor); |
551 } | 543 } |
552 | 544 |
553 | 545 |
554 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { | 546 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { |
555 // Note that <rootlibrary>.main is not a root. The appropriate main will be | 547 // Note that <rootlibrary>.main is not a root. The appropriate main will be |
556 // discovered through _getMainClosure. | 548 // discovered through _getMainClosure. |
557 | 549 |
558 AddSelector(Symbols::NoSuchMethod()); | 550 AddSelector(Symbols::NoSuchMethod()); |
559 | 551 |
560 AddSelector(Symbols::Call()); // For speed, not correctness. | 552 AddSelector(Symbols::Call()); // For speed, not correctness. |
561 | 553 |
562 // Allocated from C++. | 554 // Allocated from C++. |
563 Class& cls = Class::Handle(Z); | 555 Class& cls = Class::Handle(Z); |
564 for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) { | 556 for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) { |
565 ASSERT(isolate()->class_table()->IsValidIndex(cid)); | 557 ASSERT(isolate()->class_table()->IsValidIndex(cid)); |
566 if (!isolate()->class_table()->HasValidClassAt(cid)) { | 558 if (!isolate()->class_table()->HasValidClassAt(cid)) { |
567 continue; | 559 continue; |
568 } | 560 } |
569 if ((cid == kDynamicCid) || | 561 if ((cid == kDynamicCid) || (cid == kVoidCid) || |
570 (cid == kVoidCid) || | 562 (cid == kFreeListElement) || (cid == kForwardingCorpse)) { |
571 (cid == kFreeListElement) || | |
572 (cid == kForwardingCorpse)) { | |
573 continue; | 563 continue; |
574 } | 564 } |
575 cls = isolate()->class_table()->At(cid); | 565 cls = isolate()->class_table()->At(cid); |
576 AddInstantiatedClass(cls); | 566 AddInstantiatedClass(cls); |
577 } | 567 } |
578 | 568 |
579 Dart_QualifiedFunctionName vm_entry_points[] = { | 569 Dart_QualifiedFunctionName vm_entry_points[] = { |
580 // Functions | 570 // Functions |
581 { "dart:async", "::", "_setScheduleImmediateClosure" }, | 571 {"dart:async", "::", "_setScheduleImmediateClosure"}, |
582 { "dart:core", "::", "_completeDeferredLoads" }, | 572 {"dart:core", "::", "_completeDeferredLoads"}, |
583 { "dart:core", "AbstractClassInstantiationError", | 573 {"dart:core", "AbstractClassInstantiationError", |
584 "AbstractClassInstantiationError._create" }, | 574 "AbstractClassInstantiationError._create"}, |
585 { "dart:core", "ArgumentError", "ArgumentError." }, | 575 {"dart:core", "ArgumentError", "ArgumentError."}, |
586 { "dart:core", "CyclicInitializationError", | 576 {"dart:core", "CyclicInitializationError", "CyclicInitializationError."}, |
587 "CyclicInitializationError." }, | 577 {"dart:core", "FallThroughError", "FallThroughError._create"}, |
588 { "dart:core", "FallThroughError", "FallThroughError._create" }, | 578 {"dart:core", "FormatException", "FormatException."}, |
589 { "dart:core", "FormatException", "FormatException." }, | 579 {"dart:core", "NoSuchMethodError", "NoSuchMethodError._withType"}, |
590 { "dart:core", "NoSuchMethodError", "NoSuchMethodError._withType" }, | 580 {"dart:core", "NullThrownError", "NullThrownError."}, |
591 { "dart:core", "NullThrownError", "NullThrownError." }, | 581 {"dart:core", "OutOfMemoryError", "OutOfMemoryError."}, |
592 { "dart:core", "OutOfMemoryError", "OutOfMemoryError." }, | 582 {"dart:core", "RangeError", "RangeError."}, |
593 { "dart:core", "RangeError", "RangeError." }, | 583 {"dart:core", "RangeError", "RangeError.range"}, |
594 { "dart:core", "RangeError", "RangeError.range" }, | 584 {"dart:core", "StackOverflowError", "StackOverflowError."}, |
595 { "dart:core", "StackOverflowError", "StackOverflowError." }, | 585 {"dart:core", "UnsupportedError", "UnsupportedError."}, |
596 { "dart:core", "UnsupportedError", "UnsupportedError." }, | 586 {"dart:core", "_AssertionError", "_AssertionError._create"}, |
597 { "dart:core", "_AssertionError", "_AssertionError._create" }, | 587 {"dart:core", "_CastError", "_CastError._create"}, |
598 { "dart:core", "_CastError", "_CastError._create" }, | 588 {"dart:core", "_InternalError", "_InternalError."}, |
599 { "dart:core", "_InternalError", "_InternalError." }, | 589 {"dart:core", "_InvocationMirror", "_allocateInvocationMirror"}, |
600 { "dart:core", "_InvocationMirror", "_allocateInvocationMirror" }, | 590 {"dart:core", "_TypeError", "_TypeError._create"}, |
601 { "dart:core", "_TypeError", "_TypeError._create" }, | 591 {"dart:isolate", "IsolateSpawnException", "IsolateSpawnException."}, |
602 { "dart:isolate", "IsolateSpawnException", "IsolateSpawnException." }, | 592 {"dart:isolate", "::", "_getIsolateScheduleImmediateClosure"}, |
603 { "dart:isolate", "::", "_getIsolateScheduleImmediateClosure" }, | 593 {"dart:isolate", "::", "_setupHooks"}, |
604 { "dart:isolate", "::", "_setupHooks" }, | 594 {"dart:isolate", "::", "_startMainIsolate"}, |
605 { "dart:isolate", "::", "_startMainIsolate" }, | 595 {"dart:isolate", "::", "_startIsolate"}, |
606 { "dart:isolate", "::", "_startIsolate" }, | 596 {"dart:isolate", "_RawReceivePortImpl", "_handleMessage"}, |
607 { "dart:isolate", "_RawReceivePortImpl", "_handleMessage" }, | 597 {"dart:isolate", "_RawReceivePortImpl", "_lookupHandler"}, |
608 { "dart:isolate", "_RawReceivePortImpl", "_lookupHandler" }, | 598 {"dart:isolate", "_SendPortImpl", "send"}, |
609 { "dart:isolate", "_SendPortImpl", "send" }, | 599 {"dart:typed_data", "ByteData", "ByteData."}, |
610 { "dart:typed_data", "ByteData", "ByteData." }, | 600 {"dart:typed_data", "ByteData", "ByteData._view"}, |
611 { "dart:typed_data", "ByteData", "ByteData._view" }, | 601 {"dart:typed_data", "ByteBuffer", "ByteBuffer._New"}, |
612 { "dart:typed_data", "ByteBuffer", "ByteBuffer._New" }, | 602 {"dart:_vmservice", "::", "_registerIsolate"}, |
613 { "dart:_vmservice", "::", "_registerIsolate" }, | 603 {"dart:_vmservice", "::", "boot"}, |
614 { "dart:_vmservice", "::", "boot" }, | |
615 #if !defined(PRODUCT) | 604 #if !defined(PRODUCT) |
616 { "dart:developer", "Metrics", "_printMetrics" }, | 605 {"dart:developer", "Metrics", "_printMetrics"}, |
617 { "dart:developer", "::", "_runExtension" }, | 606 {"dart:developer", "::", "_runExtension"}, |
618 { "dart:isolate", "::", "_runPendingImmediateCallback" }, | 607 {"dart:isolate", "::", "_runPendingImmediateCallback"}, |
619 #endif // !PRODUCT | 608 #endif // !PRODUCT |
620 // Fields | 609 // Fields |
621 { "dart:core", "Error", "_stackTrace" }, | 610 {"dart:core", "Error", "_stackTrace"}, |
622 { "dart:math", "_Random", "_state" }, | 611 {"dart:math", "_Random", "_state"}, |
623 { NULL, NULL, NULL } // Must be terminated with NULL entries. | 612 {NULL, NULL, NULL} // Must be terminated with NULL entries. |
624 }; | 613 }; |
625 | 614 |
626 AddEntryPoints(vm_entry_points); | 615 AddEntryPoints(vm_entry_points); |
627 AddEntryPoints(embedder_entry_points); | 616 AddEntryPoints(embedder_entry_points); |
628 } | 617 } |
629 | 618 |
630 | 619 |
631 void Precompiler::AddEntryPoints(Dart_QualifiedFunctionName entry_points[]) { | 620 void Precompiler::AddEntryPoints(Dart_QualifiedFunctionName entry_points[]) { |
632 Library& lib = Library::Handle(Z); | 621 Library& lib = Library::Handle(Z); |
633 Class& cls = Class::Handle(Z); | 622 Class& cls = Class::Handle(Z); |
634 Function& func = Function::Handle(Z); | 623 Function& func = Function::Handle(Z); |
635 Field& field = Field::Handle(Z); | 624 Field& field = Field::Handle(Z); |
636 String& library_uri = String::Handle(Z); | 625 String& library_uri = String::Handle(Z); |
637 String& class_name = String::Handle(Z); | 626 String& class_name = String::Handle(Z); |
638 String& function_name = String::Handle(Z); | 627 String& function_name = String::Handle(Z); |
639 | 628 |
640 for (intptr_t i = 0; entry_points[i].library_uri != NULL; i++) { | 629 for (intptr_t i = 0; entry_points[i].library_uri != NULL; i++) { |
641 library_uri = Symbols::New(thread(), entry_points[i].library_uri); | 630 library_uri = Symbols::New(thread(), entry_points[i].library_uri); |
642 class_name = Symbols::New(thread(), entry_points[i].class_name); | 631 class_name = Symbols::New(thread(), entry_points[i].class_name); |
643 function_name = Symbols::New(thread(), entry_points[i].function_name); | 632 function_name = Symbols::New(thread(), entry_points[i].function_name); |
644 | 633 |
645 lib = Library::LookupLibrary(T, library_uri); | 634 lib = Library::LookupLibrary(T, library_uri); |
646 if (lib.IsNull()) { | 635 if (lib.IsNull()) { |
647 String& msg = String::Handle(Z, String::NewFormatted( | 636 String& msg = |
648 "Cannot find entry point %s\n", entry_points[i].library_uri)); | 637 String::Handle(Z, String::NewFormatted("Cannot find entry point %s\n", |
| 638 entry_points[i].library_uri)); |
649 Jump(Error::Handle(Z, ApiError::New(msg))); | 639 Jump(Error::Handle(Z, ApiError::New(msg))); |
650 UNREACHABLE(); | 640 UNREACHABLE(); |
651 } | 641 } |
652 | 642 |
653 if (class_name.raw() == Symbols::TopLevel().raw()) { | 643 if (class_name.raw() == Symbols::TopLevel().raw()) { |
654 if (Library::IsPrivate(function_name)) { | 644 if (Library::IsPrivate(function_name)) { |
655 function_name = lib.PrivateName(function_name); | 645 function_name = lib.PrivateName(function_name); |
656 } | 646 } |
657 func = lib.LookupLocalFunction(function_name); | 647 func = lib.LookupLocalFunction(function_name); |
658 field = lib.LookupLocalField(function_name); | 648 field = lib.LookupLocalField(function_name); |
659 } else { | 649 } else { |
660 if (Library::IsPrivate(class_name)) { | 650 if (Library::IsPrivate(class_name)) { |
661 class_name = lib.PrivateName(class_name); | 651 class_name = lib.PrivateName(class_name); |
662 } | 652 } |
663 cls = lib.LookupLocalClass(class_name); | 653 cls = lib.LookupLocalClass(class_name); |
664 if (cls.IsNull()) { | 654 if (cls.IsNull()) { |
665 String& msg = String::Handle(Z, String::NewFormatted( | 655 String& msg = String::Handle( |
666 "Cannot find entry point %s %s\n", | 656 Z, String::NewFormatted("Cannot find entry point %s %s\n", |
667 entry_points[i].library_uri, | 657 entry_points[i].library_uri, |
668 entry_points[i].class_name)); | 658 entry_points[i].class_name)); |
669 Jump(Error::Handle(Z, ApiError::New(msg))); | 659 Jump(Error::Handle(Z, ApiError::New(msg))); |
670 UNREACHABLE(); | 660 UNREACHABLE(); |
671 } | 661 } |
672 | 662 |
673 ASSERT(!cls.IsNull()); | 663 ASSERT(!cls.IsNull()); |
674 func = cls.LookupFunctionAllowPrivate(function_name); | 664 func = cls.LookupFunctionAllowPrivate(function_name); |
675 field = cls.LookupFieldAllowPrivate(function_name); | 665 field = cls.LookupFieldAllowPrivate(function_name); |
676 } | 666 } |
677 | 667 |
678 if (func.IsNull() && field.IsNull()) { | 668 if (func.IsNull() && field.IsNull()) { |
679 String& msg = String::Handle(Z, String::NewFormatted( | 669 String& msg = String::Handle( |
680 "Cannot find entry point %s %s %s\n", | 670 Z, String::NewFormatted("Cannot find entry point %s %s %s\n", |
681 entry_points[i].library_uri, | 671 entry_points[i].library_uri, |
682 entry_points[i].class_name, | 672 entry_points[i].class_name, |
683 entry_points[i].function_name)); | 673 entry_points[i].function_name)); |
684 Jump(Error::Handle(Z, ApiError::New(msg))); | 674 Jump(Error::Handle(Z, ApiError::New(msg))); |
685 UNREACHABLE(); | 675 UNREACHABLE(); |
686 } | 676 } |
687 | 677 |
688 if (!func.IsNull()) { | 678 if (!func.IsNull()) { |
689 AddFunction(func); | 679 AddFunction(func); |
690 if (func.IsGenerativeConstructor()) { | 680 if (func.IsGenerativeConstructor()) { |
691 // Allocation stubs are referenced from the call site of the | 681 // Allocation stubs are referenced from the call site of the |
692 // constructor, not in the constructor itself. So compiling the | 682 // constructor, not in the constructor itself. So compiling the |
693 // constructor isn't enough for us to discover the class is | 683 // constructor isn't enough for us to discover the class is |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 if (!field_type.IsFunctionType()) continue; | 742 if (!field_type.IsFunctionType()) continue; |
753 field_name = field.name(); | 743 field_name = field.name(); |
754 if (!IsSent(field_name)) continue; | 744 if (!IsSent(field_name)) continue; |
755 // Create arguments descriptor with fixed parameters from | 745 // Create arguments descriptor with fixed parameters from |
756 // signature of field_type. | 746 // signature of field_type. |
757 function = Type::Cast(field_type).signature(); | 747 function = Type::Cast(field_type).signature(); |
758 if (function.HasOptionalParameters()) continue; | 748 if (function.HasOptionalParameters()) continue; |
759 if (FLAG_trace_precompiler) { | 749 if (FLAG_trace_precompiler) { |
760 THR_Print("Found callback field %s\n", field_name.ToCString()); | 750 THR_Print("Found callback field %s\n", field_name.ToCString()); |
761 } | 751 } |
762 args_desc = | 752 args_desc = ArgumentsDescriptor::New(function.num_fixed_parameters()); |
763 ArgumentsDescriptor::New(function.num_fixed_parameters()); | |
764 cids.Clear(); | 753 cids.Clear(); |
765 if (T->cha()->ConcreteSubclasses(cls, &cids)) { | 754 if (T->cha()->ConcreteSubclasses(cls, &cids)) { |
766 for (intptr_t j = 0; j < cids.length(); ++j) { | 755 for (intptr_t j = 0; j < cids.length(); ++j) { |
767 subcls ^= I->class_table()->At(cids[j]); | 756 subcls ^= I->class_table()->At(cids[j]); |
768 if (subcls.is_allocated()) { | 757 if (subcls.is_allocated()) { |
769 // Add dispatcher to cls. | 758 // Add dispatcher to cls. |
770 dispatcher = subcls.GetInvocationDispatcher( | 759 dispatcher = subcls.GetInvocationDispatcher( |
771 field_name, | 760 field_name, args_desc, RawFunction::kInvokeFieldDispatcher, |
772 args_desc, | |
773 RawFunction::kInvokeFieldDispatcher, | |
774 /* create_if_absent = */ true); | 761 /* create_if_absent = */ true); |
775 if (FLAG_trace_precompiler) { | 762 if (FLAG_trace_precompiler) { |
776 THR_Print("Added invoke-field-dispatcher for %s to %s\n", | 763 THR_Print("Added invoke-field-dispatcher for %s to %s\n", |
777 field_name.ToCString(), subcls.ToCString()); | 764 field_name.ToCString(), subcls.ToCString()); |
778 } | 765 } |
779 AddFunction(dispatcher); | 766 AddFunction(dispatcher); |
780 } | 767 } |
781 } | 768 } |
782 } | 769 } |
783 } | 770 } |
784 } | 771 } |
785 } | 772 } |
786 } | 773 } |
787 | 774 |
788 | 775 |
789 void Precompiler::ProcessFunction(const Function& function) { | 776 void Precompiler::ProcessFunction(const Function& function) { |
790 if (!function.HasCode()) { | 777 if (!function.HasCode()) { |
791 function_count_++; | 778 function_count_++; |
792 | 779 |
793 if (FLAG_trace_precompiler) { | 780 if (FLAG_trace_precompiler) { |
794 THR_Print("Precompiling %" Pd " %s (%s, %s)\n", | 781 THR_Print("Precompiling %" Pd " %s (%s, %s)\n", function_count_, |
795 function_count_, | |
796 function.ToLibNamePrefixedQualifiedCString(), | 782 function.ToLibNamePrefixedQualifiedCString(), |
797 function.token_pos().ToCString(), | 783 function.token_pos().ToCString(), |
798 Function::KindToCString(function.kind())); | 784 Function::KindToCString(function.kind())); |
799 } | 785 } |
800 | 786 |
801 ASSERT(!function.is_abstract()); | 787 ASSERT(!function.is_abstract()); |
802 ASSERT(!function.IsRedirectingFactory()); | 788 ASSERT(!function.IsRedirectingFactory()); |
803 | 789 |
804 error_ = CompileFunction(this, thread_, zone_, function); | 790 error_ = CompileFunction(this, thread_, zone_, function); |
805 if (!error_.IsNull()) { | 791 if (!error_.IsNull()) { |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 if (!instance.IsCanonical()) return; | 1036 if (!instance.IsCanonical()) return; |
1051 | 1037 |
1052 consts_to_retain_.Insert(&Instance::ZoneHandle(Z, instance.raw())); | 1038 consts_to_retain_.Insert(&Instance::ZoneHandle(Z, instance.raw())); |
1053 | 1039 |
1054 if (cls.NumTypeArguments() > 0) { | 1040 if (cls.NumTypeArguments() > 0) { |
1055 AddTypeArguments(TypeArguments::Handle(Z, instance.GetTypeArguments())); | 1041 AddTypeArguments(TypeArguments::Handle(Z, instance.GetTypeArguments())); |
1056 } | 1042 } |
1057 | 1043 |
1058 class ConstObjectVisitor : public ObjectPointerVisitor { | 1044 class ConstObjectVisitor : public ObjectPointerVisitor { |
1059 public: | 1045 public: |
1060 ConstObjectVisitor(Precompiler* precompiler, Isolate* isolate) : | 1046 ConstObjectVisitor(Precompiler* precompiler, Isolate* isolate) |
1061 ObjectPointerVisitor(isolate), | 1047 : ObjectPointerVisitor(isolate), |
1062 precompiler_(precompiler), | 1048 precompiler_(precompiler), |
1063 subinstance_(Object::Handle()) {} | 1049 subinstance_(Object::Handle()) {} |
1064 | 1050 |
1065 virtual void VisitPointers(RawObject** first, RawObject** last) { | 1051 virtual void VisitPointers(RawObject** first, RawObject** last) { |
1066 for (RawObject** current = first; current <= last; current++) { | 1052 for (RawObject** current = first; current <= last; current++) { |
1067 subinstance_ = *current; | 1053 subinstance_ = *current; |
1068 if (subinstance_.IsInstance()) { | 1054 if (subinstance_.IsInstance()) { |
1069 precompiler_->AddConstObject(Instance::Cast(subinstance_)); | 1055 precompiler_->AddConstObject(Instance::Cast(subinstance_)); |
1070 } | 1056 } |
1071 } | 1057 } |
1072 subinstance_ = Object::null(); | 1058 subinstance_ = Object::null(); |
1073 } | 1059 } |
1074 | 1060 |
1075 private: | 1061 private: |
1076 Precompiler* precompiler_; | 1062 Precompiler* precompiler_; |
1077 Object& subinstance_; | 1063 Object& subinstance_; |
1078 }; | 1064 }; |
1079 | 1065 |
1080 ConstObjectVisitor visitor(this, I); | 1066 ConstObjectVisitor visitor(this, I); |
1081 instance.raw()->VisitPointers(&visitor); | 1067 instance.raw()->VisitPointers(&visitor); |
1082 } | 1068 } |
1083 | 1069 |
1084 | 1070 |
1085 void Precompiler::AddClosureCall(const ICData& call_site) { | 1071 void Precompiler::AddClosureCall(const ICData& call_site) { |
1086 const Array& arguments_descriptor = | 1072 const Array& arguments_descriptor = |
1087 Array::Handle(Z, call_site.arguments_descriptor()); | 1073 Array::Handle(Z, call_site.arguments_descriptor()); |
1088 const Class& cache_class = | 1074 const Class& cache_class = |
1089 Class::Handle(Z, I->object_store()->closure_class()); | 1075 Class::Handle(Z, I->object_store()->closure_class()); |
1090 const Function& dispatcher = Function::Handle(Z, | 1076 const Function& dispatcher = Function::Handle( |
1091 cache_class.GetInvocationDispatcher(Symbols::Call(), | 1077 Z, cache_class.GetInvocationDispatcher( |
1092 arguments_descriptor, | 1078 Symbols::Call(), arguments_descriptor, |
1093 RawFunction::kInvokeFieldDispatcher, | 1079 RawFunction::kInvokeFieldDispatcher, true /* create_if_absent */)); |
1094 true /* create_if_absent */)); | |
1095 AddFunction(dispatcher); | 1080 AddFunction(dispatcher); |
1096 } | 1081 } |
1097 | 1082 |
1098 | 1083 |
1099 void Precompiler::AddField(const Field& field) { | 1084 void Precompiler::AddField(const Field& field) { |
1100 fields_to_retain_.Insert(&Field::ZoneHandle(Z, field.raw())); | 1085 fields_to_retain_.Insert(&Field::ZoneHandle(Z, field.raw())); |
1101 | 1086 |
1102 if (field.is_static()) { | 1087 if (field.is_static()) { |
1103 const Object& value = Object::Handle(Z, field.StaticValue()); | 1088 const Object& value = Object::Handle(Z, field.StaticValue()); |
1104 if (value.IsInstance()) { | 1089 if (value.IsInstance()) { |
1105 AddConstObject(Instance::Cast(value)); | 1090 AddConstObject(Instance::Cast(value)); |
1106 } | 1091 } |
1107 | 1092 |
1108 if (field.has_initializer()) { | 1093 if (field.has_initializer()) { |
1109 // Should not be in the middle of initialization while precompiling. | 1094 // Should not be in the middle of initialization while precompiling. |
1110 ASSERT(value.raw() != Object::transition_sentinel().raw()); | 1095 ASSERT(value.raw() != Object::transition_sentinel().raw()); |
1111 | 1096 |
1112 const bool is_initialized = value.raw() != Object::sentinel().raw(); | 1097 const bool is_initialized = value.raw() != Object::sentinel().raw(); |
1113 if (is_initialized && !reset_fields_) return; | 1098 if (is_initialized && !reset_fields_) return; |
1114 | 1099 |
1115 if (!field.HasPrecompiledInitializer() || | 1100 if (!field.HasPrecompiledInitializer() || |
1116 !Function::Handle(Z, field.PrecompiledInitializer()).HasCode()) { | 1101 !Function::Handle(Z, field.PrecompiledInitializer()).HasCode()) { |
1117 if (FLAG_trace_precompiler) { | 1102 if (FLAG_trace_precompiler) { |
1118 THR_Print("Precompiling initializer for %s\n", field.ToCString()); | 1103 THR_Print("Precompiling initializer for %s\n", field.ToCString()); |
1119 } | 1104 } |
1120 ASSERT(Dart::snapshot_kind() != Snapshot::kAppNoJIT); | 1105 ASSERT(Dart::snapshot_kind() != Snapshot::kAppNoJIT); |
1121 const Function& initializer = Function::Handle(Z, | 1106 const Function& initializer = Function::Handle( |
1122 CompileStaticInitializer(field, /* compute_type = */ true)); | 1107 Z, CompileStaticInitializer(field, /* compute_type = */ true)); |
1123 ASSERT(!initializer.IsNull()); | 1108 ASSERT(!initializer.IsNull()); |
1124 field.SetPrecompiledInitializer(initializer); | 1109 field.SetPrecompiledInitializer(initializer); |
1125 AddCalleesOf(initializer); | 1110 AddCalleesOf(initializer); |
1126 } | 1111 } |
1127 } | 1112 } |
1128 } | 1113 } |
1129 } | 1114 } |
1130 | 1115 |
1131 | 1116 |
1132 RawFunction* Precompiler::CompileStaticInitializer(const Field& field, | 1117 RawFunction* Precompiler::CompileStaticInitializer(const Field& field, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1180 if (!field.HasPrecompiledInitializer()) { | 1165 if (!field.HasPrecompiledInitializer()) { |
1181 initializer = CompileStaticInitializer(field, /* compute_type = */ false); | 1166 initializer = CompileStaticInitializer(field, /* compute_type = */ false); |
1182 } else { | 1167 } else { |
1183 initializer ^= field.PrecompiledInitializer(); | 1168 initializer ^= field.PrecompiledInitializer(); |
1184 } | 1169 } |
1185 // Invoke the function to evaluate the expression. | 1170 // Invoke the function to evaluate the expression. |
1186 return DartEntry::InvokeFunction(initializer, Object::empty_array()); | 1171 return DartEntry::InvokeFunction(initializer, Object::empty_array()); |
1187 } else { | 1172 } else { |
1188 Thread* const thread = Thread::Current(); | 1173 Thread* const thread = Thread::Current(); |
1189 StackZone zone(thread); | 1174 StackZone zone(thread); |
1190 const Error& error = | 1175 const Error& error = Error::Handle(thread->zone(), thread->sticky_error()); |
1191 Error::Handle(thread->zone(), thread->sticky_error()); | |
1192 thread->clear_sticky_error(); | 1176 thread->clear_sticky_error(); |
1193 return error.raw(); | 1177 return error.raw(); |
1194 } | 1178 } |
1195 UNREACHABLE(); | 1179 UNREACHABLE(); |
1196 return Object::null(); | 1180 return Object::null(); |
1197 } | 1181 } |
1198 | 1182 |
1199 | 1183 |
1200 RawObject* Precompiler::ExecuteOnce(SequenceNode* fragment) { | 1184 RawObject* Precompiler::ExecuteOnce(SequenceNode* fragment) { |
1201 LongJumpScope jump; | 1185 LongJumpScope jump; |
1202 if (setjmp(*jump.Set()) == 0) { | 1186 if (setjmp(*jump.Set()) == 0) { |
1203 Thread* const thread = Thread::Current(); | 1187 Thread* const thread = Thread::Current(); |
1204 if (FLAG_support_ast_printer && FLAG_trace_compiler) { | 1188 if (FLAG_support_ast_printer && FLAG_trace_compiler) { |
1205 THR_Print("compiling expression: "); | 1189 THR_Print("compiling expression: "); |
1206 AstPrinter ast_printer; | 1190 AstPrinter ast_printer; |
1207 ast_printer.PrintNode(fragment); | 1191 ast_printer.PrintNode(fragment); |
1208 } | 1192 } |
1209 | 1193 |
1210 // Create a dummy function object for the code generator. | 1194 // Create a dummy function object for the code generator. |
1211 // The function needs to be associated with a named Class: the interface | 1195 // The function needs to be associated with a named Class: the interface |
1212 // Function fits the bill. | 1196 // Function fits the bill. |
1213 const char* kEvalConst = "eval_const"; | 1197 const char* kEvalConst = "eval_const"; |
1214 const Function& func = Function::ZoneHandle(Function::New( | 1198 const Function& func = Function::ZoneHandle(Function::New( |
1215 String::Handle(Symbols::New(thread, kEvalConst)), | 1199 String::Handle(Symbols::New(thread, kEvalConst)), |
1216 RawFunction::kRegularFunction, | 1200 RawFunction::kRegularFunction, |
1217 true, // static function | 1201 true, // static function |
1218 false, // not const function | 1202 false, // not const function |
1219 false, // not abstract | 1203 false, // not abstract |
1220 false, // not external | 1204 false, // not external |
1221 false, // not native | 1205 false, // not native |
1222 Class::Handle(Type::Handle(Type::DartFunctionType()).type_class()), | 1206 Class::Handle(Type::Handle(Type::DartFunctionType()).type_class()), |
1223 fragment->token_pos())); | 1207 fragment->token_pos())); |
1224 | 1208 |
1225 func.set_result_type(Object::dynamic_type()); | 1209 func.set_result_type(Object::dynamic_type()); |
1226 func.set_num_fixed_parameters(0); | 1210 func.set_num_fixed_parameters(0); |
1227 func.SetNumOptionalParameters(0, true); | 1211 func.SetNumOptionalParameters(0, true); |
1228 // Manually generated AST, do not recompile. | 1212 // Manually generated AST, do not recompile. |
1229 func.SetIsOptimizable(false); | 1213 func.SetIsOptimizable(false); |
1230 func.set_is_debuggable(false); | 1214 func.set_is_debuggable(false); |
1231 | 1215 |
1232 // We compile the function here, even though InvokeFunction() below | 1216 // We compile the function here, even though InvokeFunction() below |
1233 // would compile func automatically. We are checking fewer invariants | 1217 // would compile func automatically. We are checking fewer invariants |
1234 // here. | 1218 // here. |
1235 ParsedFunction* parsed_function = new ParsedFunction(thread, func); | 1219 ParsedFunction* parsed_function = new ParsedFunction(thread, func); |
1236 parsed_function->SetNodeSequence(fragment); | 1220 parsed_function->SetNodeSequence(fragment); |
1237 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); | 1221 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); |
1238 fragment->scope()->AddVariable( | 1222 fragment->scope()->AddVariable(parsed_function->current_context_var()); |
1239 parsed_function->current_context_var()); | |
1240 parsed_function->AllocateVariables(); | 1223 parsed_function->AllocateVariables(); |
1241 | 1224 |
1242 // Non-optimized code generator. | 1225 // Non-optimized code generator. |
1243 DartPrecompilationPipeline pipeline(Thread::Current()->zone()); | 1226 DartPrecompilationPipeline pipeline(Thread::Current()->zone()); |
1244 PrecompileParsedFunctionHelper helper(/* precompiler = */ NULL, | 1227 PrecompileParsedFunctionHelper helper(/* precompiler = */ NULL, |
1245 parsed_function, | 1228 parsed_function, |
1246 /* optimized = */ false); | 1229 /* optimized = */ false); |
1247 helper.Compile(&pipeline); | 1230 helper.Compile(&pipeline); |
1248 Code::Handle(func.unoptimized_code()).set_var_descriptors( | 1231 Code::Handle(func.unoptimized_code()) |
1249 Object::empty_var_descriptors()); | 1232 .set_var_descriptors(Object::empty_var_descriptors()); |
1250 | 1233 |
1251 const Object& result = PassiveObject::Handle( | 1234 const Object& result = PassiveObject::Handle( |
1252 DartEntry::InvokeFunction(func, Object::empty_array())); | 1235 DartEntry::InvokeFunction(func, Object::empty_array())); |
1253 return result.raw(); | 1236 return result.raw(); |
1254 } else { | 1237 } else { |
1255 Thread* const thread = Thread::Current(); | 1238 Thread* const thread = Thread::Current(); |
1256 const Object& result = | 1239 const Object& result = PassiveObject::Handle(thread->sticky_error()); |
1257 PassiveObject::Handle(thread->sticky_error()); | |
1258 thread->clear_sticky_error(); | 1240 thread->clear_sticky_error(); |
1259 return result.raw(); | 1241 return result.raw(); |
1260 } | 1242 } |
1261 UNREACHABLE(); | 1243 UNREACHABLE(); |
1262 return Object::null(); | 1244 return Object::null(); |
1263 } | 1245 } |
1264 | 1246 |
1265 | 1247 |
1266 void Precompiler::AddFunction(const Function& function) { | 1248 void Precompiler::AddFunction(const Function& function) { |
1267 if (enqueued_functions_.Lookup(&function) != NULL) return; | 1249 if (enqueued_functions_.Lookup(&function) != NULL) return; |
(...skipping 14 matching lines...) Expand all Loading... |
1282 | 1264 |
1283 void Precompiler::AddSelector(const String& selector) { | 1265 void Precompiler::AddSelector(const String& selector) { |
1284 ASSERT(!selector.IsNull()); | 1266 ASSERT(!selector.IsNull()); |
1285 | 1267 |
1286 if (!IsSent(selector)) { | 1268 if (!IsSent(selector)) { |
1287 sent_selectors_.Insert(&String::ZoneHandle(Z, selector.raw())); | 1269 sent_selectors_.Insert(&String::ZoneHandle(Z, selector.raw())); |
1288 selector_count_++; | 1270 selector_count_++; |
1289 changed_ = true; | 1271 changed_ = true; |
1290 | 1272 |
1291 if (FLAG_trace_precompiler) { | 1273 if (FLAG_trace_precompiler) { |
1292 THR_Print("Enqueueing selector %" Pd " %s\n", | 1274 THR_Print("Enqueueing selector %" Pd " %s\n", selector_count_, |
1293 selector_count_, | |
1294 selector.ToCString()); | 1275 selector.ToCString()); |
1295 } | 1276 } |
1296 } | 1277 } |
1297 } | 1278 } |
1298 | 1279 |
1299 | 1280 |
1300 void Precompiler::AddInstantiatedClass(const Class& cls) { | 1281 void Precompiler::AddInstantiatedClass(const Class& cls) { |
1301 if (cls.is_allocated()) return; | 1282 if (cls.is_allocated()) return; |
1302 | 1283 |
1303 class_count_++; | 1284 class_count_++; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 | 1336 |
1356 // Handle the implicit call type conversions. | 1337 // Handle the implicit call type conversions. |
1357 if (Field::IsGetterName(selector)) { | 1338 if (Field::IsGetterName(selector)) { |
1358 selector2 = Field::NameFromGetter(selector); | 1339 selector2 = Field::NameFromGetter(selector); |
1359 selector3 = Symbols::Lookup(thread(), selector2); | 1340 selector3 = Symbols::Lookup(thread(), selector2); |
1360 if (IsSent(selector2)) { | 1341 if (IsSent(selector2)) { |
1361 // Call-through-getter. | 1342 // Call-through-getter. |
1362 // Function is get:foo and somewhere foo is called. | 1343 // Function is get:foo and somewhere foo is called. |
1363 AddFunction(function); | 1344 AddFunction(function); |
1364 } | 1345 } |
1365 selector3 = Symbols::LookupFromConcat(thread(), | 1346 selector3 = Symbols::LookupFromConcat( |
1366 Symbols::ClosurizePrefix(), selector2); | 1347 thread(), Symbols::ClosurizePrefix(), selector2); |
1367 if (IsSent(selector3)) { | 1348 if (IsSent(selector3)) { |
1368 // Hash-closurization. | 1349 // Hash-closurization. |
1369 // Function is get:foo and somewhere get:#foo is called. | 1350 // Function is get:foo and somewhere get:#foo is called. |
1370 AddFunction(function); | 1351 AddFunction(function); |
1371 | 1352 |
1372 function2 = function.ImplicitClosureFunction(); | 1353 function2 = function.ImplicitClosureFunction(); |
1373 AddFunction(function2); | 1354 AddFunction(function2); |
1374 | 1355 |
1375 // Add corresponding method extractor get:#foo. | 1356 // Add corresponding method extractor get:#foo. |
1376 function2 = function.GetMethodExtractor(selector3); | 1357 function2 = function.GetMethodExtractor(selector3); |
1377 AddFunction(function2); | 1358 AddFunction(function2); |
1378 } | 1359 } |
1379 } else if (Field::IsSetterName(selector)) { | 1360 } else if (Field::IsSetterName(selector)) { |
1380 selector2 = Symbols::LookupFromConcat(thread(), | 1361 selector2 = Symbols::LookupFromConcat( |
1381 Symbols::ClosurizePrefix(), selector); | 1362 thread(), Symbols::ClosurizePrefix(), selector); |
1382 if (IsSent(selector2)) { | 1363 if (IsSent(selector2)) { |
1383 // Hash-closurization. | 1364 // Hash-closurization. |
1384 // Function is set:foo and somewhere get:#set:foo is called. | 1365 // Function is set:foo and somewhere get:#set:foo is called. |
1385 AddFunction(function); | 1366 AddFunction(function); |
1386 | 1367 |
1387 function2 = function.ImplicitClosureFunction(); | 1368 function2 = function.ImplicitClosureFunction(); |
1388 AddFunction(function2); | 1369 AddFunction(function2); |
1389 | 1370 |
1390 // Add corresponding method extractor get:#set:foo. | 1371 // Add corresponding method extractor get:#set:foo. |
1391 function2 = function.GetMethodExtractor(selector2); | 1372 function2 = function.GetMethodExtractor(selector2); |
1392 AddFunction(function2); | 1373 AddFunction(function2); |
1393 } | 1374 } |
1394 } else if (function.kind() == RawFunction::kRegularFunction) { | 1375 } else if (function.kind() == RawFunction::kRegularFunction) { |
1395 selector2 = Field::LookupGetterSymbol(selector); | 1376 selector2 = Field::LookupGetterSymbol(selector); |
1396 if (IsSent(selector2)) { | 1377 if (IsSent(selector2)) { |
1397 // Closurization. | 1378 // Closurization. |
1398 // Function is foo and somewhere get:foo is called. | 1379 // Function is foo and somewhere get:foo is called. |
1399 function2 = function.ImplicitClosureFunction(); | 1380 function2 = function.ImplicitClosureFunction(); |
1400 AddFunction(function2); | 1381 AddFunction(function2); |
1401 | 1382 |
1402 // Add corresponding method extractor. | 1383 // Add corresponding method extractor. |
1403 function2 = function.GetMethodExtractor(selector2); | 1384 function2 = function.GetMethodExtractor(selector2); |
1404 AddFunction(function2); | 1385 AddFunction(function2); |
1405 } | 1386 } |
1406 selector2 = Symbols::LookupFromConcat(thread(), | 1387 selector2 = Symbols::LookupFromConcat( |
1407 Symbols::ClosurizePrefix(), selector); | 1388 thread(), Symbols::ClosurizePrefix(), selector); |
1408 if (IsSent(selector2)) { | 1389 if (IsSent(selector2)) { |
1409 // Hash-closurization. | 1390 // Hash-closurization. |
1410 // Function is foo and somewhere get:#foo is called. | 1391 // Function is foo and somewhere get:#foo is called. |
1411 function2 = function.ImplicitClosureFunction(); | 1392 function2 = function.ImplicitClosureFunction(); |
1412 AddFunction(function2); | 1393 AddFunction(function2); |
1413 | 1394 |
1414 // Add corresponding method extractor get:#foo | 1395 // Add corresponding method extractor get:#foo |
1415 function2 = function.GetMethodExtractor(selector2); | 1396 function2 = function.GetMethodExtractor(selector2); |
1416 AddFunction(function2); | 1397 AddFunction(function2); |
1417 } | 1398 } |
1418 } | 1399 } |
1419 } | 1400 } |
1420 } | 1401 } |
1421 } | 1402 } |
1422 } | 1403 } |
1423 | 1404 |
1424 | 1405 |
1425 class NameFunctionsTraits { | 1406 class NameFunctionsTraits { |
1426 public: | 1407 public: |
1427 static const char* Name() { return "NameFunctionsTraits"; } | 1408 static const char* Name() { return "NameFunctionsTraits"; } |
1428 static bool ReportStats() { return false; } | 1409 static bool ReportStats() { return false; } |
1429 | 1410 |
1430 static bool IsMatch(const Object& a, const Object& b) { | 1411 static bool IsMatch(const Object& a, const Object& b) { |
1431 return a.IsString() && b.IsString() && | 1412 return a.IsString() && b.IsString() && |
1432 String::Cast(a).Equals(String::Cast(b)); | 1413 String::Cast(a).Equals(String::Cast(b)); |
1433 } | 1414 } |
1434 static uword Hash(const Object& obj) { | 1415 static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); } |
1435 return String::Cast(obj).Hash(); | 1416 static RawObject* NewKey(const String& str) { return str.raw(); } |
1436 } | |
1437 static RawObject* NewKey(const String& str) { | |
1438 return str.raw(); | |
1439 } | |
1440 }; | 1417 }; |
1441 | 1418 |
1442 typedef UnorderedHashMap<NameFunctionsTraits> Table; | 1419 typedef UnorderedHashMap<NameFunctionsTraits> Table; |
1443 | 1420 |
1444 | 1421 |
1445 static void AddNameToFunctionsTable(Zone* zone, | 1422 static void AddNameToFunctionsTable(Zone* zone, |
1446 Table* table, | 1423 Table* table, |
1447 const String& fname, | 1424 const String& fname, |
1448 const Function& function) { | 1425 const Function& function) { |
1449 Array& farray = Array::Handle(zone); | 1426 Array& farray = Array::Handle(zone); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 get_runtime_type_is_unique_ = !farray.IsNull() && (farray.Length() == 1); | 1500 get_runtime_type_is_unique_ = !farray.IsNull() && (farray.Length() == 1); |
1524 | 1501 |
1525 if (FLAG_print_unique_targets) { | 1502 if (FLAG_print_unique_targets) { |
1526 UniqueFunctionsSet::Iterator unique_iter(&functions_set); | 1503 UniqueFunctionsSet::Iterator unique_iter(&functions_set); |
1527 while (unique_iter.MoveNext()) { | 1504 while (unique_iter.MoveNext()) { |
1528 intptr_t curr_key = unique_iter.Current(); | 1505 intptr_t curr_key = unique_iter.Current(); |
1529 function ^= functions_set.GetKey(curr_key); | 1506 function ^= functions_set.GetKey(curr_key); |
1530 THR_Print("* %s\n", function.ToQualifiedCString()); | 1507 THR_Print("* %s\n", function.ToQualifiedCString()); |
1531 } | 1508 } |
1532 THR_Print("%" Pd " of %" Pd " dynamic selectors are unique\n", | 1509 THR_Print("%" Pd " of %" Pd " dynamic selectors are unique\n", |
1533 functions_set.NumOccupied(), table.NumOccupied()); | 1510 functions_set.NumOccupied(), table.NumOccupied()); |
1534 } | 1511 } |
1535 | 1512 |
1536 isolate()->object_store()->set_unique_dynamic_targets( | 1513 isolate()->object_store()->set_unique_dynamic_targets( |
1537 functions_set.Release()); | 1514 functions_set.Release()); |
1538 table.Release(); | 1515 table.Release(); |
1539 } | 1516 } |
1540 | 1517 |
1541 | 1518 |
1542 void Precompiler::TraceConstFunctions() { | 1519 void Precompiler::TraceConstFunctions() { |
1543 // Compilation of const accessors happens outside of the treeshakers | 1520 // Compilation of const accessors happens outside of the treeshakers |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1729 type = field.type(); | 1706 type = field.type(); |
1730 AddType(type); | 1707 AddType(type); |
1731 } else { | 1708 } else { |
1732 bool top_level = cls.IsTopLevel(); | 1709 bool top_level = cls.IsTopLevel(); |
1733 if (top_level) { | 1710 if (top_level) { |
1734 name = field.DictionaryName(); | 1711 name = field.DictionaryName(); |
1735 lib.RemoveObject(field, name); | 1712 lib.RemoveObject(field, name); |
1736 } | 1713 } |
1737 dropped_field_count_++; | 1714 dropped_field_count_++; |
1738 if (FLAG_trace_precompiler) { | 1715 if (FLAG_trace_precompiler) { |
1739 THR_Print("Dropping field %s\n", | 1716 THR_Print("Dropping field %s\n", field.ToCString()); |
1740 field.ToCString()); | |
1741 } | 1717 } |
1742 } | 1718 } |
1743 } | 1719 } |
1744 | 1720 |
1745 if (retained_fields.Length() > 0) { | 1721 if (retained_fields.Length() > 0) { |
1746 fields = Array::MakeArray(retained_fields); | 1722 fields = Array::MakeArray(retained_fields); |
1747 cls.SetFields(fields); | 1723 cls.SetFields(fields); |
1748 } else { | 1724 } else { |
1749 cls.SetFields(Object::empty_array()); | 1725 cls.SetFields(Object::empty_array()); |
1750 } | 1726 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1809 } else { | 1785 } else { |
1810 dropped_typearg_count_++; | 1786 dropped_typearg_count_++; |
1811 } | 1787 } |
1812 } | 1788 } |
1813 typeargs_table.Release(); | 1789 typeargs_table.Release(); |
1814 } | 1790 } |
1815 | 1791 |
1816 // Now construct a new type arguments table and save in the object store. | 1792 // Now construct a new type arguments table and save in the object store. |
1817 const intptr_t dict_size = | 1793 const intptr_t dict_size = |
1818 Utils::RoundUpToPowerOfTwo(retained_typeargs.Length() * 4 / 3); | 1794 Utils::RoundUpToPowerOfTwo(retained_typeargs.Length() * 4 / 3); |
1819 typeargs_array = HashTables::New<CanonicalTypeArgumentsSet>(dict_size, | 1795 typeargs_array = |
1820 Heap::kOld); | 1796 HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld); |
1821 CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.raw()); | 1797 CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.raw()); |
1822 bool present; | 1798 bool present; |
1823 for (intptr_t i = 0; i < retained_typeargs.Length(); i++) { | 1799 for (intptr_t i = 0; i < retained_typeargs.Length(); i++) { |
1824 typeargs ^= retained_typeargs.At(i); | 1800 typeargs ^= retained_typeargs.At(i); |
1825 present = typeargs_table.Insert(typeargs); | 1801 present = typeargs_table.Insert(typeargs); |
1826 ASSERT(!present); | 1802 ASSERT(!present); |
1827 } | 1803 } |
1828 object_store->set_canonical_type_arguments(typeargs_table.Release()); | 1804 object_store->set_canonical_type_arguments(typeargs_table.Release()); |
1829 } | 1805 } |
1830 | 1806 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1962 ASSERT(!cls.is_allocated()); | 1938 ASSERT(!cls.is_allocated()); |
1963 constants = cls.constants(); | 1939 constants = cls.constants(); |
1964 ASSERT(constants.Length() == 0); | 1940 ASSERT(constants.Length() == 0); |
1965 | 1941 |
1966 #if defined(DEBUG) | 1942 #if defined(DEBUG) |
1967 intptr_t instances = | 1943 intptr_t instances = |
1968 class_table->StatsWithUpdatedSize(cid)->post_gc.new_count + | 1944 class_table->StatsWithUpdatedSize(cid)->post_gc.new_count + |
1969 class_table->StatsWithUpdatedSize(cid)->post_gc.old_count; | 1945 class_table->StatsWithUpdatedSize(cid)->post_gc.old_count; |
1970 if (instances != 0) { | 1946 if (instances != 0) { |
1971 FATAL2("Want to drop class %s, but it has %" Pd " instances\n", | 1947 FATAL2("Want to drop class %s, but it has %" Pd " instances\n", |
1972 cls.ToCString(), | 1948 cls.ToCString(), instances); |
1973 instances); | |
1974 } | 1949 } |
1975 #endif | 1950 #endif |
1976 | 1951 |
1977 dropped_class_count_++; | 1952 dropped_class_count_++; |
1978 if (FLAG_trace_precompiler) { | 1953 if (FLAG_trace_precompiler) { |
1979 THR_Print("Dropping class %" Pd " %s\n", cid, cls.ToCString()); | 1954 THR_Print("Dropping class %" Pd " %s\n", cid, cls.ToCString()); |
1980 } | 1955 } |
1981 | 1956 |
1982 #if defined(DEBUG) | 1957 #if defined(DEBUG) |
1983 class_table->Unregister(cid); | 1958 class_table->Unregister(cid); |
1984 #endif | 1959 #endif |
1985 cls.set_id(kIllegalCid); // We check this when serializing. | 1960 cls.set_id(kIllegalCid); // We check this when serializing. |
1986 | 1961 |
1987 lib = cls.library(); | 1962 lib = cls.library(); |
1988 name = cls.DictionaryName(); | 1963 name = cls.DictionaryName(); |
1989 lib.RemoveObject(cls, name); | 1964 lib.RemoveObject(cls, name); |
1990 } | 1965 } |
1991 } | 1966 } |
1992 | 1967 |
1993 | 1968 |
1994 void Precompiler::DropLibraries() { | 1969 void Precompiler::DropLibraries() { |
1995 const GrowableObjectArray& retained_libraries = | 1970 const GrowableObjectArray& retained_libraries = |
1996 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); | 1971 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
1997 const Library& root_lib = Library::Handle(Z, | 1972 const Library& root_lib = |
1998 I->object_store()->root_library()); | 1973 Library::Handle(Z, I->object_store()->root_library()); |
1999 Library& lib = Library::Handle(Z); | 1974 Library& lib = Library::Handle(Z); |
2000 | 1975 |
2001 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 1976 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
2002 lib ^= libraries_.At(i); | 1977 lib ^= libraries_.At(i); |
2003 lib.DropDependencies(); | 1978 lib.DropDependencies(); |
2004 intptr_t entries = 0; | 1979 intptr_t entries = 0; |
2005 DictionaryIterator it(lib); | 1980 DictionaryIterator it(lib); |
2006 while (it.HasNext()) { | 1981 while (it.HasNext()) { |
2007 it.GetNext(); | 1982 it.GetNext(); |
2008 entries++; | 1983 entries++; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2040 } | 2015 } |
2041 | 2016 |
2042 Library::RegisterLibraries(T, retained_libraries); | 2017 Library::RegisterLibraries(T, retained_libraries); |
2043 libraries_ = retained_libraries.raw(); | 2018 libraries_ = retained_libraries.raw(); |
2044 } | 2019 } |
2045 | 2020 |
2046 | 2021 |
2047 void Precompiler::BindStaticCalls() { | 2022 void Precompiler::BindStaticCalls() { |
2048 class BindStaticCallsVisitor : public FunctionVisitor { | 2023 class BindStaticCallsVisitor : public FunctionVisitor { |
2049 public: | 2024 public: |
2050 explicit BindStaticCallsVisitor(Zone* zone) : | 2025 explicit BindStaticCallsVisitor(Zone* zone) |
2051 code_(Code::Handle(zone)), | 2026 : code_(Code::Handle(zone)), |
2052 table_(Array::Handle(zone)), | 2027 table_(Array::Handle(zone)), |
2053 pc_offset_(Smi::Handle(zone)), | 2028 pc_offset_(Smi::Handle(zone)), |
2054 target_(Function::Handle(zone)), | 2029 target_(Function::Handle(zone)), |
2055 target_code_(Code::Handle(zone)) { | 2030 target_code_(Code::Handle(zone)) {} |
2056 } | |
2057 | 2031 |
2058 void Visit(const Function& function) { | 2032 void Visit(const Function& function) { |
2059 if (!function.HasCode()) { | 2033 if (!function.HasCode()) { |
2060 return; | 2034 return; |
2061 } | 2035 } |
2062 code_ = function.CurrentCode(); | 2036 code_ = function.CurrentCode(); |
2063 table_ = code_.static_calls_target_table(); | 2037 table_ = code_.static_calls_target_table(); |
2064 | 2038 |
2065 for (intptr_t i = 0; | 2039 for (intptr_t i = 0; i < table_.Length(); |
2066 i < table_.Length(); | |
2067 i += Code::kSCallTableEntryLength) { | 2040 i += Code::kSCallTableEntryLength) { |
2068 pc_offset_ ^= table_.At(i + Code::kSCallTableOffsetEntry); | 2041 pc_offset_ ^= table_.At(i + Code::kSCallTableOffsetEntry); |
2069 target_ ^= table_.At(i + Code::kSCallTableFunctionEntry); | 2042 target_ ^= table_.At(i + Code::kSCallTableFunctionEntry); |
2070 if (target_.IsNull()) { | 2043 if (target_.IsNull()) { |
2071 target_code_ ^= table_.At(i + Code::kSCallTableCodeEntry); | 2044 target_code_ ^= table_.At(i + Code::kSCallTableCodeEntry); |
2072 ASSERT(!target_code_.IsNull()); | 2045 ASSERT(!target_code_.IsNull()); |
2073 ASSERT(!target_code_.IsFunctionCode()); | 2046 ASSERT(!target_code_.IsFunctionCode()); |
2074 // Allocation stub or AllocateContext or AllocateArray or ... | 2047 // Allocation stub or AllocateContext or AllocateArray or ... |
2075 } else { | 2048 } else { |
2076 // Static calls initially call the CallStaticFunction stub because | 2049 // Static calls initially call the CallStaticFunction stub because |
(...skipping 30 matching lines...) Expand all Loading... |
2107 #if !defined(TARGET_ARCH_DBC) | 2080 #if !defined(TARGET_ARCH_DBC) |
2108 // Now that all functions have been compiled, we can switch to an instance | 2081 // Now that all functions have been compiled, we can switch to an instance |
2109 // call sequence that loads the Code object and entry point directly from | 2082 // call sequence that loads the Code object and entry point directly from |
2110 // the ic data array instead indirectly through a Function in the ic data | 2083 // the ic data array instead indirectly through a Function in the ic data |
2111 // array. Iterate all the object pools and rewrite the ic data from | 2084 // array. Iterate all the object pools and rewrite the ic data from |
2112 // (cid, target function, count) to (cid, target code, entry point), and | 2085 // (cid, target function, count) to (cid, target code, entry point), and |
2113 // replace the ICCallThroughFunction stub with ICCallThroughCode. | 2086 // replace the ICCallThroughFunction stub with ICCallThroughCode. |
2114 | 2087 |
2115 class SwitchICCallsVisitor : public FunctionVisitor { | 2088 class SwitchICCallsVisitor : public FunctionVisitor { |
2116 public: | 2089 public: |
2117 explicit SwitchICCallsVisitor(Zone* zone) : | 2090 explicit SwitchICCallsVisitor(Zone* zone) |
2118 zone_(zone), | 2091 : zone_(zone), |
2119 code_(Code::Handle(zone)), | 2092 code_(Code::Handle(zone)), |
2120 pool_(ObjectPool::Handle(zone)), | 2093 pool_(ObjectPool::Handle(zone)), |
2121 entry_(Object::Handle(zone)), | 2094 entry_(Object::Handle(zone)), |
2122 ic_(ICData::Handle(zone)), | 2095 ic_(ICData::Handle(zone)), |
2123 target_name_(String::Handle(zone)), | 2096 target_name_(String::Handle(zone)), |
2124 args_descriptor_(Array::Handle(zone)), | 2097 args_descriptor_(Array::Handle(zone)), |
2125 unlinked_(UnlinkedCall::Handle(zone)), | 2098 unlinked_(UnlinkedCall::Handle(zone)), |
2126 target_code_(Code::Handle(zone)), | 2099 target_code_(Code::Handle(zone)), |
2127 canonical_unlinked_calls_() { | 2100 canonical_unlinked_calls_() {} |
2128 } | |
2129 | 2101 |
2130 void Visit(const Function& function) { | 2102 void Visit(const Function& function) { |
2131 if (!function.HasCode()) { | 2103 if (!function.HasCode()) { |
2132 return; | 2104 return; |
2133 } | 2105 } |
2134 | 2106 |
2135 code_ = function.CurrentCode(); | 2107 code_ = function.CurrentCode(); |
2136 pool_ = code_.object_pool(); | 2108 pool_ = code_.object_pool(); |
2137 for (intptr_t i = 0; i < pool_.Length(); i++) { | 2109 for (intptr_t i = 0; i < pool_.Length(); i++) { |
2138 if (pool_.InfoAt(i) != ObjectPool::kTaggedObject) continue; | 2110 if (pool_.InfoAt(i) != ObjectPool::kTaggedObject) continue; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2184 }; | 2156 }; |
2185 | 2157 |
2186 ASSERT(!I->compilation_allowed()); | 2158 ASSERT(!I->compilation_allowed()); |
2187 SwitchICCallsVisitor visitor(Z); | 2159 SwitchICCallsVisitor visitor(Z); |
2188 VisitFunctions(&visitor); | 2160 VisitFunctions(&visitor); |
2189 #endif | 2161 #endif |
2190 } | 2162 } |
2191 | 2163 |
2192 | 2164 |
2193 void Precompiler::ShareMegamorphicBuckets() { | 2165 void Precompiler::ShareMegamorphicBuckets() { |
2194 const GrowableObjectArray& table = GrowableObjectArray::Handle(Z, | 2166 const GrowableObjectArray& table = GrowableObjectArray::Handle( |
2195 I->object_store()->megamorphic_cache_table()); | 2167 Z, I->object_store()->megamorphic_cache_table()); |
2196 if (table.IsNull()) return; | 2168 if (table.IsNull()) return; |
2197 MegamorphicCache& cache = MegamorphicCache::Handle(Z); | 2169 MegamorphicCache& cache = MegamorphicCache::Handle(Z); |
2198 | 2170 |
2199 const intptr_t capacity = 1; | 2171 const intptr_t capacity = 1; |
2200 const Array& buckets = Array::Handle(Z, | 2172 const Array& buckets = Array::Handle( |
2201 Array::New(MegamorphicCache::kEntryLength * capacity, Heap::kOld)); | 2173 Z, Array::New(MegamorphicCache::kEntryLength * capacity, Heap::kOld)); |
2202 const Function& handler = | 2174 const Function& handler = |
2203 Function::Handle(Z, MegamorphicCacheTable::miss_handler(I)); | 2175 Function::Handle(Z, MegamorphicCacheTable::miss_handler(I)); |
2204 MegamorphicCache::SetEntry(buckets, 0, | 2176 MegamorphicCache::SetEntry(buckets, 0, MegamorphicCache::smi_illegal_cid(), |
2205 MegamorphicCache::smi_illegal_cid(), handler); | 2177 handler); |
2206 | 2178 |
2207 for (intptr_t i = 0; i < table.Length(); i++) { | 2179 for (intptr_t i = 0; i < table.Length(); i++) { |
2208 cache ^= table.At(i); | 2180 cache ^= table.At(i); |
2209 cache.set_buckets(buckets); | 2181 cache.set_buckets(buckets); |
2210 cache.set_mask(capacity - 1); | 2182 cache.set_mask(capacity - 1); |
2211 cache.set_filled_entry_count(0); | 2183 cache.set_filled_entry_count(0); |
2212 } | 2184 } |
2213 } | 2185 } |
2214 | 2186 |
2215 | 2187 |
2216 void Precompiler::DedupStackmaps() { | 2188 void Precompiler::DedupStackmaps() { |
2217 class DedupStackmapsVisitor : public FunctionVisitor { | 2189 class DedupStackmapsVisitor : public FunctionVisitor { |
2218 public: | 2190 public: |
2219 explicit DedupStackmapsVisitor(Zone* zone) : | 2191 explicit DedupStackmapsVisitor(Zone* zone) |
2220 zone_(zone), | 2192 : zone_(zone), |
2221 canonical_stackmaps_(), | 2193 canonical_stackmaps_(), |
2222 code_(Code::Handle(zone)), | 2194 code_(Code::Handle(zone)), |
2223 stackmaps_(Array::Handle(zone)), | 2195 stackmaps_(Array::Handle(zone)), |
2224 stackmap_(Stackmap::Handle(zone)) { | 2196 stackmap_(Stackmap::Handle(zone)) {} |
2225 } | |
2226 | 2197 |
2227 void Visit(const Function& function) { | 2198 void Visit(const Function& function) { |
2228 if (!function.HasCode()) { | 2199 if (!function.HasCode()) { |
2229 return; | 2200 return; |
2230 } | 2201 } |
2231 code_ = function.CurrentCode(); | 2202 code_ = function.CurrentCode(); |
2232 stackmaps_ = code_.stackmaps(); | 2203 stackmaps_ = code_.stackmaps(); |
2233 if (stackmaps_.IsNull()) return; | 2204 if (stackmaps_.IsNull()) return; |
2234 for (intptr_t i = 0; i < stackmaps_.Length(); i++) { | 2205 for (intptr_t i = 0; i < stackmaps_.Length(); i++) { |
2235 stackmap_ ^= stackmaps_.At(i); | 2206 stackmap_ ^= stackmaps_.At(i); |
(...skipping 23 matching lines...) Expand all Loading... |
2259 }; | 2230 }; |
2260 | 2231 |
2261 DedupStackmapsVisitor visitor(Z); | 2232 DedupStackmapsVisitor visitor(Z); |
2262 VisitFunctions(&visitor); | 2233 VisitFunctions(&visitor); |
2263 } | 2234 } |
2264 | 2235 |
2265 | 2236 |
2266 void Precompiler::DedupLists() { | 2237 void Precompiler::DedupLists() { |
2267 class DedupListsVisitor : public FunctionVisitor { | 2238 class DedupListsVisitor : public FunctionVisitor { |
2268 public: | 2239 public: |
2269 explicit DedupListsVisitor(Zone* zone) : | 2240 explicit DedupListsVisitor(Zone* zone) |
2270 zone_(zone), | 2241 : zone_(zone), |
2271 canonical_lists_(), | 2242 canonical_lists_(), |
2272 code_(Code::Handle(zone)), | 2243 code_(Code::Handle(zone)), |
2273 list_(Array::Handle(zone)) { | 2244 list_(Array::Handle(zone)) {} |
2274 } | |
2275 | 2245 |
2276 void Visit(const Function& function) { | 2246 void Visit(const Function& function) { |
2277 code_ = function.CurrentCode(); | 2247 code_ = function.CurrentCode(); |
2278 if (!code_.IsNull()) { | 2248 if (!code_.IsNull()) { |
2279 list_ = code_.stackmaps(); | 2249 list_ = code_.stackmaps(); |
2280 if (!list_.IsNull()) { | 2250 if (!list_.IsNull()) { |
2281 list_ = DedupList(list_); | 2251 list_ = DedupList(list_); |
2282 code_.set_stackmaps(list_); | 2252 code_.set_stackmaps(list_); |
2283 } | 2253 } |
2284 } | 2254 } |
2285 | 2255 |
2286 list_ = function.parameter_types(); | 2256 list_ = function.parameter_types(); |
2287 if (!list_.IsNull()) { | 2257 if (!list_.IsNull()) { |
2288 if (!function.IsSignatureFunction() && | 2258 if (!function.IsSignatureFunction() && !function.IsClosureFunction() && |
2289 !function.IsClosureFunction() && | 2259 (function.name() != Symbols::Call().raw()) && !list_.InVMHeap()) { |
2290 (function.name() != Symbols::Call().raw()) && | |
2291 !list_.InVMHeap()) { | |
2292 // Parameter types not needed for function type tests. | 2260 // Parameter types not needed for function type tests. |
2293 for (intptr_t i = 0; i < list_.Length(); i++) { | 2261 for (intptr_t i = 0; i < list_.Length(); i++) { |
2294 list_.SetAt(i, Object::dynamic_type()); | 2262 list_.SetAt(i, Object::dynamic_type()); |
2295 } | 2263 } |
2296 } | 2264 } |
2297 list_ = DedupList(list_); | 2265 list_ = DedupList(list_); |
2298 function.set_parameter_types(list_); | 2266 function.set_parameter_types(list_); |
2299 } | 2267 } |
2300 | 2268 |
2301 list_ = function.parameter_names(); | 2269 list_ = function.parameter_names(); |
2302 if (!list_.IsNull()) { | 2270 if (!list_.IsNull()) { |
2303 if (!function.HasOptionalNamedParameters() && | 2271 if (!function.HasOptionalNamedParameters() && !list_.InVMHeap()) { |
2304 !list_.InVMHeap()) { | |
2305 // Parameter names not needed for resolution. | 2272 // Parameter names not needed for resolution. |
2306 for (intptr_t i = 0; i < list_.Length(); i++) { | 2273 for (intptr_t i = 0; i < list_.Length(); i++) { |
2307 list_.SetAt(i, Symbols::OptimizedOut()); | 2274 list_.SetAt(i, Symbols::OptimizedOut()); |
2308 } | 2275 } |
2309 } | 2276 } |
2310 list_ = DedupList(list_); | 2277 list_ = DedupList(list_); |
2311 function.set_parameter_names(list_); | 2278 function.set_parameter_names(list_); |
2312 } | 2279 } |
2313 } | 2280 } |
2314 | 2281 |
(...skipping 15 matching lines...) Expand all Loading... |
2330 }; | 2297 }; |
2331 | 2298 |
2332 DedupListsVisitor visitor(Z); | 2299 DedupListsVisitor visitor(Z); |
2333 VisitFunctions(&visitor); | 2300 VisitFunctions(&visitor); |
2334 } | 2301 } |
2335 | 2302 |
2336 | 2303 |
2337 void Precompiler::DedupInstructions() { | 2304 void Precompiler::DedupInstructions() { |
2338 class DedupInstructionsVisitor : public FunctionVisitor { | 2305 class DedupInstructionsVisitor : public FunctionVisitor { |
2339 public: | 2306 public: |
2340 explicit DedupInstructionsVisitor(Zone* zone) : | 2307 explicit DedupInstructionsVisitor(Zone* zone) |
2341 zone_(zone), | 2308 : zone_(zone), |
2342 canonical_instructions_set_(), | 2309 canonical_instructions_set_(), |
2343 code_(Code::Handle(zone)), | 2310 code_(Code::Handle(zone)), |
2344 instructions_(Instructions::Handle(zone)) { | 2311 instructions_(Instructions::Handle(zone)) {} |
2345 } | |
2346 | 2312 |
2347 void Visit(const Function& function) { | 2313 void Visit(const Function& function) { |
2348 if (!function.HasCode()) { | 2314 if (!function.HasCode()) { |
2349 ASSERT(function.HasImplicitClosureFunction()); | 2315 ASSERT(function.HasImplicitClosureFunction()); |
2350 return; | 2316 return; |
2351 } | 2317 } |
2352 code_ = function.CurrentCode(); | 2318 code_ = function.CurrentCode(); |
2353 instructions_ = code_.instructions(); | 2319 instructions_ = code_.instructions(); |
2354 instructions_ = DedupOneInstructions(instructions_); | 2320 instructions_ = DedupOneInstructions(instructions_); |
2355 code_.SetActiveInstructions(instructions_); | 2321 code_.SetActiveInstructions(instructions_); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2456 | 2422 |
2457 | 2423 |
2458 void Precompiler::FinalizeAllClasses() { | 2424 void Precompiler::FinalizeAllClasses() { |
2459 Library& lib = Library::Handle(Z); | 2425 Library& lib = Library::Handle(Z); |
2460 Class& cls = Class::Handle(Z); | 2426 Class& cls = Class::Handle(Z); |
2461 | 2427 |
2462 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 2428 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
2463 lib ^= libraries_.At(i); | 2429 lib ^= libraries_.At(i); |
2464 if (!lib.Loaded()) { | 2430 if (!lib.Loaded()) { |
2465 String& uri = String::Handle(Z, lib.url()); | 2431 String& uri = String::Handle(Z, lib.url()); |
2466 String& msg = String::Handle(Z, String::NewFormatted( | 2432 String& msg = String::Handle( |
2467 "Library '%s' is not loaded. " | 2433 Z, |
2468 "Did you forget to call Dart_FinalizeLoading?", uri.ToCString())); | 2434 String::NewFormatted("Library '%s' is not loaded. " |
| 2435 "Did you forget to call Dart_FinalizeLoading?", |
| 2436 uri.ToCString())); |
2469 Jump(Error::Handle(Z, ApiError::New(msg))); | 2437 Jump(Error::Handle(Z, ApiError::New(msg))); |
2470 } | 2438 } |
2471 | 2439 |
2472 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); | 2440 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
2473 while (it.HasNext()) { | 2441 while (it.HasNext()) { |
2474 cls = it.GetNextClass(); | 2442 cls = it.GetNextClass(); |
2475 if (cls.IsDynamicClass()) { | 2443 if (cls.IsDynamicClass()) { |
2476 continue; // class 'dynamic' is in the read-only VM isolate. | 2444 continue; // class 'dynamic' is in the read-only VM isolate. |
2477 } | 2445 } |
2478 error_ = cls.EnsureIsFinalized(T); | 2446 error_ = cls.EnsureIsFinalized(T); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2516 } | 2484 } |
2517 | 2485 |
2518 while (dfs_stack.length() > 0) { | 2486 while (dfs_stack.length() > 0) { |
2519 intptr_t cid = dfs_stack.RemoveLast(); | 2487 intptr_t cid = dfs_stack.RemoveLast(); |
2520 ASSERT(table->HasValidClassAt(cid)); | 2488 ASSERT(table->HasValidClassAt(cid)); |
2521 cls = table->At(cid); | 2489 cls = table->At(cid); |
2522 ASSERT(!cls.IsNull()); | 2490 ASSERT(!cls.IsNull()); |
2523 if (old_to_new_cid[cid] == -1) { | 2491 if (old_to_new_cid[cid] == -1) { |
2524 old_to_new_cid[cid] = next_new_cid++; | 2492 old_to_new_cid[cid] = next_new_cid++; |
2525 if (FLAG_trace_precompiler) { | 2493 if (FLAG_trace_precompiler) { |
2526 THR_Print("%" Pd ": %s, was %" Pd "\n", | 2494 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid], |
2527 old_to_new_cid[cid], cls.ToCString(), cid); | 2495 cls.ToCString(), cid); |
2528 } | 2496 } |
2529 } | 2497 } |
2530 subclasses = cls.direct_subclasses(); | 2498 subclasses = cls.direct_subclasses(); |
2531 if (!subclasses.IsNull()) { | 2499 if (!subclasses.IsNull()) { |
2532 for (intptr_t i = 0; i < subclasses.Length(); i++) { | 2500 for (intptr_t i = 0; i < subclasses.Length(); i++) { |
2533 cls ^= subclasses.At(i); | 2501 cls ^= subclasses.At(i); |
2534 ASSERT(!cls.IsNull()); | 2502 ASSERT(!cls.IsNull()); |
2535 dfs_stack.Add(cls.id()); | 2503 dfs_stack.Add(cls.id()); |
2536 } | 2504 } |
2537 } | 2505 } |
2538 } | 2506 } |
2539 | 2507 |
2540 // Top-level classes, typedefs, patch classes, etc. | 2508 // Top-level classes, typedefs, patch classes, etc. |
2541 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { | 2509 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { |
2542 if (old_to_new_cid[cid] == -1) { | 2510 if (old_to_new_cid[cid] == -1) { |
2543 old_to_new_cid[cid] = next_new_cid++; | 2511 old_to_new_cid[cid] = next_new_cid++; |
2544 if (FLAG_trace_precompiler && table->HasValidClassAt(cid)) { | 2512 if (FLAG_trace_precompiler && table->HasValidClassAt(cid)) { |
2545 cls = table->At(cid); | 2513 cls = table->At(cid); |
2546 THR_Print("%" Pd ": %s, was %" Pd "\n", | 2514 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid], |
2547 old_to_new_cid[cid], cls.ToCString(), cid); | 2515 cls.ToCString(), cid); |
2548 } | 2516 } |
2549 } | 2517 } |
2550 } | 2518 } |
2551 ASSERT(next_new_cid == num_cids); | 2519 ASSERT(next_new_cid == num_cids); |
2552 | 2520 |
2553 RemapClassIds(old_to_new_cid); | 2521 RemapClassIds(old_to_new_cid); |
2554 delete[] old_to_new_cid; | 2522 delete[] old_to_new_cid; |
2555 } | 2523 } |
2556 | 2524 |
2557 | 2525 |
2558 class CidRewriteVisitor : public ObjectVisitor { | 2526 class CidRewriteVisitor : public ObjectVisitor { |
2559 public: | 2527 public: |
2560 explicit CidRewriteVisitor(intptr_t* old_to_new_cids) | 2528 explicit CidRewriteVisitor(intptr_t* old_to_new_cids) |
2561 : old_to_new_cids_(old_to_new_cids) { } | 2529 : old_to_new_cids_(old_to_new_cids) {} |
2562 | 2530 |
2563 intptr_t Map(intptr_t cid) { | 2531 intptr_t Map(intptr_t cid) { |
2564 ASSERT(cid != -1); | 2532 ASSERT(cid != -1); |
2565 return old_to_new_cids_[cid]; | 2533 return old_to_new_cids_[cid]; |
2566 } | 2534 } |
2567 | 2535 |
2568 void VisitObject(RawObject* obj) { | 2536 void VisitObject(RawObject* obj) { |
2569 if (obj->IsClass()) { | 2537 if (obj->IsClass()) { |
2570 RawClass* cls = Class::RawCast(obj); | 2538 RawClass* cls = Class::RawCast(obj); |
2571 cls->ptr()->id_ = Map(cls->ptr()->id_); | 2539 cls->ptr()->id_ = Map(cls->ptr()->id_); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2663 | 2631 |
2664 CSTAT_TIMER_SCOPE(thread(), codefinalizer_timer); | 2632 CSTAT_TIMER_SCOPE(thread(), codefinalizer_timer); |
2665 // CreateDeoptInfo uses the object pool and needs to be done before | 2633 // CreateDeoptInfo uses the object pool and needs to be done before |
2666 // FinalizeCode. | 2634 // FinalizeCode. |
2667 const Array& deopt_info_array = | 2635 const Array& deopt_info_array = |
2668 Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler)); | 2636 Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler)); |
2669 INC_STAT(thread(), total_code_size, | 2637 INC_STAT(thread(), total_code_size, |
2670 deopt_info_array.Length() * sizeof(uword)); | 2638 deopt_info_array.Length() * sizeof(uword)); |
2671 // Allocates instruction object. Since this occurs only at safepoint, | 2639 // Allocates instruction object. Since this occurs only at safepoint, |
2672 // there can be no concurrent access to the instruction page. | 2640 // there can be no concurrent access to the instruction page. |
2673 const Code& code = Code::Handle( | 2641 const Code& code = |
2674 Code::FinalizeCode(function, assembler, optimized())); | 2642 Code::Handle(Code::FinalizeCode(function, assembler, optimized())); |
2675 code.set_is_optimized(optimized()); | 2643 code.set_is_optimized(optimized()); |
2676 code.set_owner(function); | 2644 code.set_owner(function); |
2677 if (!function.IsOptimizable()) { | 2645 if (!function.IsOptimizable()) { |
2678 // A function with huge unoptimized code can become non-optimizable | 2646 // A function with huge unoptimized code can become non-optimizable |
2679 // after generating unoptimized code. | 2647 // after generating unoptimized code. |
2680 function.set_usage_counter(INT_MIN); | 2648 function.set_usage_counter(INT_MIN); |
2681 } | 2649 } |
2682 | 2650 |
2683 const Array& intervals = graph_compiler->inlined_code_intervals(); | 2651 const Array& intervals = graph_compiler->inlined_code_intervals(); |
2684 INC_STAT(thread(), total_code_size, | 2652 INC_STAT(thread(), total_code_size, intervals.Length() * sizeof(uword)); |
2685 intervals.Length() * sizeof(uword)); | |
2686 code.SetInlinedIntervals(intervals); | 2653 code.SetInlinedIntervals(intervals); |
2687 | 2654 |
2688 const Array& inlined_id_array = | 2655 const Array& inlined_id_array = |
2689 Array::Handle(zone, graph_compiler->InliningIdToFunction()); | 2656 Array::Handle(zone, graph_compiler->InliningIdToFunction()); |
2690 INC_STAT(thread(), total_code_size, | 2657 INC_STAT(thread(), total_code_size, |
2691 inlined_id_array.Length() * sizeof(uword)); | 2658 inlined_id_array.Length() * sizeof(uword)); |
2692 code.SetInlinedIdToFunction(inlined_id_array); | 2659 code.SetInlinedIdToFunction(inlined_id_array); |
2693 | 2660 |
2694 const Array& caller_inlining_id_map_array = | 2661 const Array& caller_inlining_id_map_array = |
2695 Array::Handle(zone, graph_compiler->CallerInliningIdMap()); | 2662 Array::Handle(zone, graph_compiler->CallerInliningIdMap()); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2760 | 2727 |
2761 // Class hierarchy analysis is registered with the thread in the | 2728 // Class hierarchy analysis is registered with the thread in the |
2762 // constructor and unregisters itself upon destruction. | 2729 // constructor and unregisters itself upon destruction. |
2763 CHA cha(thread()); | 2730 CHA cha(thread()); |
2764 | 2731 |
2765 // TimerScope needs an isolate to be properly terminated in case of a | 2732 // TimerScope needs an isolate to be properly terminated in case of a |
2766 // LongJump. | 2733 // LongJump. |
2767 { | 2734 { |
2768 CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer); | 2735 CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer); |
2769 ZoneGrowableArray<const ICData*>* ic_data_array = | 2736 ZoneGrowableArray<const ICData*>* ic_data_array = |
2770 new(zone) ZoneGrowableArray<const ICData*>(); | 2737 new (zone) ZoneGrowableArray<const ICData*>(); |
2771 #ifndef PRODUCT | 2738 #ifndef PRODUCT |
2772 TimelineDurationScope tds(thread(), | 2739 TimelineDurationScope tds(thread(), compiler_timeline, |
2773 compiler_timeline, | |
2774 "BuildFlowGraph"); | 2740 "BuildFlowGraph"); |
2775 #endif // !PRODUCT | 2741 #endif // !PRODUCT |
2776 flow_graph = pipeline->BuildFlowGraph(zone, | 2742 flow_graph = pipeline->BuildFlowGraph( |
2777 parsed_function(), | 2743 zone, parsed_function(), *ic_data_array, Compiler::kNoOSRDeoptId); |
2778 *ic_data_array, | |
2779 Compiler::kNoOSRDeoptId); | |
2780 } | 2744 } |
2781 | 2745 |
2782 const bool print_flow_graph = | 2746 const bool print_flow_graph = |
2783 (FLAG_print_flow_graph || | 2747 (FLAG_print_flow_graph || |
2784 (optimized() && FLAG_print_flow_graph_optimized)) && | 2748 (optimized() && FLAG_print_flow_graph_optimized)) && |
2785 FlowGraphPrinter::ShouldPrint(function); | 2749 FlowGraphPrinter::ShouldPrint(function); |
2786 | 2750 |
2787 if (print_flow_graph) { | 2751 if (print_flow_graph) { |
2788 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | 2752 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
2789 } | 2753 } |
2790 | 2754 |
2791 if (optimized()) { | 2755 if (optimized()) { |
2792 #ifndef PRODUCT | 2756 #ifndef PRODUCT |
2793 TimelineDurationScope tds(thread(), | 2757 TimelineDurationScope tds(thread(), compiler_timeline, "ComputeSSA"); |
2794 compiler_timeline, | |
2795 "ComputeSSA"); | |
2796 #endif // !PRODUCT | 2758 #endif // !PRODUCT |
2797 CSTAT_TIMER_SCOPE(thread(), ssa_timer); | 2759 CSTAT_TIMER_SCOPE(thread(), ssa_timer); |
2798 // Transform to SSA (virtual register 0 and no inlining arguments). | 2760 // Transform to SSA (virtual register 0 and no inlining arguments). |
2799 flow_graph->ComputeSSA(0, NULL); | 2761 flow_graph->ComputeSSA(0, NULL); |
2800 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2762 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2801 if (print_flow_graph) { | 2763 if (print_flow_graph) { |
2802 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); | 2764 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); |
2803 } | 2765 } |
2804 } | 2766 } |
2805 | 2767 |
2806 // Maps inline_id_to_function[inline_id] -> function. Top scope | 2768 // Maps inline_id_to_function[inline_id] -> function. Top scope |
2807 // function has inline_id 0. The map is populated by the inliner. | 2769 // function has inline_id 0. The map is populated by the inliner. |
2808 GrowableArray<const Function*> inline_id_to_function; | 2770 GrowableArray<const Function*> inline_id_to_function; |
2809 // Token position where inlining occured. | 2771 // Token position where inlining occured. |
2810 GrowableArray<TokenPosition> inline_id_to_token_pos; | 2772 GrowableArray<TokenPosition> inline_id_to_token_pos; |
2811 // For a given inlining-id(index) specifies the caller's inlining-id. | 2773 // For a given inlining-id(index) specifies the caller's inlining-id. |
2812 GrowableArray<intptr_t> caller_inline_id; | 2774 GrowableArray<intptr_t> caller_inline_id; |
2813 // Collect all instance fields that are loaded in the graph and | 2775 // Collect all instance fields that are loaded in the graph and |
2814 // have non-generic type feedback attached to them that can | 2776 // have non-generic type feedback attached to them that can |
2815 // potentially affect optimizations. | 2777 // potentially affect optimizations. |
2816 if (optimized()) { | 2778 if (optimized()) { |
2817 #ifndef PRODUCT | 2779 #ifndef PRODUCT |
2818 TimelineDurationScope tds(thread(), | 2780 TimelineDurationScope tds(thread(), compiler_timeline, |
2819 compiler_timeline, | |
2820 "OptimizationPasses"); | 2781 "OptimizationPasses"); |
2821 #endif // !PRODUCT | 2782 #endif // !PRODUCT |
2822 inline_id_to_function.Add(&function); | 2783 inline_id_to_function.Add(&function); |
2823 // We do not add the token position now because we don't know the | 2784 // We do not add the token position now because we don't know the |
2824 // position of the inlined call until later. A side effect of this | 2785 // position of the inlined call until later. A side effect of this |
2825 // is that the length of |inline_id_to_function| is always larger | 2786 // is that the length of |inline_id_to_function| is always larger |
2826 // than the length of |inline_id_to_token_pos| by one. | 2787 // than the length of |inline_id_to_token_pos| by one. |
2827 // Top scope function has no caller (-1). We do this because we expect | 2788 // Top scope function has no caller (-1). We do this because we expect |
2828 // all token positions to be at an inlined call. | 2789 // all token positions to be at an inlined call. |
2829 // Top scope function has no caller (-1). | 2790 // Top scope function has no caller (-1). |
2830 caller_inline_id.Add(-1); | 2791 caller_inline_id.Add(-1); |
2831 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); | 2792 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); |
2832 | 2793 |
2833 AotOptimizer optimizer(precompiler_, | 2794 AotOptimizer optimizer(precompiler_, flow_graph, |
2834 flow_graph, | 2795 use_speculative_inlining, &inlining_black_list); |
2835 use_speculative_inlining, | |
2836 &inlining_black_list); | |
2837 optimizer.PopulateWithICData(); | 2796 optimizer.PopulateWithICData(); |
2838 | 2797 |
2839 optimizer.ApplyClassIds(); | 2798 optimizer.ApplyClassIds(); |
2840 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2799 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2841 | 2800 |
2842 FlowGraphTypePropagator::Propagate(flow_graph); | 2801 FlowGraphTypePropagator::Propagate(flow_graph); |
2843 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2802 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2844 | 2803 |
2845 optimizer.ApplyICData(); | 2804 optimizer.ApplyICData(); |
2846 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2805 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2847 | 2806 |
2848 // Optimize (a << b) & c patterns, merge operations. | 2807 // Optimize (a << b) & c patterns, merge operations. |
2849 // Run early in order to have more opportunity to optimize left shifts. | 2808 // Run early in order to have more opportunity to optimize left shifts. |
2850 flow_graph->TryOptimizePatterns(); | 2809 flow_graph->TryOptimizePatterns(); |
2851 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2810 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2852 | 2811 |
2853 FlowGraphInliner::SetInliningId(flow_graph, 0); | 2812 FlowGraphInliner::SetInliningId(flow_graph, 0); |
2854 | 2813 |
2855 // Inlining (mutates the flow graph) | 2814 // Inlining (mutates the flow graph) |
2856 if (FLAG_use_inlining) { | 2815 if (FLAG_use_inlining) { |
2857 #ifndef PRODUCT | 2816 #ifndef PRODUCT |
2858 TimelineDurationScope tds2(thread(), | 2817 TimelineDurationScope tds2(thread(), compiler_timeline, "Inlining"); |
2859 compiler_timeline, | |
2860 "Inlining"); | |
2861 #endif // !PRODUCT | 2818 #endif // !PRODUCT |
2862 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); | 2819 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); |
2863 // Propagate types to create more inlining opportunities. | 2820 // Propagate types to create more inlining opportunities. |
2864 FlowGraphTypePropagator::Propagate(flow_graph); | 2821 FlowGraphTypePropagator::Propagate(flow_graph); |
2865 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2822 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2866 | 2823 |
2867 // Use propagated class-ids to create more inlining opportunities. | 2824 // Use propagated class-ids to create more inlining opportunities. |
2868 optimizer.ApplyClassIds(); | 2825 optimizer.ApplyClassIds(); |
2869 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2826 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2870 | 2827 |
2871 FlowGraphInliner inliner(flow_graph, | 2828 FlowGraphInliner inliner(flow_graph, &inline_id_to_function, |
2872 &inline_id_to_function, | 2829 &inline_id_to_token_pos, &caller_inline_id, |
2873 &inline_id_to_token_pos, | |
2874 &caller_inline_id, | |
2875 use_speculative_inlining, | 2830 use_speculative_inlining, |
2876 &inlining_black_list, | 2831 &inlining_black_list, precompiler_); |
2877 precompiler_); | |
2878 inliner.Inline(); | 2832 inliner.Inline(); |
2879 // Use lists are maintained and validated by the inliner. | 2833 // Use lists are maintained and validated by the inliner. |
2880 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2834 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2881 } | 2835 } |
2882 | 2836 |
2883 // Propagate types and eliminate more type tests. | 2837 // Propagate types and eliminate more type tests. |
2884 FlowGraphTypePropagator::Propagate(flow_graph); | 2838 FlowGraphTypePropagator::Propagate(flow_graph); |
2885 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2839 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2886 | 2840 |
2887 { | 2841 { |
2888 #ifndef PRODUCT | 2842 #ifndef PRODUCT |
2889 TimelineDurationScope tds2(thread(), | 2843 TimelineDurationScope tds2(thread(), compiler_timeline, |
2890 compiler_timeline, | |
2891 "ApplyClassIds"); | 2844 "ApplyClassIds"); |
2892 #endif // !PRODUCT | 2845 #endif // !PRODUCT |
2893 // Use propagated class-ids to optimize further. | 2846 // Use propagated class-ids to optimize further. |
2894 optimizer.ApplyClassIds(); | 2847 optimizer.ApplyClassIds(); |
2895 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2848 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2896 } | 2849 } |
2897 | 2850 |
2898 // Propagate types for potentially newly added instructions by | 2851 // Propagate types for potentially newly added instructions by |
2899 // ApplyClassIds(). Must occur before canonicalization. | 2852 // ApplyClassIds(). Must occur before canonicalization. |
2900 FlowGraphTypePropagator::Propagate(flow_graph); | 2853 FlowGraphTypePropagator::Propagate(flow_graph); |
2901 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2854 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2902 | 2855 |
2903 // Do optimizations that depend on the propagated type information. | 2856 // Do optimizations that depend on the propagated type information. |
2904 if (flow_graph->Canonicalize()) { | 2857 if (flow_graph->Canonicalize()) { |
2905 // Invoke Canonicalize twice in order to fully canonicalize patterns | 2858 // Invoke Canonicalize twice in order to fully canonicalize patterns |
2906 // like "if (a & const == 0) { }". | 2859 // like "if (a & const == 0) { }". |
2907 flow_graph->Canonicalize(); | 2860 flow_graph->Canonicalize(); |
2908 } | 2861 } |
2909 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2862 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2910 | 2863 |
2911 { | 2864 { |
2912 #ifndef PRODUCT | 2865 #ifndef PRODUCT |
2913 TimelineDurationScope tds2(thread(), | 2866 TimelineDurationScope tds2(thread(), compiler_timeline, |
2914 compiler_timeline, | |
2915 "BranchSimplifier"); | 2867 "BranchSimplifier"); |
2916 #endif // !PRODUCT | 2868 #endif // !PRODUCT |
2917 BranchSimplifier::Simplify(flow_graph); | 2869 BranchSimplifier::Simplify(flow_graph); |
2918 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2870 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2919 | 2871 |
2920 IfConverter::Simplify(flow_graph); | 2872 IfConverter::Simplify(flow_graph); |
2921 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2873 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2922 } | 2874 } |
2923 | 2875 |
2924 if (FLAG_constant_propagation) { | 2876 if (FLAG_constant_propagation) { |
2925 #ifndef PRODUCT | 2877 #ifndef PRODUCT |
2926 TimelineDurationScope tds2(thread(), | 2878 TimelineDurationScope tds2(thread(), compiler_timeline, |
2927 compiler_timeline, | |
2928 "ConstantPropagation"); | 2879 "ConstantPropagation"); |
2929 #endif // !PRODUCT | 2880 #endif // !PRODUCT |
2930 ConstantPropagator::Optimize(flow_graph); | 2881 ConstantPropagator::Optimize(flow_graph); |
2931 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2882 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2932 // A canonicalization pass to remove e.g. smi checks on smi constants. | 2883 // A canonicalization pass to remove e.g. smi checks on smi constants. |
2933 flow_graph->Canonicalize(); | 2884 flow_graph->Canonicalize(); |
2934 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2885 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2935 // Canonicalization introduced more opportunities for constant | 2886 // Canonicalization introduced more opportunities for constant |
2936 // propagation. | 2887 // propagation. |
2937 ConstantPropagator::Optimize(flow_graph); | 2888 ConstantPropagator::Optimize(flow_graph); |
2938 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2889 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2939 } | 2890 } |
2940 | 2891 |
2941 // Optimistically convert loop phis that have a single non-smi input | 2892 // Optimistically convert loop phis that have a single non-smi input |
2942 // coming from the loop pre-header into smi-phis. | 2893 // coming from the loop pre-header into smi-phis. |
2943 if (FLAG_loop_invariant_code_motion) { | 2894 if (FLAG_loop_invariant_code_motion) { |
2944 LICM licm(flow_graph); | 2895 LICM licm(flow_graph); |
2945 licm.OptimisticallySpecializeSmiPhis(); | 2896 licm.OptimisticallySpecializeSmiPhis(); |
2946 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2897 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2947 } | 2898 } |
2948 | 2899 |
2949 // Propagate types and eliminate even more type tests. | 2900 // Propagate types and eliminate even more type tests. |
2950 // Recompute types after constant propagation to infer more precise | 2901 // Recompute types after constant propagation to infer more precise |
2951 // types for uses that were previously reached by now eliminated phis. | 2902 // types for uses that were previously reached by now eliminated phis. |
2952 FlowGraphTypePropagator::Propagate(flow_graph); | 2903 FlowGraphTypePropagator::Propagate(flow_graph); |
2953 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2904 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2954 | 2905 |
2955 { | 2906 { |
2956 #ifndef PRODUCT | 2907 #ifndef PRODUCT |
2957 TimelineDurationScope tds2(thread(), | 2908 TimelineDurationScope tds2(thread(), compiler_timeline, |
2958 compiler_timeline, | |
2959 "SelectRepresentations"); | 2909 "SelectRepresentations"); |
2960 #endif // !PRODUCT | 2910 #endif // !PRODUCT |
2961 // Where beneficial convert Smi operations into Int32 operations. | 2911 // Where beneficial convert Smi operations into Int32 operations. |
2962 // Only meanigful for 32bit platforms right now. | 2912 // Only meanigful for 32bit platforms right now. |
2963 flow_graph->WidenSmiToInt32(); | 2913 flow_graph->WidenSmiToInt32(); |
2964 | 2914 |
2965 // Unbox doubles. Performed after constant propagation to minimize | 2915 // Unbox doubles. Performed after constant propagation to minimize |
2966 // interference from phis merging double values and tagged | 2916 // interference from phis merging double values and tagged |
2967 // values coming from dead paths. | 2917 // values coming from dead paths. |
2968 flow_graph->SelectRepresentations(); | 2918 flow_graph->SelectRepresentations(); |
2969 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2919 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
2970 } | 2920 } |
2971 | 2921 |
2972 { | 2922 { |
2973 #ifndef PRODUCT | 2923 #ifndef PRODUCT |
2974 TimelineDurationScope tds2(thread(), | 2924 TimelineDurationScope tds2(thread(), compiler_timeline, |
2975 compiler_timeline, | |
2976 "CommonSubexpressionElinination"); | 2925 "CommonSubexpressionElinination"); |
2977 #endif // !PRODUCT | 2926 #endif // !PRODUCT |
2978 if (FLAG_common_subexpression_elimination || | 2927 if (FLAG_common_subexpression_elimination || |
2979 FLAG_loop_invariant_code_motion) { | 2928 FLAG_loop_invariant_code_motion) { |
2980 flow_graph->ComputeBlockEffects(); | 2929 flow_graph->ComputeBlockEffects(); |
2981 } | 2930 } |
2982 | 2931 |
2983 if (FLAG_common_subexpression_elimination) { | 2932 if (FLAG_common_subexpression_elimination) { |
2984 if (DominatorBasedCSE::Optimize(flow_graph)) { | 2933 if (DominatorBasedCSE::Optimize(flow_graph)) { |
2985 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2934 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
(...skipping 20 matching lines...) Expand all Loading... |
3006 } | 2955 } |
3007 | 2956 |
3008 // Optimize (a << b) & c patterns, merge operations. | 2957 // Optimize (a << b) & c patterns, merge operations. |
3009 // Run after CSE in order to have more opportunity to merge | 2958 // Run after CSE in order to have more opportunity to merge |
3010 // instructions that have same inputs. | 2959 // instructions that have same inputs. |
3011 flow_graph->TryOptimizePatterns(); | 2960 flow_graph->TryOptimizePatterns(); |
3012 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2961 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3013 | 2962 |
3014 { | 2963 { |
3015 #ifndef PRODUCT | 2964 #ifndef PRODUCT |
3016 TimelineDurationScope tds2(thread(), | 2965 TimelineDurationScope tds2(thread(), compiler_timeline, |
3017 compiler_timeline, | |
3018 "DeadStoreElimination"); | 2966 "DeadStoreElimination"); |
3019 #endif // !PRODUCT | 2967 #endif // !PRODUCT |
3020 DeadStoreElimination::Optimize(flow_graph); | 2968 DeadStoreElimination::Optimize(flow_graph); |
3021 } | 2969 } |
3022 | 2970 |
3023 if (FLAG_range_analysis) { | 2971 if (FLAG_range_analysis) { |
3024 #ifndef PRODUCT | 2972 #ifndef PRODUCT |
3025 TimelineDurationScope tds2(thread(), | 2973 TimelineDurationScope tds2(thread(), compiler_timeline, |
3026 compiler_timeline, | |
3027 "RangeAnalysis"); | 2974 "RangeAnalysis"); |
3028 #endif // !PRODUCT | 2975 #endif // !PRODUCT |
3029 // Propagate types after store-load-forwarding. Some phis may have | 2976 // Propagate types after store-load-forwarding. Some phis may have |
3030 // become smi phis that can be processed by range analysis. | 2977 // become smi phis that can be processed by range analysis. |
3031 FlowGraphTypePropagator::Propagate(flow_graph); | 2978 FlowGraphTypePropagator::Propagate(flow_graph); |
3032 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2979 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3033 | 2980 |
3034 // We have to perform range analysis after LICM because it | 2981 // We have to perform range analysis after LICM because it |
3035 // optimistically moves CheckSmi through phis into loop preheaders | 2982 // optimistically moves CheckSmi through phis into loop preheaders |
3036 // making some phis smi. | 2983 // making some phis smi. |
3037 RangeAnalysis range_analysis(flow_graph); | 2984 RangeAnalysis range_analysis(flow_graph); |
3038 range_analysis.Analyze(); | 2985 range_analysis.Analyze(); |
3039 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2986 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3040 } | 2987 } |
3041 | 2988 |
3042 if (FLAG_constant_propagation) { | 2989 if (FLAG_constant_propagation) { |
3043 #ifndef PRODUCT | 2990 #ifndef PRODUCT |
3044 TimelineDurationScope tds2(thread(), | 2991 TimelineDurationScope tds2(thread(), compiler_timeline, |
3045 compiler_timeline, | |
3046 "ConstantPropagator::OptimizeBranches"); | 2992 "ConstantPropagator::OptimizeBranches"); |
3047 #endif // !PRODUCT | 2993 #endif // !PRODUCT |
3048 // Constant propagation can use information from range analysis to | 2994 // Constant propagation can use information from range analysis to |
3049 // find unreachable branch targets and eliminate branches that have | 2995 // find unreachable branch targets and eliminate branches that have |
3050 // the same true- and false-target. | 2996 // the same true- and false-target. |
3051 ConstantPropagator::OptimizeBranches(flow_graph); | 2997 ConstantPropagator::OptimizeBranches(flow_graph); |
3052 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2998 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3053 } | 2999 } |
3054 | 3000 |
3055 // Recompute types after code movement was done to ensure correct | 3001 // Recompute types after code movement was done to ensure correct |
3056 // reaching types for hoisted values. | 3002 // reaching types for hoisted values. |
3057 FlowGraphTypePropagator::Propagate(flow_graph); | 3003 FlowGraphTypePropagator::Propagate(flow_graph); |
3058 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3004 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3059 | 3005 |
3060 { | 3006 { |
3061 #ifndef PRODUCT | 3007 #ifndef PRODUCT |
3062 TimelineDurationScope tds2(thread(), | 3008 TimelineDurationScope tds2(thread(), compiler_timeline, |
3063 compiler_timeline, | |
3064 "TryCatchAnalyzer::Optimize"); | 3009 "TryCatchAnalyzer::Optimize"); |
3065 #endif // !PRODUCT | 3010 #endif // !PRODUCT |
3066 // Optimize try-blocks. | 3011 // Optimize try-blocks. |
3067 TryCatchAnalyzer::Optimize(flow_graph); | 3012 TryCatchAnalyzer::Optimize(flow_graph); |
3068 } | 3013 } |
3069 | 3014 |
3070 // Detach environments from the instructions that can't deoptimize. | 3015 // Detach environments from the instructions that can't deoptimize. |
3071 // Do it before we attempt to perform allocation sinking to minimize | 3016 // Do it before we attempt to perform allocation sinking to minimize |
3072 // amount of materializations it has to perform. | 3017 // amount of materializations it has to perform. |
3073 flow_graph->EliminateEnvironments(); | 3018 flow_graph->EliminateEnvironments(); |
3074 | 3019 |
3075 { | 3020 { |
3076 #ifndef PRODUCT | 3021 #ifndef PRODUCT |
3077 TimelineDurationScope tds2(thread(), | 3022 TimelineDurationScope tds2(thread(), compiler_timeline, |
3078 compiler_timeline, | |
3079 "EliminateDeadPhis"); | 3023 "EliminateDeadPhis"); |
3080 #endif // !PRODUCT | 3024 #endif // !PRODUCT |
3081 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 3025 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
3082 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3026 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3083 } | 3027 } |
3084 | 3028 |
3085 if (flow_graph->Canonicalize()) { | 3029 if (flow_graph->Canonicalize()) { |
3086 flow_graph->Canonicalize(); | 3030 flow_graph->Canonicalize(); |
3087 } | 3031 } |
3088 | 3032 |
3089 // Attempt to sink allocations of temporary non-escaping objects to | 3033 // Attempt to sink allocations of temporary non-escaping objects to |
3090 // the deoptimization path. | 3034 // the deoptimization path. |
3091 AllocationSinking* sinking = NULL; | 3035 AllocationSinking* sinking = NULL; |
3092 if (FLAG_allocation_sinking && | 3036 if (FLAG_allocation_sinking && |
3093 (flow_graph->graph_entry()->SuccessorCount() == 1)) { | 3037 (flow_graph->graph_entry()->SuccessorCount() == 1)) { |
3094 #ifndef PRODUCT | 3038 #ifndef PRODUCT |
3095 TimelineDurationScope tds2(thread(), | 3039 TimelineDurationScope tds2(thread(), compiler_timeline, |
3096 compiler_timeline, | |
3097 "AllocationSinking::Optimize"); | 3040 "AllocationSinking::Optimize"); |
3098 #endif // !PRODUCT | 3041 #endif // !PRODUCT |
3099 // TODO(fschneider): Support allocation sinking with try-catch. | 3042 // TODO(fschneider): Support allocation sinking with try-catch. |
3100 sinking = new AllocationSinking(flow_graph); | 3043 sinking = new AllocationSinking(flow_graph); |
3101 sinking->Optimize(); | 3044 sinking->Optimize(); |
3102 } | 3045 } |
3103 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3046 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3104 | 3047 |
3105 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 3048 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
3106 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3049 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3107 | 3050 |
3108 FlowGraphTypePropagator::Propagate(flow_graph); | 3051 FlowGraphTypePropagator::Propagate(flow_graph); |
3109 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3052 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3110 | 3053 |
3111 { | 3054 { |
3112 #ifndef PRODUCT | 3055 #ifndef PRODUCT |
3113 TimelineDurationScope tds2(thread(), | 3056 TimelineDurationScope tds2(thread(), compiler_timeline, |
3114 compiler_timeline, | |
3115 "SelectRepresentations"); | 3057 "SelectRepresentations"); |
3116 #endif // !PRODUCT | 3058 #endif // !PRODUCT |
3117 // Ensure that all phis inserted by optimization passes have | 3059 // Ensure that all phis inserted by optimization passes have |
3118 // consistent representations. | 3060 // consistent representations. |
3119 flow_graph->SelectRepresentations(); | 3061 flow_graph->SelectRepresentations(); |
3120 } | 3062 } |
3121 | 3063 |
3122 if (flow_graph->Canonicalize()) { | 3064 if (flow_graph->Canonicalize()) { |
3123 // To fully remove redundant boxing (e.g. BoxDouble used only in | 3065 // To fully remove redundant boxing (e.g. BoxDouble used only in |
3124 // environments and UnboxDouble instructions) instruction we | 3066 // environments and UnboxDouble instructions) instruction we |
3125 // first need to replace all their uses and then fold them away. | 3067 // first need to replace all their uses and then fold them away. |
3126 // For now we just repeat Canonicalize twice to do that. | 3068 // For now we just repeat Canonicalize twice to do that. |
3127 // TODO(vegorov): implement a separate representation folding pass. | 3069 // TODO(vegorov): implement a separate representation folding pass. |
3128 flow_graph->Canonicalize(); | 3070 flow_graph->Canonicalize(); |
3129 } | 3071 } |
3130 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3072 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
3131 | 3073 |
3132 if (sinking != NULL) { | 3074 if (sinking != NULL) { |
3133 #ifndef PRODUCT | 3075 #ifndef PRODUCT |
3134 TimelineDurationScope tds2( | 3076 TimelineDurationScope tds2( |
3135 thread(), | 3077 thread(), compiler_timeline, |
3136 compiler_timeline, | |
3137 "AllocationSinking::DetachMaterializations"); | 3078 "AllocationSinking::DetachMaterializations"); |
3138 #endif // !PRODUCT | 3079 #endif // !PRODUCT |
3139 // Remove all MaterializeObject instructions inserted by allocation | 3080 // Remove all MaterializeObject instructions inserted by allocation |
3140 // sinking from the flow graph and let them float on the side | 3081 // sinking from the flow graph and let them float on the side |
3141 // referenced only from environments. Register allocator will consider | 3082 // referenced only from environments. Register allocator will consider |
3142 // them as part of a deoptimization environment. | 3083 // them as part of a deoptimization environment. |
3143 sinking->DetachMaterializations(); | 3084 sinking->DetachMaterializations(); |
3144 } | 3085 } |
3145 | 3086 |
3146 // Replace bounds check instruction with a generic one. | 3087 // Replace bounds check instruction with a generic one. |
3147 optimizer.ReplaceArrayBoundChecks(); | 3088 optimizer.ReplaceArrayBoundChecks(); |
3148 | 3089 |
3149 // Compute and store graph informations (call & instruction counts) | 3090 // Compute and store graph informations (call & instruction counts) |
3150 // to be later used by the inliner. | 3091 // to be later used by the inliner. |
3151 FlowGraphInliner::CollectGraphInfo(flow_graph, true); | 3092 FlowGraphInliner::CollectGraphInfo(flow_graph, true); |
3152 | 3093 |
3153 { | 3094 { |
3154 #ifndef PRODUCT | 3095 #ifndef PRODUCT |
3155 TimelineDurationScope tds2(thread(), | 3096 TimelineDurationScope tds2(thread(), compiler_timeline, |
3156 compiler_timeline, | |
3157 "AllocateRegisters"); | 3097 "AllocateRegisters"); |
3158 #endif // !PRODUCT | 3098 #endif // !PRODUCT |
3159 // Perform register allocation on the SSA graph. | 3099 // Perform register allocation on the SSA graph. |
3160 FlowGraphAllocator allocator(*flow_graph); | 3100 FlowGraphAllocator allocator(*flow_graph); |
3161 allocator.AllocateRegisters(); | 3101 allocator.AllocateRegisters(); |
3162 } | 3102 } |
3163 | 3103 |
3164 if (print_flow_graph) { | 3104 if (print_flow_graph) { |
3165 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); | 3105 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); |
3166 } | 3106 } |
3167 } | 3107 } |
3168 | 3108 |
3169 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); | 3109 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); |
3170 Assembler assembler(use_far_branches); | 3110 Assembler assembler(use_far_branches); |
3171 FlowGraphCompiler graph_compiler(&assembler, flow_graph, | 3111 FlowGraphCompiler graph_compiler( |
3172 *parsed_function(), optimized(), | 3112 &assembler, flow_graph, *parsed_function(), optimized(), |
3173 inline_id_to_function, | 3113 inline_id_to_function, inline_id_to_token_pos, caller_inline_id); |
3174 inline_id_to_token_pos, | |
3175 caller_inline_id); | |
3176 { | 3114 { |
3177 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); | 3115 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); |
3178 #ifndef PRODUCT | 3116 #ifndef PRODUCT |
3179 TimelineDurationScope tds(thread(), | 3117 TimelineDurationScope tds(thread(), compiler_timeline, "CompileGraph"); |
3180 compiler_timeline, | |
3181 "CompileGraph"); | |
3182 #endif // !PRODUCT | 3118 #endif // !PRODUCT |
3183 graph_compiler.CompileGraph(); | 3119 graph_compiler.CompileGraph(); |
3184 pipeline->FinalizeCompilation(flow_graph); | 3120 pipeline->FinalizeCompilation(flow_graph); |
3185 } | 3121 } |
3186 { | 3122 { |
3187 #ifndef PRODUCT | 3123 #ifndef PRODUCT |
3188 TimelineDurationScope tds(thread(), | 3124 TimelineDurationScope tds(thread(), compiler_timeline, |
3189 compiler_timeline, | |
3190 "FinalizeCompilation"); | 3125 "FinalizeCompilation"); |
3191 #endif // !PRODUCT | 3126 #endif // !PRODUCT |
3192 ASSERT(thread()->IsMutatorThread()); | 3127 ASSERT(thread()->IsMutatorThread()); |
3193 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); | 3128 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); |
3194 } | 3129 } |
3195 // Mark that this isolate now has compiled code. | 3130 // Mark that this isolate now has compiled code. |
3196 isolate()->set_has_compiled_code(true); | 3131 isolate()->set_has_compiled_code(true); |
3197 // Exit the loop and the function with the correct result value. | 3132 // Exit the loop and the function with the correct result value. |
3198 is_compiled = true; | 3133 is_compiled = true; |
3199 done = true; | 3134 done = true; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3260 // Check that we optimize, except if the function is not optimizable. | 3195 // Check that we optimize, except if the function is not optimizable. |
3261 ASSERT(FLAG_precompiled_mode); | 3196 ASSERT(FLAG_precompiled_mode); |
3262 ASSERT(!function.IsOptimizable() || optimized); | 3197 ASSERT(!function.IsOptimizable() || optimized); |
3263 ASSERT(!function.HasCode()); | 3198 ASSERT(!function.HasCode()); |
3264 LongJumpScope jump; | 3199 LongJumpScope jump; |
3265 if (setjmp(*jump.Set()) == 0) { | 3200 if (setjmp(*jump.Set()) == 0) { |
3266 Thread* const thread = Thread::Current(); | 3201 Thread* const thread = Thread::Current(); |
3267 StackZone stack_zone(thread); | 3202 StackZone stack_zone(thread); |
3268 Zone* const zone = stack_zone.GetZone(); | 3203 Zone* const zone = stack_zone.GetZone(); |
3269 const bool trace_compiler = | 3204 const bool trace_compiler = |
3270 FLAG_trace_compiler || | 3205 FLAG_trace_compiler || (FLAG_trace_optimizing_compiler && optimized); |
3271 (FLAG_trace_optimizing_compiler && optimized); | |
3272 Timer per_compile_timer(trace_compiler, "Compilation time"); | 3206 Timer per_compile_timer(trace_compiler, "Compilation time"); |
3273 per_compile_timer.Start(); | 3207 per_compile_timer.Start(); |
3274 | 3208 |
3275 ParsedFunction* parsed_function = new(zone) ParsedFunction( | 3209 ParsedFunction* parsed_function = new (zone) |
3276 thread, Function::ZoneHandle(zone, function.raw())); | 3210 ParsedFunction(thread, Function::ZoneHandle(zone, function.raw())); |
3277 if (trace_compiler) { | 3211 if (trace_compiler) { |
3278 THR_Print( | 3212 THR_Print("Precompiling %sfunction: '%s' @ token %" Pd ", size %" Pd "\n", |
3279 "Precompiling %sfunction: '%s' @ token %" Pd ", size %" Pd "\n", | 3213 (optimized ? "optimized " : ""), |
3280 (optimized ? "optimized " : ""), | 3214 function.ToFullyQualifiedCString(), function.token_pos().Pos(), |
3281 function.ToFullyQualifiedCString(), | 3215 (function.end_token_pos().Pos() - function.token_pos().Pos())); |
3282 function.token_pos().Pos(), | |
3283 (function.end_token_pos().Pos() - function.token_pos().Pos())); | |
3284 } | 3216 } |
3285 INC_STAT(thread, num_functions_compiled, 1); | 3217 INC_STAT(thread, num_functions_compiled, 1); |
3286 if (optimized) { | 3218 if (optimized) { |
3287 INC_STAT(thread, num_functions_optimized, 1); | 3219 INC_STAT(thread, num_functions_optimized, 1); |
3288 } | 3220 } |
3289 { | 3221 { |
3290 HANDLESCOPE(thread); | 3222 HANDLESCOPE(thread); |
3291 const int64_t num_tokens_before = STAT_VALUE(thread, num_tokens_consumed); | 3223 const int64_t num_tokens_before = STAT_VALUE(thread, num_tokens_consumed); |
3292 pipeline->ParseFunction(parsed_function); | 3224 pipeline->ParseFunction(parsed_function); |
3293 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); | 3225 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); |
3294 INC_STAT(thread, | 3226 INC_STAT(thread, num_func_tokens_compiled, |
3295 num_func_tokens_compiled, | |
3296 num_tokens_after - num_tokens_before); | 3227 num_tokens_after - num_tokens_before); |
3297 } | 3228 } |
3298 | 3229 |
3299 PrecompileParsedFunctionHelper helper( | 3230 PrecompileParsedFunctionHelper helper(precompiler, parsed_function, |
3300 precompiler, parsed_function, optimized); | 3231 optimized); |
3301 const bool success = helper.Compile(pipeline); | 3232 const bool success = helper.Compile(pipeline); |
3302 if (!success) { | 3233 if (!success) { |
3303 // Encountered error. | 3234 // Encountered error. |
3304 Error& error = Error::Handle(); | 3235 Error& error = Error::Handle(); |
3305 // We got an error during compilation. | 3236 // We got an error during compilation. |
3306 error = thread->sticky_error(); | 3237 error = thread->sticky_error(); |
3307 thread->clear_sticky_error(); | 3238 thread->clear_sticky_error(); |
3308 ASSERT(error.IsLanguageError() && | 3239 ASSERT(error.IsLanguageError() && |
3309 LanguageError::Cast(error).kind() != Report::kBailout); | 3240 LanguageError::Cast(error).kind() != Report::kBailout); |
3310 return error.raw(); | 3241 return error.raw(); |
3311 } | 3242 } |
3312 | 3243 |
3313 per_compile_timer.Stop(); | 3244 per_compile_timer.Stop(); |
3314 | 3245 |
3315 if (trace_compiler) { | 3246 if (trace_compiler) { |
3316 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", | 3247 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", |
3317 function.ToFullyQualifiedCString(), | 3248 function.ToFullyQualifiedCString(), |
3318 Code::Handle(function.CurrentCode()).PayloadStart(), | 3249 Code::Handle(function.CurrentCode()).PayloadStart(), |
3319 Code::Handle(function.CurrentCode()).Size(), | 3250 Code::Handle(function.CurrentCode()).Size(), |
3320 per_compile_timer.TotalElapsedTime()); | 3251 per_compile_timer.TotalElapsedTime()); |
3321 } | 3252 } |
3322 | 3253 |
3323 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { | 3254 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { |
3324 Disassembler::DisassembleCode(function, optimized); | 3255 Disassembler::DisassembleCode(function, optimized); |
3325 } else if (FLAG_disassemble_optimized && | 3256 } else if (FLAG_disassemble_optimized && optimized && |
3326 optimized && | |
3327 FlowGraphPrinter::ShouldPrint(function)) { | 3257 FlowGraphPrinter::ShouldPrint(function)) { |
3328 Disassembler::DisassembleCode(function, true); | 3258 Disassembler::DisassembleCode(function, true); |
3329 } | 3259 } |
3330 return Error::null(); | 3260 return Error::null(); |
3331 } else { | 3261 } else { |
3332 Thread* const thread = Thread::Current(); | 3262 Thread* const thread = Thread::Current(); |
3333 StackZone stack_zone(thread); | 3263 StackZone stack_zone(thread); |
3334 Error& error = Error::Handle(); | 3264 Error& error = Error::Handle(); |
3335 // We got an error during compilation. | 3265 // We got an error during compilation. |
3336 error = thread->sticky_error(); | 3266 error = thread->sticky_error(); |
(...skipping 18 matching lines...) Expand all Loading... |
3355 | 3285 |
3356 ASSERT(FLAG_precompiled_mode); | 3286 ASSERT(FLAG_precompiled_mode); |
3357 const bool optimized = function.IsOptimizable(); // False for natives. | 3287 const bool optimized = function.IsOptimizable(); // False for natives. |
3358 DartPrecompilationPipeline pipeline(zone, field_type_map); | 3288 DartPrecompilationPipeline pipeline(zone, field_type_map); |
3359 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); | 3289 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); |
3360 } | 3290 } |
3361 | 3291 |
3362 #endif // DART_PRECOMPILER | 3292 #endif // DART_PRECOMPILER |
3363 | 3293 |
3364 } // namespace dart | 3294 } // namespace dart |
OLD | NEW |