Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/precompiler.h" | 5 #include "vm/precompiler.h" |
| 6 | 6 |
| 7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
| 10 #include "vm/branch_optimizer.h" | 10 #include "vm/branch_optimizer.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 #include "vm/flow_graph_type_propagator.h" | 26 #include "vm/flow_graph_type_propagator.h" |
| 27 #include "vm/hash_table.h" | 27 #include "vm/hash_table.h" |
| 28 #include "vm/il_printer.h" | 28 #include "vm/il_printer.h" |
| 29 #include "vm/isolate.h" | 29 #include "vm/isolate.h" |
| 30 #include "vm/log.h" | 30 #include "vm/log.h" |
| 31 #include "vm/longjump.h" | 31 #include "vm/longjump.h" |
| 32 #include "vm/object.h" | 32 #include "vm/object.h" |
| 33 #include "vm/object_store.h" | 33 #include "vm/object_store.h" |
| 34 #include "vm/os.h" | 34 #include "vm/os.h" |
| 35 #include "vm/parser.h" | 35 #include "vm/parser.h" |
| 36 #include "vm/program_visitor.h" | |
| 36 #include "vm/redundancy_elimination.h" | 37 #include "vm/redundancy_elimination.h" |
| 37 #include "vm/regexp_assembler.h" | 38 #include "vm/regexp_assembler.h" |
| 38 #include "vm/regexp_parser.h" | 39 #include "vm/regexp_parser.h" |
| 39 #include "vm/resolver.h" | 40 #include "vm/resolver.h" |
| 40 #include "vm/symbols.h" | 41 #include "vm/symbols.h" |
| 41 #include "vm/tags.h" | 42 #include "vm/tags.h" |
| 42 #include "vm/timeline.h" | 43 #include "vm/timeline.h" |
| 43 #include "vm/timer.h" | 44 #include "vm/timer.h" |
| 44 #include "vm/type_table.h" | 45 #include "vm/type_table.h" |
| 46 #include "vm/version.h" | |
| 47 #include "vm/json_parser.h" | |
| 45 | 48 |
| 46 namespace dart { | 49 namespace dart { |
| 47 | 50 |
| 48 | |
| 49 #define T (thread()) | 51 #define T (thread()) |
| 50 #define I (isolate()) | 52 #define I (isolate()) |
| 51 #define Z (zone()) | 53 #define Z (zone()) |
| 52 | 54 |
| 53 | 55 |
| 54 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); | 56 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); |
| 55 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); | 57 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); |
| 56 DEFINE_FLAG( | 58 DEFINE_FLAG( |
| 57 int, | 59 int, |
| 58 max_speculative_inlining_attempts, | 60 max_speculative_inlining_attempts, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 69 DECLARE_FLAG(bool, range_analysis); | 71 DECLARE_FLAG(bool, range_analysis); |
| 70 DECLARE_FLAG(bool, trace_compiler); | 72 DECLARE_FLAG(bool, trace_compiler); |
| 71 DECLARE_FLAG(bool, trace_optimizing_compiler); | 73 DECLARE_FLAG(bool, trace_optimizing_compiler); |
| 72 DECLARE_FLAG(bool, trace_bailout); | 74 DECLARE_FLAG(bool, trace_bailout); |
| 73 DECLARE_FLAG(bool, use_inlining); | 75 DECLARE_FLAG(bool, use_inlining); |
| 74 DECLARE_FLAG(bool, verify_compiler); | 76 DECLARE_FLAG(bool, verify_compiler); |
| 75 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); | 77 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); |
| 76 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 78 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
| 77 DECLARE_FLAG(bool, trace_inlining_intervals); | 79 DECLARE_FLAG(bool, trace_inlining_intervals); |
| 78 DECLARE_FLAG(bool, trace_irregexp); | 80 DECLARE_FLAG(bool, trace_irregexp); |
| 81 DECLARE_FLAG(int, inlining_hotness); | |
| 82 DECLARE_FLAG(int, inlining_size_threshold); | |
| 83 DECLARE_FLAG(int, inlining_callee_size_threshold); | |
| 84 DECLARE_FLAG(int, inline_getters_setters_smaller_than); | |
| 85 DECLARE_FLAG(int, inlining_depth_threshold); | |
| 86 DECLARE_FLAG(int, inlining_caller_size_threshold); | |
| 87 DECLARE_FLAG(int, inlining_constant_arguments_max_size_threshold); | |
| 88 DECLARE_FLAG(int, inlining_constant_arguments_min_size_threshold); | |
| 89 | |
| 79 | 90 |
| 80 #ifdef DART_PRECOMPILER | 91 #ifdef DART_PRECOMPILER |
| 81 | 92 |
| 82 class DartPrecompilationPipeline : public DartCompilationPipeline { | 93 class DartPrecompilationPipeline : public DartCompilationPipeline { |
| 83 public: | 94 public: |
| 84 explicit DartPrecompilationPipeline(Zone* zone, | 95 explicit DartPrecompilationPipeline(Zone* zone, |
| 85 FieldTypeMap* field_map = NULL) | 96 FieldTypeMap* field_map = NULL) |
| 86 : zone_(zone), result_type_(CompileType::None()), field_map_(field_map) {} | 97 : zone_(zone), result_type_(CompileType::None()), field_map_(field_map) {} |
| 87 | 98 |
| 88 virtual void FinalizeCompilation(FlowGraph* flow_graph) { | 99 virtual void FinalizeCompilation(FlowGraph* flow_graph) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 | 189 |
| 179 DISALLOW_COPY_AND_ASSIGN(PrecompileParsedFunctionHelper); | 190 DISALLOW_COPY_AND_ASSIGN(PrecompileParsedFunctionHelper); |
| 180 }; | 191 }; |
| 181 | 192 |
| 182 | 193 |
| 183 static void Jump(const Error& error) { | 194 static void Jump(const Error& error) { |
| 184 Thread::Current()->long_jump_base()->Jump(1, error); | 195 Thread::Current()->long_jump_base()->Jump(1, error); |
| 185 } | 196 } |
| 186 | 197 |
| 187 | 198 |
| 199 TypeRangeCache::TypeRangeCache(Precompiler* precompiler, | |
| 200 Thread* thread, | |
| 201 intptr_t num_cids) | |
| 202 : precompiler_(precompiler), | |
| 203 thread_(thread), | |
| 204 lower_limits_(thread->zone()->Alloc<intptr_t>(num_cids)), | |
| 205 upper_limits_(thread->zone()->Alloc<intptr_t>(num_cids)) { | |
| 206 for (intptr_t i = 0; i < num_cids; i++) { | |
| 207 lower_limits_[i] = kNotComputed; | |
| 208 upper_limits_[i] = kNotComputed; | |
| 209 } | |
| 210 ASSERT(precompiler->type_range_cache() == NULL); | |
| 211 precompiler->set_type_range_cache(this); | |
| 212 } | |
| 213 | |
| 214 | |
| 215 TypeRangeCache::~TypeRangeCache() { | |
| 216 ASSERT(precompiler_->type_range_cache() == this); | |
| 217 precompiler_->set_type_range_cache(NULL); | |
| 218 } | |
| 219 | |
| 220 | |
| 188 RawError* Precompiler::CompileAll( | 221 RawError* Precompiler::CompileAll( |
| 189 Dart_QualifiedFunctionName embedder_entry_points[], | 222 Dart_QualifiedFunctionName embedder_entry_points[], |
| 190 bool reset_fields) { | 223 bool reset_fields, |
| 224 uint8_t* jit_feedback, | |
| 225 intptr_t jit_feedback_length) { | |
| 191 LongJumpScope jump; | 226 LongJumpScope jump; |
| 192 if (setjmp(*jump.Set()) == 0) { | 227 if (setjmp(*jump.Set()) == 0) { |
| 193 Precompiler precompiler(Thread::Current(), reset_fields); | 228 Precompiler precompiler(Thread::Current(), reset_fields); |
| 229 precompiler.LoadFeedback(jit_feedback, jit_feedback_length); | |
| 194 precompiler.DoCompileAll(embedder_entry_points); | 230 precompiler.DoCompileAll(embedder_entry_points); |
| 195 return Error::null(); | 231 return Error::null(); |
| 196 } else { | 232 } else { |
| 197 Thread* thread = Thread::Current(); | 233 Thread* thread = Thread::Current(); |
| 198 const Error& error = Error::Handle(thread->sticky_error()); | 234 const Error& error = Error::Handle(thread->sticky_error()); |
| 199 thread->clear_sticky_error(); | 235 thread->clear_sticky_error(); |
| 200 return error.raw(); | 236 return error.raw(); |
| 201 } | 237 } |
| 202 } | 238 } |
| 203 | 239 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 287 upper_limits_[type_cid] = *upper_limit; | 323 upper_limits_[type_cid] = *upper_limit; |
| 288 return true; | 324 return true; |
| 289 } | 325 } |
| 290 | 326 |
| 291 | 327 |
| 292 Precompiler::Precompiler(Thread* thread, bool reset_fields) | 328 Precompiler::Precompiler(Thread* thread, bool reset_fields) |
| 293 : thread_(thread), | 329 : thread_(thread), |
| 294 zone_(NULL), | 330 zone_(NULL), |
| 295 isolate_(thread->isolate()), | 331 isolate_(thread->isolate()), |
| 296 reset_fields_(reset_fields), | 332 reset_fields_(reset_fields), |
| 333 jit_feedback_(NULL), | |
| 297 changed_(false), | 334 changed_(false), |
| 298 function_count_(0), | 335 function_count_(0), |
| 299 class_count_(0), | 336 class_count_(0), |
| 300 selector_count_(0), | 337 selector_count_(0), |
| 301 dropped_function_count_(0), | 338 dropped_function_count_(0), |
| 302 dropped_field_count_(0), | 339 dropped_field_count_(0), |
| 303 dropped_class_count_(0), | 340 dropped_class_count_(0), |
| 304 dropped_typearg_count_(0), | 341 dropped_typearg_count_(0), |
| 305 dropped_type_count_(0), | 342 dropped_type_count_(0), |
| 306 dropped_library_count_(0), | 343 dropped_library_count_(0), |
| 307 libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())), | 344 libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())), |
| 308 pending_functions_( | 345 pending_functions_( |
| 309 GrowableObjectArray::Handle(GrowableObjectArray::New())), | 346 GrowableObjectArray::Handle(GrowableObjectArray::New())), |
| 310 sent_selectors_(), | 347 sent_selectors_(), |
| 311 enqueued_functions_(), | 348 enqueued_functions_(), |
| 312 fields_to_retain_(), | 349 fields_to_retain_(), |
| 313 functions_to_retain_(), | 350 functions_to_retain_(), |
| 314 classes_to_retain_(), | 351 classes_to_retain_(), |
| 315 typeargs_to_retain_(), | 352 typeargs_to_retain_(), |
| 316 types_to_retain_(), | 353 types_to_retain_(), |
| 317 consts_to_retain_(), | 354 consts_to_retain_(), |
| 318 field_type_map_(), | 355 field_type_map_(), |
| 356 type_range_cache_(NULL), | |
| 319 error_(Error::Handle()), | 357 error_(Error::Handle()), |
| 320 get_runtime_type_is_unique_(false) {} | 358 get_runtime_type_is_unique_(false) {} |
| 321 | 359 |
| 322 | 360 |
| 361 void Precompiler::LoadFeedback(uint8_t* buffer, intptr_t length) { | |
| 362 if (buffer == NULL) { | |
| 363 if (FLAG_trace_precompiler) { | |
| 364 THR_Print("Precompiler running without JIT feedback\n"); | |
| 365 } | |
| 366 | |
| 367 // Flags affecting compilation only: | |
| 368 // There is no counter feedback in precompilation, so ignore the counter | |
| 369 // when making inlining decisions. | |
| 370 FLAG_inlining_hotness = 0; | |
| 371 // Use smaller thresholds in precompilation as we are compiling everything | |
| 372 // with the optimizing compiler instead of only hot functions. | |
| 373 FLAG_inlining_size_threshold = 5; | |
| 374 FLAG_inline_getters_setters_smaller_than = 5; | |
| 375 FLAG_inlining_callee_size_threshold = 20; | |
| 376 FLAG_inlining_depth_threshold = 4; | |
| 377 FLAG_inlining_caller_size_threshold = 1000; | |
| 378 FLAG_inlining_constant_arguments_max_size_threshold = 100; | |
| 379 FLAG_inlining_constant_arguments_min_size_threshold = 30; | |
| 380 return; | |
| 381 } | |
| 382 | |
| 383 if (FLAG_trace_precompiler) { | |
| 384 THR_Print("Loading JIT feedback\n"); | |
| 385 } | |
| 386 | |
| 387 JSONParser parser(reinterpret_cast<const char*>(buffer), length, | |
| 388 Thread::Current()->zone()); | |
| 389 ParsedJSONValue* root = parser.ParseValue(); | |
| 390 if (root->IsError()) { | |
| 391 ParsedJSONError* error = static_cast<ParsedJSONError*>(root); | |
| 392 THR_Print("Error parsing JIT feedback: %s:%" Pd "\n", error->message(), | |
| 393 error->position()); | |
| 394 } else if (!root->IsObject()) { | |
| 395 THR_Print("Error parsing JIT feedback: object expected\n"); | |
| 396 } else { | |
| 397 jit_feedback_ = static_cast<ParsedJSONObject*>(root); | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 | |
| 323 void Precompiler::DoCompileAll( | 402 void Precompiler::DoCompileAll( |
| 324 Dart_QualifiedFunctionName embedder_entry_points[]) { | 403 Dart_QualifiedFunctionName embedder_entry_points[]) { |
| 325 ASSERT(I->compilation_allowed()); | 404 ASSERT(I->compilation_allowed()); |
| 326 | 405 |
| 327 { | 406 { |
| 328 StackZone stack_zone(T); | 407 StackZone stack_zone(T); |
| 329 zone_ = stack_zone.GetZone(); | 408 zone_ = stack_zone.GetZone(); |
| 330 | 409 |
| 331 { | 410 { |
| 332 HANDLESCOPE(T); | 411 HANDLESCOPE(T); |
| 333 // Make sure class hierarchy is stable before compilation so that CHA | 412 // Make sure class hierarchy is stable before compilation so that CHA |
| 334 // can be used. Also ensures lookup of entry points won't miss functions | 413 // can be used. Also ensures lookup of entry points won't miss functions |
| 335 // because their class hasn't been finalized yet. | 414 // because their class hasn't been finalized yet. |
| 336 FinalizeAllClasses(); | 415 FinalizeAllClasses(); |
| 337 | 416 |
| 338 SortClasses(); | 417 SortClasses(); |
| 339 TypeRangeCache trc(T, I->class_table()->NumCids()); | 418 TypeRangeCache trc(this, T, I->class_table()->NumCids()); |
| 419 VerifyJITFeedback(); | |
| 340 | 420 |
| 341 // Precompile static initializers to compute result type information. | 421 // Precompile static initializers to compute result type information. |
| 342 PrecompileStaticInitializers(); | 422 PrecompileStaticInitializers(); |
| 343 | 423 |
| 344 // Precompile constructors to compute type information for final fields. | 424 // Precompile constructors to compute type information for final fields. |
| 345 ClearAllCode(); | 425 ClearAllCode(); |
| 346 PrecompileConstructors(); | 426 PrecompileConstructors(); |
| 347 | 427 |
| 348 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { | 428 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { |
| 349 if (FLAG_trace_precompiler) { | 429 if (FLAG_trace_precompiler) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 } | 551 } |
| 472 | 552 |
| 473 private: | 553 private: |
| 474 Array& fields_; | 554 Array& fields_; |
| 475 Field& field_; | 555 Field& field_; |
| 476 Function& function_; | 556 Function& function_; |
| 477 }; | 557 }; |
| 478 | 558 |
| 479 HANDLESCOPE(T); | 559 HANDLESCOPE(T); |
| 480 StaticInitializerVisitor visitor(Z); | 560 StaticInitializerVisitor visitor(Z); |
| 481 VisitClasses(&visitor); | 561 ProgramVisitor::VisitClasses(&visitor); |
| 482 } | 562 } |
| 483 | 563 |
| 484 | 564 |
| 485 void Precompiler::PrecompileConstructors() { | 565 void Precompiler::PrecompileConstructors() { |
| 486 class ConstructorVisitor : public FunctionVisitor { | 566 class ConstructorVisitor : public FunctionVisitor { |
| 487 public: | 567 public: |
| 488 explicit ConstructorVisitor(Precompiler* precompiler, Zone* zone) | 568 explicit ConstructorVisitor(Precompiler* precompiler, Zone* zone) |
| 489 : precompiler_(precompiler), zone_(zone) {} | 569 : precompiler_(precompiler), zone_(zone) {} |
| 490 void Visit(const Function& function) { | 570 void Visit(const Function& function) { |
| 491 if (!function.IsGenerativeConstructor()) return; | 571 if (!function.IsGenerativeConstructor()) return; |
| 492 if (function.HasCode()) { | 572 if (function.HasCode()) { |
| 493 // Const constructors may have been visited before. Recompile them here | 573 // Const constructors may have been visited before. Recompile them here |
| 494 // to collect type information for final fields for them as well. | 574 // to collect type information for final fields for them as well. |
| 495 function.ClearCode(); | 575 function.ClearCode(); |
| 496 } | 576 } |
| 497 if (FLAG_trace_precompiler) { | 577 if (FLAG_trace_precompiler) { |
| 498 THR_Print("Precompiling constructor %s\n", function.ToCString()); | 578 THR_Print("Precompiling constructor %s\n", function.ToCString()); |
| 499 } | 579 } |
| 500 CompileFunction(precompiler_, Thread::Current(), zone_, function, | 580 CompileFunction(precompiler_, Thread::Current(), zone_, function, |
| 501 precompiler_->field_type_map()); | 581 precompiler_->field_type_map()); |
| 502 } | 582 } |
| 503 | 583 |
| 504 private: | 584 private: |
| 505 Precompiler* precompiler_; | 585 Precompiler* precompiler_; |
| 506 Zone* zone_; | 586 Zone* zone_; |
| 507 }; | 587 }; |
| 508 | 588 |
| 509 HANDLESCOPE(T); | 589 HANDLESCOPE(T); |
| 510 ConstructorVisitor visitor(this, zone_); | 590 ConstructorVisitor visitor(this, zone_); |
| 511 VisitFunctions(&visitor); | 591 ProgramVisitor::VisitFunctions(&visitor); |
| 512 | 592 |
| 513 FieldTypeMap::Iterator it(field_type_map_.GetIterator()); | 593 FieldTypeMap::Iterator it(field_type_map_.GetIterator()); |
| 514 for (FieldTypePair* current = it.Next(); current != NULL; | 594 for (FieldTypePair* current = it.Next(); current != NULL; |
| 515 current = it.Next()) { | 595 current = it.Next()) { |
| 516 const intptr_t cid = current->cid_; | 596 const intptr_t cid = current->cid_; |
| 517 current->field_->set_guarded_cid(cid); | 597 current->field_->set_guarded_cid(cid); |
| 518 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); | 598 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); |
| 519 if (FLAG_trace_precompiler) { | 599 if (FLAG_trace_precompiler) { |
| 520 THR_Print( | 600 THR_Print( |
| 521 "Field %s <- Type %s\n", current->field_->ToCString(), | 601 "Field %s <- Type %s\n", current->field_->ToCString(), |
| 522 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); | 602 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); |
| 523 } | 603 } |
| 524 } | 604 } |
| 525 } | 605 } |
| 526 | 606 |
| 527 | 607 |
| 528 void Precompiler::ClearAllCode() { | 608 void Precompiler::ClearAllCode() { |
| 529 class ClearCodeFunctionVisitor : public FunctionVisitor { | 609 class ClearCodeFunctionVisitor : public FunctionVisitor { |
| 530 void Visit(const Function& function) { | 610 void Visit(const Function& function) { |
| 531 function.ClearCode(); | 611 function.ClearCode(); |
| 532 function.ClearICDataArray(); | 612 function.ClearICDataArray(); |
| 533 } | 613 } |
| 534 }; | 614 }; |
| 535 ClearCodeFunctionVisitor function_visitor; | 615 ClearCodeFunctionVisitor function_visitor; |
| 536 VisitFunctions(&function_visitor); | 616 ProgramVisitor::VisitFunctions(&function_visitor); |
| 537 | 617 |
| 538 class ClearCodeClassVisitor : public ClassVisitor { | 618 class ClearCodeClassVisitor : public ClassVisitor { |
| 539 void Visit(const Class& cls) { cls.DisableAllocationStub(); } | 619 void Visit(const Class& cls) { cls.DisableAllocationStub(); } |
| 540 }; | 620 }; |
| 541 ClearCodeClassVisitor class_visitor; | 621 ClearCodeClassVisitor class_visitor; |
| 542 VisitClasses(&class_visitor); | 622 ProgramVisitor::VisitClasses(&class_visitor); |
| 543 } | 623 } |
| 544 | 624 |
| 545 | 625 |
| 546 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { | 626 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { |
| 547 // Note that <rootlibrary>.main is not a root. The appropriate main will be | 627 // Note that <rootlibrary>.main is not a root. The appropriate main will be |
| 548 // discovered through _getMainClosure. | 628 // discovered through _getMainClosure. |
| 549 | 629 |
| 550 AddSelector(Symbols::NoSuchMethod()); | 630 AddSelector(Symbols::NoSuchMethod()); |
| 551 | 631 |
| 552 AddSelector(Symbols::Call()); // For speed, not correctness. | 632 AddSelector(Symbols::Call()); // For speed, not correctness. |
| (...skipping 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2074 | 2154 |
| 2075 private: | 2155 private: |
| 2076 Code& code_; | 2156 Code& code_; |
| 2077 Array& table_; | 2157 Array& table_; |
| 2078 Smi& pc_offset_; | 2158 Smi& pc_offset_; |
| 2079 Function& target_; | 2159 Function& target_; |
| 2080 Code& target_code_; | 2160 Code& target_code_; |
| 2081 }; | 2161 }; |
| 2082 | 2162 |
| 2083 BindStaticCallsVisitor visitor(Z); | 2163 BindStaticCallsVisitor visitor(Z); |
| 2084 VisitFunctions(&visitor); | 2164 ProgramVisitor::VisitFunctions(&visitor); |
| 2085 } | 2165 } |
| 2086 | 2166 |
| 2087 | 2167 |
| 2088 void Precompiler::SwitchICCalls() { | 2168 void Precompiler::SwitchICCalls() { |
| 2089 #if !defined(TARGET_ARCH_DBC) | 2169 #if !defined(TARGET_ARCH_DBC) |
| 2090 // Now that all functions have been compiled, we can switch to an instance | 2170 // Now that all functions have been compiled, we can switch to an instance |
| 2091 // call sequence that loads the Code object and entry point directly from | 2171 // call sequence that loads the Code object and entry point directly from |
| 2092 // the ic data array instead indirectly through a Function in the ic data | 2172 // the ic data array instead indirectly through a Function in the ic data |
| 2093 // array. Iterate all the object pools and rewrite the ic data from | 2173 // array. Iterate all the object pools and rewrite the ic data from |
| 2094 // (cid, target function, count) to (cid, target code, entry point), and | 2174 // (cid, target function, count) to (cid, target code, entry point), and |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2163 ICData& ic_; | 2243 ICData& ic_; |
| 2164 String& target_name_; | 2244 String& target_name_; |
| 2165 Array& args_descriptor_; | 2245 Array& args_descriptor_; |
| 2166 UnlinkedCall& unlinked_; | 2246 UnlinkedCall& unlinked_; |
| 2167 Code& target_code_; | 2247 Code& target_code_; |
| 2168 UnlinkedCallSet canonical_unlinked_calls_; | 2248 UnlinkedCallSet canonical_unlinked_calls_; |
| 2169 }; | 2249 }; |
| 2170 | 2250 |
| 2171 ASSERT(!I->compilation_allowed()); | 2251 ASSERT(!I->compilation_allowed()); |
| 2172 SwitchICCallsVisitor visitor(Z); | 2252 SwitchICCallsVisitor visitor(Z); |
| 2173 VisitFunctions(&visitor); | 2253 ProgramVisitor::VisitFunctions(&visitor); |
| 2174 #endif | 2254 #endif |
| 2175 } | 2255 } |
| 2176 | 2256 |
| 2177 | 2257 |
| 2178 void Precompiler::ShareMegamorphicBuckets() { | 2258 void Precompiler::ShareMegamorphicBuckets() { |
| 2179 const GrowableObjectArray& table = GrowableObjectArray::Handle( | 2259 const GrowableObjectArray& table = GrowableObjectArray::Handle( |
| 2180 Z, I->object_store()->megamorphic_cache_table()); | 2260 Z, I->object_store()->megamorphic_cache_table()); |
| 2181 if (table.IsNull()) return; | 2261 if (table.IsNull()) return; |
| 2182 MegamorphicCache& cache = MegamorphicCache::Handle(Z); | 2262 MegamorphicCache& cache = MegamorphicCache::Handle(Z); |
| 2183 | 2263 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2236 | 2316 |
| 2237 private: | 2317 private: |
| 2238 Zone* zone_; | 2318 Zone* zone_; |
| 2239 StackMapSet canonical_stackmaps_; | 2319 StackMapSet canonical_stackmaps_; |
| 2240 Code& code_; | 2320 Code& code_; |
| 2241 Array& stackmaps_; | 2321 Array& stackmaps_; |
| 2242 StackMap& stackmap_; | 2322 StackMap& stackmap_; |
| 2243 }; | 2323 }; |
| 2244 | 2324 |
| 2245 DedupStackMapsVisitor visitor(Z); | 2325 DedupStackMapsVisitor visitor(Z); |
| 2246 VisitFunctions(&visitor); | 2326 ProgramVisitor::VisitFunctions(&visitor); |
| 2247 } | 2327 } |
| 2248 | 2328 |
| 2249 | 2329 |
| 2250 void Precompiler::DedupLists() { | 2330 void Precompiler::DedupLists() { |
| 2251 class DedupListsVisitor : public FunctionVisitor { | 2331 class DedupListsVisitor : public FunctionVisitor { |
| 2252 public: | 2332 public: |
| 2253 explicit DedupListsVisitor(Zone* zone) | 2333 explicit DedupListsVisitor(Zone* zone) |
| 2254 : zone_(zone), | 2334 : zone_(zone), |
| 2255 canonical_lists_(), | 2335 canonical_lists_(), |
| 2256 code_(Code::Handle(zone)), | 2336 code_(Code::Handle(zone)), |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2303 } | 2383 } |
| 2304 | 2384 |
| 2305 private: | 2385 private: |
| 2306 Zone* zone_; | 2386 Zone* zone_; |
| 2307 ArraySet canonical_lists_; | 2387 ArraySet canonical_lists_; |
| 2308 Code& code_; | 2388 Code& code_; |
| 2309 Array& list_; | 2389 Array& list_; |
| 2310 }; | 2390 }; |
| 2311 | 2391 |
| 2312 DedupListsVisitor visitor(Z); | 2392 DedupListsVisitor visitor(Z); |
| 2313 VisitFunctions(&visitor); | 2393 ProgramVisitor::VisitFunctions(&visitor); |
| 2314 } | 2394 } |
| 2315 | 2395 |
| 2316 | 2396 |
| 2317 void Precompiler::DedupInstructions() { | 2397 void Precompiler::DedupInstructions() { |
| 2318 class DedupInstructionsVisitor : public FunctionVisitor { | 2398 class DedupInstructionsVisitor : public FunctionVisitor { |
| 2319 public: | 2399 public: |
| 2320 explicit DedupInstructionsVisitor(Zone* zone) | 2400 explicit DedupInstructionsVisitor(Zone* zone) |
| 2321 : zone_(zone), | 2401 : zone_(zone), |
| 2322 canonical_instructions_set_(), | 2402 canonical_instructions_set_(), |
| 2323 code_(Code::Handle(zone)), | 2403 code_(Code::Handle(zone)), |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2349 } | 2429 } |
| 2350 | 2430 |
| 2351 private: | 2431 private: |
| 2352 Zone* zone_; | 2432 Zone* zone_; |
| 2353 InstructionsSet canonical_instructions_set_; | 2433 InstructionsSet canonical_instructions_set_; |
| 2354 Code& code_; | 2434 Code& code_; |
| 2355 Instructions& instructions_; | 2435 Instructions& instructions_; |
| 2356 }; | 2436 }; |
| 2357 | 2437 |
| 2358 DedupInstructionsVisitor visitor(Z); | 2438 DedupInstructionsVisitor visitor(Z); |
| 2359 VisitFunctions(&visitor); | 2439 ProgramVisitor::VisitFunctions(&visitor); |
| 2360 } | 2440 } |
| 2361 | 2441 |
| 2362 | 2442 |
| 2363 void Precompiler::VisitClasses(ClassVisitor* visitor) { | |
| 2364 Library& lib = Library::Handle(Z); | |
| 2365 Class& cls = Class::Handle(Z); | |
| 2366 | |
| 2367 for (intptr_t i = 0; i < libraries_.Length(); i++) { | |
| 2368 lib ^= libraries_.At(i); | |
| 2369 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); | |
| 2370 while (it.HasNext()) { | |
| 2371 cls = it.GetNextClass(); | |
| 2372 if (cls.IsDynamicClass()) { | |
| 2373 continue; // class 'dynamic' is in the read-only VM isolate. | |
| 2374 } | |
| 2375 visitor->Visit(cls); | |
| 2376 } | |
| 2377 } | |
| 2378 } | |
| 2379 | |
| 2380 | |
| 2381 void Precompiler::VisitFunctions(FunctionVisitor* visitor) { | |
| 2382 Library& lib = Library::Handle(Z); | |
| 2383 Class& cls = Class::Handle(Z); | |
| 2384 Array& functions = Array::Handle(Z); | |
| 2385 Array& fields = Array::Handle(Z); | |
| 2386 Field& field = Field::Handle(Z); | |
| 2387 Object& object = Object::Handle(Z); | |
| 2388 Function& function = Function::Handle(Z); | |
| 2389 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); | |
| 2390 | |
| 2391 for (intptr_t i = 0; i < libraries_.Length(); i++) { | |
| 2392 lib ^= libraries_.At(i); | |
| 2393 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); | |
| 2394 while (it.HasNext()) { | |
| 2395 cls = it.GetNextClass(); | |
| 2396 if (cls.IsDynamicClass()) { | |
| 2397 continue; // class 'dynamic' is in the read-only VM isolate. | |
| 2398 } | |
| 2399 | |
| 2400 functions = cls.functions(); | |
| 2401 for (intptr_t j = 0; j < functions.Length(); j++) { | |
| 2402 function ^= functions.At(j); | |
| 2403 visitor->Visit(function); | |
| 2404 if (function.HasImplicitClosureFunction()) { | |
| 2405 function = function.ImplicitClosureFunction(); | |
| 2406 visitor->Visit(function); | |
| 2407 } | |
| 2408 } | |
| 2409 | |
| 2410 functions = cls.invocation_dispatcher_cache(); | |
| 2411 for (intptr_t j = 0; j < functions.Length(); j++) { | |
| 2412 object = functions.At(j); | |
| 2413 if (object.IsFunction()) { | |
| 2414 function ^= functions.At(j); | |
| 2415 visitor->Visit(function); | |
| 2416 } | |
| 2417 } | |
| 2418 fields = cls.fields(); | |
| 2419 for (intptr_t j = 0; j < fields.Length(); j++) { | |
| 2420 field ^= fields.At(j); | |
| 2421 if (field.is_static() && field.HasPrecompiledInitializer()) { | |
| 2422 function ^= field.PrecompiledInitializer(); | |
| 2423 visitor->Visit(function); | |
| 2424 } | |
| 2425 } | |
| 2426 } | |
| 2427 } | |
| 2428 closures = isolate()->object_store()->closure_functions(); | |
| 2429 for (intptr_t j = 0; j < closures.Length(); j++) { | |
| 2430 function ^= closures.At(j); | |
| 2431 visitor->Visit(function); | |
| 2432 ASSERT(!function.HasImplicitClosureFunction()); | |
| 2433 } | |
| 2434 } | |
| 2435 | |
| 2436 | |
| 2437 void Precompiler::FinalizeAllClasses() { | 2443 void Precompiler::FinalizeAllClasses() { |
| 2438 Library& lib = Library::Handle(Z); | 2444 Library& lib = Library::Handle(Z); |
| 2439 Class& cls = Class::Handle(Z); | 2445 Class& cls = Class::Handle(Z); |
| 2440 | 2446 |
| 2441 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 2447 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
| 2442 lib ^= libraries_.At(i); | 2448 lib ^= libraries_.At(i); |
| 2443 if (!lib.Loaded()) { | 2449 if (!lib.Loaded()) { |
| 2444 String& uri = String::Handle(Z, lib.url()); | 2450 String& uri = String::Handle(Z, lib.url()); |
| 2445 String& msg = String::Handle( | 2451 String& msg = String::Handle( |
| 2446 Z, | 2452 Z, |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2600 } | 2606 } |
| 2601 } | 2607 } |
| 2602 | 2608 |
| 2603 #if defined(DEBUG) | 2609 #if defined(DEBUG) |
| 2604 I->class_table()->Validate(); | 2610 I->class_table()->Validate(); |
| 2605 I->heap()->Verify(); | 2611 I->heap()->Verify(); |
| 2606 #endif | 2612 #endif |
| 2607 } | 2613 } |
| 2608 | 2614 |
| 2609 | 2615 |
| 2616 void Precompiler::VerifyJITFeedback() { | |
| 2617 if (jit_feedback_ == NULL) return; | |
| 2618 | |
| 2619 ParsedJSONString* js_vmversion = jit_feedback_->StringAt("vmVersion"); | |
| 2620 if ((js_vmversion == NULL) || | |
| 2621 strcmp(Version::CommitString(), js_vmversion->value()) != 0) { | |
| 2622 THR_Print("JIT feedback contains invalid vm version\n"); | |
| 2623 THR_Print("%s\n", js_vmversion->value()); | |
| 2624 THR_Print("%s\n", Version::SnapshotString()); | |
| 2625 jit_feedback_ = NULL; | |
| 2626 return; | |
| 2627 } | |
| 2628 ParsedJSONBoolean* js_asserts = jit_feedback_->BooleanAt("asserts"); | |
| 2629 if ((js_asserts == NULL) || (FLAG_enable_asserts != js_asserts->value())) { | |
| 2630 THR_Print("JIT feedback contains invalid FLAG_enable_asserts\n"); | |
| 2631 jit_feedback_ = NULL; | |
| 2632 return; | |
| 2633 } | |
| 2634 ParsedJSONBoolean* js_typechecks = jit_feedback_->BooleanAt("typeChecks"); | |
| 2635 if ((js_typechecks == NULL) || | |
| 2636 (FLAG_enable_type_checks != js_typechecks->value())) { | |
| 2637 THR_Print("JIT feedback contains invalid FLAG_enable_type_checks\n"); | |
| 2638 jit_feedback_ = NULL; | |
| 2639 return; | |
| 2640 } | |
| 2641 | |
| 2642 ParsedJSONArray* js_scripts = jit_feedback_->ArrayAt("scripts"); | |
| 2643 ASSERT(js_scripts != NULL); | |
| 2644 Script& script = Script::Handle(Z); | |
| 2645 for (intptr_t i = 0; i < js_scripts->Length(); i++) { | |
| 2646 ParsedJSONObject* js_script = js_scripts->ObjectAt(i); | |
| 2647 ASSERT(js_script != NULL); | |
| 2648 ParsedJSONString* js_uri = js_script->StringAt("uri"); | |
| 2649 ASSERT(js_uri != NULL); | |
| 2650 ParsedJSONNumber* js_fp = js_script->NumberAt("checksum"); | |
| 2651 ASSERT(js_fp != NULL); | |
| 2652 script = LookupScript(js_uri->value()); | |
| 2653 if (script.IsNull()) { | |
| 2654 THR_Print("Cannot find script %s\n", js_uri->value()); | |
| 2655 continue; | |
| 2656 } | |
| 2657 intptr_t fp = script.SourceFingerprint(); | |
| 2658 if (fp != js_fp->value()) { | |
| 2659 THR_Print( | |
| 2660 "Fingerprint has changed for %s. Continuing without JIT " | |
| 2661 "feedback.\n", | |
| 2662 js_uri->value()); | |
| 2663 jit_feedback_ = NULL; | |
| 2664 return; | |
| 2665 } | |
| 2666 } | |
| 2667 | |
| 2668 ParsedJSONArray* js_classes = jit_feedback_->ArrayAt("classes"); | |
| 2669 ASSERT(js_classes != NULL); | |
| 2670 Library& lib = Library::Handle(Z); | |
| 2671 Class& cls = Class::Handle(Z); | |
| 2672 String& str = String::Handle(Z); | |
| 2673 for (intptr_t i = 0; i < js_classes->Length(); i++) { | |
| 2674 ParsedJSONObject* js_class = js_classes->ObjectAt(i); | |
| 2675 ASSERT(js_class != NULL); | |
| 2676 ParsedJSONString* js_uri = js_class->StringAt("uri"); | |
| 2677 ASSERT(js_uri != NULL); | |
| 2678 ParsedJSONString* js_name = js_class->StringAt("name"); | |
| 2679 ASSERT(js_name != NULL); | |
| 2680 ParsedJSONNumber* js_cid = js_class->NumberAt("cid"); | |
| 2681 ASSERT(js_cid != NULL); | |
| 2682 | |
| 2683 str = String::New(js_uri->value()); | |
| 2684 lib = Library::LookupLibrary(T, str); | |
| 2685 if (lib.IsNull()) { | |
| 2686 THR_Print("Cannot find library %s\n", js_uri->value()); | |
| 2687 continue; | |
| 2688 } | |
| 2689 str = String::New(js_name->value()); | |
| 2690 if (str.Equals(Symbols::TopLevel())) { | |
| 2691 cls = lib.toplevel_class(); | |
| 2692 } else { | |
| 2693 cls = lib.LookupClassAllowPrivate(str); | |
| 2694 } | |
| 2695 if (cls.IsNull()) { | |
| 2696 THR_Print("Missing class %s\n", js_name->value()); | |
| 2697 continue; | |
| 2698 } | |
| 2699 | |
| 2700 feedback_cid_map_.Insert(IntptrPair(js_cid->value(), cls.id())); | |
| 2701 } | |
| 2702 | |
| 2703 ParsedJSONArray* js_functions = jit_feedback_->ArrayAt("functions"); | |
| 2704 ASSERT(js_functions != NULL); | |
| 2705 for (intptr_t i = 0; i < js_functions->Length(); i++) { | |
| 2706 ParsedJSONObject* js_function = js_functions->ObjectAt(i); | |
| 2707 ASSERT(js_function != NULL); | |
| 2708 ParsedJSONString* js_name = js_function->StringAt("name"); | |
| 2709 ASSERT(js_name != NULL); | |
| 2710 ParsedJSONNumber* js_cid = js_function->NumberAt("class"); | |
| 2711 ASSERT(js_cid != NULL); | |
| 2712 ParsedJSONNumber* js_token = js_function->NumberAt("tokenPos"); | |
| 2713 ASSERT(js_token != NULL); | |
| 2714 ParsedJSONNumber* js_kind = js_function->NumberAt("kind"); | |
| 2715 ASSERT(js_kind != NULL); | |
| 2716 function_feedback_map_.Insert(FunctionFeedbackPair( | |
| 2717 FunctionFeedbackKey(MapCid(js_cid->value()), js_token->value(), | |
| 2718 js_kind->value()), | |
| 2719 js_function)); | |
| 2720 } | |
| 2721 | |
| 2722 class ApplyUsageVisitor : public FunctionVisitor { | |
| 2723 public: | |
| 2724 explicit ApplyUsageVisitor(Precompiler* precompiler) | |
| 2725 : precompiler_(precompiler) {} | |
| 2726 void Visit(const Function& function) { | |
| 2727 ParsedJSONObject* js_function = precompiler_->LookupFeedback(function); | |
| 2728 if (js_function == NULL) { | |
| 2729 function.set_usage_counter(0); | |
| 2730 } else { | |
| 2731 ParsedJSONNumber* js_usage = js_function->NumberAt("usageCounter"); | |
| 2732 ASSERT(js_usage != NULL); | |
| 2733 function.set_usage_counter(js_usage->value()); | |
| 2734 } | |
| 2735 } | |
| 2736 | |
| 2737 private: | |
| 2738 Precompiler* precompiler_; | |
| 2739 }; | |
| 2740 | |
| 2741 ApplyUsageVisitor visitor(this); | |
| 2742 ProgramVisitor::VisitFunctions(&visitor); | |
| 2743 } | |
| 2744 | |
| 2745 | |
| 2746 ParsedJSONObject* Precompiler::LookupFeedback(const Function& function) { | |
| 2747 const Class& owner = Class::Handle(Z, function.Owner()); | |
| 2748 | |
| 2749 FunctionFeedbackKey key(owner.id(), function.token_pos().value(), | |
| 2750 function.kind()); | |
| 2751 FunctionFeedbackPair* pair = function_feedback_map_.Lookup(key); | |
| 2752 if (pair == NULL) { | |
| 2753 return NULL; | |
| 2754 } | |
| 2755 return pair->value_; | |
| 2756 } | |
| 2757 | |
| 2758 | |
| 2759 RawScript* Precompiler::LookupScript(const char* uri) { | |
| 2760 String& dart_uri = String::Handle(Z, String::New(uri)); | |
| 2761 Library& lib = Library::Handle(Z); | |
| 2762 Script& script = Script::Handle(Z); | |
| 2763 for (intptr_t i = 0; i < libraries_.Length(); i++) { | |
| 2764 lib ^= libraries_.At(i); | |
| 2765 script = lib.LookupScript(dart_uri); | |
| 2766 if (!script.IsNull()) { | |
| 2767 return script.raw(); | |
| 2768 } | |
| 2769 } | |
| 2770 return Script::null(); | |
| 2771 } | |
| 2772 | |
| 2773 | |
| 2774 intptr_t Precompiler::MapCid(intptr_t feedback_cid) { | |
| 2775 if (feedback_cid < kNumPredefinedCids) { | |
| 2776 return feedback_cid; | |
| 2777 } | |
| 2778 IntptrPair* pair = feedback_cid_map_.Lookup(feedback_cid); | |
| 2779 if (pair == NULL) return kIllegalCid; | |
| 2780 return pair->value_; | |
| 2781 } | |
| 2782 | |
| 2783 | |
| 2784 void Precompiler::PopulateWithICData(const Function& function, | |
| 2785 FlowGraph* graph) { | |
| 2786 Zone* zone = Thread::Current()->zone(); | |
| 2787 | |
| 2788 for (BlockIterator block_it = graph->reverse_postorder_iterator(); | |
| 2789 !block_it.Done(); block_it.Advance()) { | |
| 2790 ForwardInstructionIterator it(block_it.Current()); | |
| 2791 for (; !it.Done(); it.Advance()) { | |
| 2792 Instruction* instr = it.Current(); | |
| 2793 if (instr->IsInstanceCall()) { | |
| 2794 InstanceCallInstr* call = instr->AsInstanceCall(); | |
| 2795 if (!call->HasICData()) { | |
| 2796 const Array& arguments_descriptor = Array::Handle( | |
| 2797 zone, ArgumentsDescriptor::New(call->ArgumentCount(), | |
| 2798 call->argument_names())); | |
| 2799 const ICData& ic_data = ICData::ZoneHandle( | |
| 2800 zone, ICData::New(function, call->function_name(), | |
| 2801 arguments_descriptor, call->deopt_id(), | |
| 2802 call->checked_argument_count(), false)); | |
| 2803 call->set_ic_data(&ic_data); | |
| 2804 } | |
| 2805 } else if (instr->IsStaticCall()) { | |
| 2806 StaticCallInstr* call = instr->AsStaticCall(); | |
| 2807 if (!call->HasICData()) { | |
| 2808 const Array& arguments_descriptor = Array::Handle( | |
| 2809 zone, ArgumentsDescriptor::New(call->ArgumentCount(), | |
| 2810 call->argument_names())); | |
| 2811 const Function& target = call->function(); | |
| 2812 MethodRecognizer::Kind recognized_kind = | |
| 2813 MethodRecognizer::RecognizeKind(target); | |
| 2814 int num_args_checked = 0; | |
| 2815 switch (recognized_kind) { | |
| 2816 case MethodRecognizer::kDoubleFromInteger: | |
| 2817 case MethodRecognizer::kMathMin: | |
| 2818 case MethodRecognizer::kMathMax: | |
| 2819 num_args_checked = 2; | |
| 2820 break; | |
| 2821 default: | |
| 2822 break; | |
| 2823 } | |
| 2824 const ICData& ic_data = ICData::ZoneHandle( | |
| 2825 zone, ICData::New(function, String::Handle(target.name()), | |
|
Florian Schneider
2016/12/15 19:09:35
Pass zone into String::Handle as well.
rmacnak
2016/12/15 21:27:19
Done.
| |
| 2826 arguments_descriptor, call->deopt_id(), | |
| 2827 num_args_checked, true)); | |
| 2828 ic_data.AddTarget(target); | |
| 2829 call->set_ic_data(&ic_data); | |
| 2830 } | |
| 2831 } | |
| 2832 } | |
| 2833 } | |
| 2834 | |
| 2835 if (this == NULL) { | |
|
Florian Schneider
2016/12/15 19:09:35
Check this at the call-site to avoid C++ undefined
rmacnak
2016/12/15 21:27:19
Done.
| |
| 2836 return; | |
| 2837 } | |
| 2838 | |
| 2839 ParsedJSONObject* js_function = LookupFeedback(function); | |
| 2840 if (js_function == NULL) { | |
| 2841 if (FLAG_trace_precompiler) { | |
| 2842 THR_Print("No feedback available for %s\n", | |
| 2843 function.ToQualifiedCString()); | |
| 2844 } | |
| 2845 return; | |
| 2846 } | |
| 2847 | |
| 2848 ParsedJSONArray* js_icdatas = js_function->ArrayAt("ics"); | |
| 2849 ASSERT(js_icdatas != NULL); | |
| 2850 | |
| 2851 for (BlockIterator block_it = graph->reverse_postorder_iterator(); | |
| 2852 !block_it.Done(); block_it.Advance()) { | |
| 2853 ForwardInstructionIterator it(block_it.Current()); | |
| 2854 for (; !it.Done(); it.Advance()) { | |
| 2855 Instruction* instr = it.Current(); | |
| 2856 if (instr->IsInstanceCall()) { | |
| 2857 InstanceCallInstr* call = instr->AsInstanceCall(); | |
| 2858 TryApplyFeedback(js_icdatas, *call->ic_data()); | |
| 2859 } else if (instr->IsStaticCall()) { | |
| 2860 StaticCallInstr* call = instr->AsStaticCall(); | |
| 2861 TryApplyFeedback(js_icdatas, *call->ic_data()); | |
| 2862 } | |
| 2863 } | |
| 2864 } | |
| 2865 } | |
| 2866 | |
| 2867 | |
| 2868 void Precompiler::TryApplyFeedback(ParsedJSONArray* js_icdatas, | |
| 2869 const ICData& ic) { | |
| 2870 for (intptr_t j = 0; j < js_icdatas->Length(); j++) { | |
| 2871 ParsedJSONObject* js_icdata = js_icdatas->ObjectAt(j); | |
| 2872 ASSERT(js_icdata != NULL); | |
| 2873 | |
| 2874 ParsedJSONNumber* js_deoptid = js_icdata->NumberAt("deoptId"); | |
| 2875 ASSERT(js_deoptid != NULL); | |
| 2876 if (js_deoptid->value() != ic.deopt_id()) continue; | |
| 2877 | |
| 2878 ParsedJSONBoolean* js_isstaticcall = js_icdata->BooleanAt("isStaticCall"); | |
| 2879 ASSERT(js_isstaticcall != NULL); | |
| 2880 if (js_isstaticcall->value() != ic.is_static_call()) return; | |
| 2881 | |
| 2882 ParsedJSONNumber* js_argsTested = js_icdata->NumberAt("argsTested"); | |
| 2883 ASSERT(js_argsTested != NULL); | |
| 2884 if (js_argsTested->value() != ic.NumArgsTested()) return; | |
| 2885 | |
| 2886 ParsedJSONString* js_selector = js_icdata->StringAt("selector"); | |
| 2887 ASSERT(js_selector != NULL); | |
| 2888 const String& feedback_selector = | |
| 2889 String::Handle(String::New(js_selector->value())); | |
| 2890 const String& selector = String::Handle(ic.target_name()); | |
| 2891 // N.B.: EqualsIgnoringPrivateKey is not symmetric. | |
| 2892 if (!String::EqualsIgnoringPrivateKey(selector, feedback_selector)) return; | |
| 2893 | |
| 2894 ParsedJSONArray* js_entries = js_icdata->ArrayAt("entries"); | |
| 2895 ASSERT(js_entries != NULL); | |
| 2896 if (ic.is_static_call()) { | |
| 2897 // [cid [cid]] target count | |
| 2898 ParsedJSONNumber* entry = js_entries->NumberAt(js_entries->Length() - 1); | |
| 2899 ASSERT(entry != NULL); | |
| 2900 ic.SetCountAt(0, entry->value()); | |
| 2901 } else { | |
| 2902 // [cid [cid [cid]]] target count | |
| 2903 const Array& arguments_descriptor = | |
| 2904 Array::Handle(ic.arguments_descriptor()); | |
| 2905 ArgumentsDescriptor args_desc(arguments_descriptor); | |
| 2906 | |
| 2907 intptr_t kNumArgsChecked = ic.NumArgsTested(); | |
|
Florian Schneider
2016/12/15 19:09:35
Not really a compile-time constant:
s/kNumArgsChe
rmacnak
2016/12/15 21:27:19
Done.
| |
| 2908 for (intptr_t k = 0; k < js_entries->Length(); k += kNumArgsChecked + 1) { | |
| 2909 GrowableArray<intptr_t> class_ids(kNumArgsChecked); | |
| 2910 for (intptr_t arg = 0; arg < kNumArgsChecked; arg++) { | |
| 2911 ParsedJSONNumber* entry = js_entries->NumberAt(k + arg); | |
| 2912 ASSERT(entry != NULL); | |
| 2913 class_ids.Add(MapCid(entry->value())); | |
| 2914 } | |
| 2915 ParsedJSONNumber* entry = js_entries->NumberAt(k + kNumArgsChecked); | |
| 2916 ASSERT(entry != NULL); | |
| 2917 intptr_t count = entry->value(); | |
| 2918 | |
| 2919 bool has_missing_cid = false; | |
| 2920 for (intptr_t arg = 0; arg < kNumArgsChecked; arg++) { | |
| 2921 if (class_ids[arg] == kIllegalCid) { | |
| 2922 has_missing_cid = true; | |
| 2923 } | |
| 2924 } | |
| 2925 if (has_missing_cid) continue; | |
| 2926 | |
| 2927 intptr_t receiver_cid = class_ids[0]; | |
| 2928 const Class& receiver_cls = | |
| 2929 Class::Handle(I->class_table()->At(receiver_cid)); | |
| 2930 if (receiver_cls.IsClass()) { | |
| 2931 const Function& target = | |
| 2932 Function::Handle(Resolver::ResolveDynamicForReceiverClass( | |
| 2933 receiver_cls, selector, args_desc, false)); | |
| 2934 if (!target.IsNull()) { | |
| 2935 if (kNumArgsChecked == 1) { | |
| 2936 ic.AddReceiverCheck(receiver_cid, target, count); | |
| 2937 } else { | |
| 2938 ic.AddCheck(class_ids, target, count); | |
| 2939 } | |
| 2940 } | |
| 2941 } | |
| 2942 } | |
| 2943 } | |
| 2944 | |
| 2945 return; | |
| 2946 } | |
| 2947 } | |
| 2948 | |
| 2949 | |
| 2610 void Precompiler::ResetPrecompilerState() { | 2950 void Precompiler::ResetPrecompilerState() { |
| 2611 changed_ = false; | 2951 changed_ = false; |
| 2612 function_count_ = 0; | 2952 function_count_ = 0; |
| 2613 class_count_ = 0; | 2953 class_count_ = 0; |
| 2614 selector_count_ = 0; | 2954 selector_count_ = 0; |
| 2615 dropped_function_count_ = 0; | 2955 dropped_function_count_ = 0; |
| 2616 dropped_field_count_ = 0; | 2956 dropped_field_count_ = 0; |
| 2617 ASSERT(pending_functions_.Length() == 0); | 2957 ASSERT(pending_functions_.Length() == 0); |
| 2618 sent_selectors_.Clear(); | 2958 sent_selectors_.Clear(); |
| 2619 enqueued_functions_.Clear(); | 2959 enqueued_functions_.Clear(); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2749 ZoneGrowableArray<const ICData*>* ic_data_array = | 3089 ZoneGrowableArray<const ICData*>* ic_data_array = |
| 2750 new (zone) ZoneGrowableArray<const ICData*>(); | 3090 new (zone) ZoneGrowableArray<const ICData*>(); |
| 2751 #ifndef PRODUCT | 3091 #ifndef PRODUCT |
| 2752 TimelineDurationScope tds(thread(), compiler_timeline, | 3092 TimelineDurationScope tds(thread(), compiler_timeline, |
| 2753 "BuildFlowGraph"); | 3093 "BuildFlowGraph"); |
| 2754 #endif // !PRODUCT | 3094 #endif // !PRODUCT |
| 2755 flow_graph = pipeline->BuildFlowGraph( | 3095 flow_graph = pipeline->BuildFlowGraph( |
| 2756 zone, parsed_function(), *ic_data_array, Compiler::kNoOSRDeoptId); | 3096 zone, parsed_function(), *ic_data_array, Compiler::kNoOSRDeoptId); |
| 2757 } | 3097 } |
| 2758 | 3098 |
| 3099 if (optimized()) { | |
| 3100 precompiler_->PopulateWithICData(parsed_function()->function(), | |
| 3101 flow_graph); | |
| 3102 } | |
| 3103 | |
| 2759 const bool print_flow_graph = | 3104 const bool print_flow_graph = |
| 2760 (FLAG_print_flow_graph || | 3105 (FLAG_print_flow_graph || |
| 2761 (optimized() && FLAG_print_flow_graph_optimized)) && | 3106 (optimized() && FLAG_print_flow_graph_optimized)) && |
| 2762 FlowGraphPrinter::ShouldPrint(function); | 3107 FlowGraphPrinter::ShouldPrint(function); |
| 2763 | 3108 |
| 2764 if (print_flow_graph) { | 3109 if (print_flow_graph) { |
| 2765 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | 3110 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
| 2766 } | 3111 } |
| 2767 | 3112 |
| 2768 if (optimized()) { | 3113 if (optimized()) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 2799 // is that the length of |inline_id_to_function| is always larger | 3144 // is that the length of |inline_id_to_function| is always larger |
| 2800 // than the length of |inline_id_to_token_pos| by one. | 3145 // than the length of |inline_id_to_token_pos| by one. |
| 2801 // Top scope function has no caller (-1). We do this because we expect | 3146 // Top scope function has no caller (-1). We do this because we expect |
| 2802 // all token positions to be at an inlined call. | 3147 // all token positions to be at an inlined call. |
| 2803 // Top scope function has no caller (-1). | 3148 // Top scope function has no caller (-1). |
| 2804 caller_inline_id.Add(-1); | 3149 caller_inline_id.Add(-1); |
| 2805 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); | 3150 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); |
| 2806 | 3151 |
| 2807 AotOptimizer optimizer(precompiler_, flow_graph, | 3152 AotOptimizer optimizer(precompiler_, flow_graph, |
| 2808 use_speculative_inlining, &inlining_black_list); | 3153 use_speculative_inlining, &inlining_black_list); |
| 2809 optimizer.PopulateWithICData(); | |
| 2810 | 3154 |
| 2811 optimizer.ApplyClassIds(); | 3155 optimizer.ApplyClassIds(); |
| 2812 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3156 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 2813 | 3157 |
| 2814 FlowGraphTypePropagator::Propagate(flow_graph); | 3158 FlowGraphTypePropagator::Propagate(flow_graph); |
| 2815 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3159 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 2816 | 3160 |
| 2817 optimizer.ApplyICData(); | 3161 optimizer.ApplyICData(); |
| 2818 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 3162 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 2819 | 3163 |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3298 | 3642 |
| 3299 ASSERT(FLAG_precompiled_mode); | 3643 ASSERT(FLAG_precompiled_mode); |
| 3300 const bool optimized = function.IsOptimizable(); // False for natives. | 3644 const bool optimized = function.IsOptimizable(); // False for natives. |
| 3301 DartPrecompilationPipeline pipeline(zone, field_type_map); | 3645 DartPrecompilationPipeline pipeline(zone, field_type_map); |
| 3302 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); | 3646 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); |
| 3303 } | 3647 } |
| 3304 | 3648 |
| 3305 #endif // DART_PRECOMPILER | 3649 #endif // DART_PRECOMPILER |
| 3306 | 3650 |
| 3307 } // namespace dart | 3651 } // namespace dart |
| OLD | NEW |