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