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/compiler.h" | 7 #include "vm/compiler.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/longjump.h" | 9 #include "vm/longjump.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 42 } | 42 } |
| 43 | 43 |
| 44 | 44 |
| 45 Precompiler::Precompiler(Thread* thread) : | 45 Precompiler::Precompiler(Thread* thread) : |
| 46 thread_(thread), | 46 thread_(thread), |
| 47 zone_(thread->zone()), | 47 zone_(thread->zone()), |
| 48 isolate_(thread->isolate()), | 48 isolate_(thread->isolate()), |
| 49 changed_(false), | 49 changed_(false), |
| 50 function_count_(0), | 50 function_count_(0), |
| 51 class_count_(0), | 51 class_count_(0), |
| 52 selector_count_(0), | |
| 53 dropped_function_count_(0), | |
| 52 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), | 54 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), |
| 53 pending_functions_(GrowableObjectArray::Handle(Z, | 55 pending_functions_(GrowableObjectArray::Handle(Z, |
| 54 GrowableObjectArray::New())), | 56 GrowableObjectArray::New())), |
| 55 collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())), | 57 collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())), |
| 56 sent_selectors_(GrowableObjectArray::Handle(Z, GrowableObjectArray::New())), | 58 sent_selectors_(Z), |
| 57 error_(Error::Handle(Z)) { | 59 error_(Error::Handle(Z)) { |
| 58 } | 60 } |
| 59 | 61 |
| 60 | 62 |
| 61 void Precompiler::DoCompileAll() { | 63 void Precompiler::DoCompileAll() { |
| 62 // Drop all existing code so we can use the presence of code as an indicator | 64 // Drop all existing code so we can use the presence of code as an indicator |
| 63 // that we have already looked for the function's callees. | 65 // that we have already looked for the function's callees. |
| 64 ClearAllCode(); | 66 ClearAllCode(); |
| 65 | 67 |
| 66 // Start with the allocations and invocations that happen from C++. | 68 // Start with the allocations and invocations that happen from C++. |
| 67 AddRoots(); | 69 AddRoots(); |
| 68 | 70 |
| 69 // TODO(rmacnak): Eagerly add field-invocation functions to all signature | 71 // TODO(rmacnak): Eagerly add field-invocation functions to all signature |
| 70 // classes so closure calls don't go through the runtime. | 72 // classes so closure calls don't go through the runtime. |
| 71 | 73 |
| 72 // Compile newly found targets and add their callees until we reach a fixed | 74 // Compile newly found targets and add their callees until we reach a fixed |
| 73 // point. | 75 // point. |
| 74 Iterate(); | 76 Iterate(); |
| 75 | 77 |
| 76 CleanUp(); | 78 CleanUp(); |
| 77 | 79 |
| 78 if (FLAG_trace_precompiler) { | 80 if (FLAG_trace_precompiler) { |
| 79 OS::Print("Precompiled %" Pd " functions, %" Pd " dynamic types," | 81 OS::Print("Precompiled %" Pd " functions, %" Pd " dynamic types," |
| 80 " %" Pd " dynamic selectors\n", | 82 " %" Pd " dynamic selectors\n", |
| 81 function_count_, | 83 function_count_, |
| 82 class_count_, | 84 class_count_, |
| 83 sent_selectors_.Length()); | 85 selector_count_); |
| 86 OS::Print("Dropped %" Pd " functions\n", | |
| 87 dropped_function_count_); | |
|
srdjan
2015/08/05 18:20:08
ISL_Print
Cutch
2015/08/05 18:25:05
DBC: You may also want to put a:
LogBlock lb(Thre
rmacnak
2015/08/05 19:51:50
Done.
| |
| 84 } | 88 } |
| 85 | 89 |
| 86 I->set_compilation_allowed(false); | 90 I->set_compilation_allowed(false); |
| 87 } | 91 } |
| 88 | 92 |
| 89 | 93 |
| 90 void Precompiler::ClearAllCode() { | 94 void Precompiler::ClearAllCode() { |
| 91 Library& lib = Library::Handle(Z); | 95 Library& lib = Library::Handle(Z); |
| 92 Class& cls = Class::Handle(Z); | 96 Class& cls = Class::Handle(Z); |
| 93 Array& functions = Array::Handle(Z); | 97 Array& functions = Array::Handle(Z); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 326 function ^= collected_closures_.RemoveLast(); | 330 function ^= collected_closures_.RemoveLast(); |
| 327 ProcessFunction(function); | 331 ProcessFunction(function); |
| 328 } | 332 } |
| 329 } | 333 } |
| 330 } | 334 } |
| 331 | 335 |
| 332 | 336 |
| 333 void Precompiler::CleanUp() { | 337 void Precompiler::CleanUp() { |
| 334 I->set_collected_closures(GrowableObjectArray::Handle(Z)); | 338 I->set_collected_closures(GrowableObjectArray::Handle(Z)); |
| 335 | 339 |
| 336 // TODO(rmacnak): Drop functions without code, classes without functions, etc. | 340 DropUncompiledFunctions(); |
| 341 | |
| 342 // TODO(rmacnak): DropEmptyClasses(); | |
| 337 } | 343 } |
| 338 | 344 |
| 339 | 345 |
| 340 void Precompiler::ProcessFunction(const Function& function) { | 346 void Precompiler::ProcessFunction(const Function& function) { |
| 341 if (!function.HasCode()) { | 347 if (!function.HasCode()) { |
| 342 function_count_++; | 348 function_count_++; |
| 343 | 349 |
| 344 if (FLAG_trace_precompiler) { | 350 if (FLAG_trace_precompiler) { |
| 345 OS::Print("Precompiling %" Pd " %s (%" Pd ", %s)\n", | 351 OS::Print("Precompiling %" Pd " %s (%" Pd ", %s)\n", |
| 346 function_count_, | 352 function_count_, |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 447 | 453 |
| 448 void Precompiler::AddFunction(const Function& function) { | 454 void Precompiler::AddFunction(const Function& function) { |
| 449 if (function.HasCode()) return; | 455 if (function.HasCode()) return; |
| 450 | 456 |
| 451 pending_functions_.Add(function); | 457 pending_functions_.Add(function); |
| 452 changed_ = true; | 458 changed_ = true; |
| 453 } | 459 } |
| 454 | 460 |
| 455 | 461 |
| 456 bool Precompiler::IsSent(const String& selector) { | 462 bool Precompiler::IsSent(const String& selector) { |
| 457 ASSERT(selector.IsSymbol()); | 463 return sent_selectors_.Includes(selector); |
| 458 | |
| 459 // TODO(rmacnak): Use a proper set. | |
| 460 for (intptr_t i = 0; i < sent_selectors_.Length(); i++) { | |
| 461 if (sent_selectors_.At(i) == selector.raw()) { | |
| 462 return true; | |
| 463 } | |
| 464 } | |
| 465 | |
| 466 return false; | |
| 467 } | 464 } |
| 468 | 465 |
| 469 | 466 |
| 470 void Precompiler::AddSelector(const String& selector) { | 467 void Precompiler::AddSelector(const String& selector) { |
| 471 if (!IsSent(selector)) { | 468 if (!IsSent(selector)) { |
| 469 sent_selectors_.Add(selector); | |
| 470 selector_count_++; | |
| 471 changed_ = true; | |
| 472 | |
| 472 if (FLAG_trace_precompiler) { | 473 if (FLAG_trace_precompiler) { |
| 473 OS::Print("Enqueueing selector %" Pd " %s\n", | 474 OS::Print("Enqueueing selector %" Pd " %s\n", |
| 474 sent_selectors_.Length(), | 475 selector_count_, |
| 475 selector.ToCString()); | 476 selector.ToCString()); |
| 476 } | 477 } |
| 477 | 478 |
| 478 sent_selectors_.Add(selector); | |
| 479 changed_ = true; | |
| 480 | |
| 481 if (!Field::IsGetterName(selector) && | 479 if (!Field::IsGetterName(selector) && |
| 482 !Field::IsSetterName(selector)) { | 480 !Field::IsSetterName(selector)) { |
| 483 // Regular method may be call-through-getter. | 481 // Regular method may be call-through-getter. |
| 484 // TODO(rmacnak): Do not create the symbol if it does not already exist. | 482 const String& getter = String::Handle(Field::GetterSymbol(selector)); |
|
rmacnak
2015/08/05 18:11:54
Turns out the vast majority of these selectors alr
| |
| 485 String& getter = String::Handle(Field::GetterName(selector)); | |
| 486 getter = Symbols::New(getter); | |
| 487 AddSelector(getter); | 483 AddSelector(getter); |
| 488 } | 484 } |
| 489 } | 485 } |
| 490 } | 486 } |
| 491 | 487 |
| 492 | 488 |
| 493 void Precompiler::AddClass(const Class& cls) { | 489 void Precompiler::AddClass(const Class& cls) { |
| 494 if (cls.is_allocated()) return; | 490 if (cls.is_allocated()) return; |
| 495 | 491 |
| 496 class_count_++; | 492 class_count_++; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 // if (function.HasCode()) continue; | 566 // if (function.HasCode()) continue; |
| 571 | 567 |
| 572 selector = function.name(); | 568 selector = function.name(); |
| 573 if (IsSent(selector)) { | 569 if (IsSent(selector)) { |
| 574 AddFunction(function); | 570 AddFunction(function); |
| 575 } | 571 } |
| 576 | 572 |
| 577 if (function.kind() == RawFunction::kRegularFunction && | 573 if (function.kind() == RawFunction::kRegularFunction && |
| 578 !Field::IsGetterName(selector) && | 574 !Field::IsGetterName(selector) && |
| 579 !Field::IsSetterName(selector)) { | 575 !Field::IsSetterName(selector)) { |
| 580 // TODO(rmacnak): Do not create the symbol if it does not already | 576 selector = Field::GetterSymbol(selector); |
| 581 // exist. | |
| 582 selector = Field::GetterName(selector); | |
| 583 selector = Symbols::New(selector); | |
| 584 if (IsSent(selector)) { | 577 if (IsSent(selector)) { |
| 585 function = function.ImplicitClosureFunction(); | 578 function = function.ImplicitClosureFunction(); |
| 586 AddFunction(function); | 579 AddFunction(function); |
| 587 } | 580 } |
| 588 } | 581 } |
| 589 } | 582 } |
| 590 } | 583 } |
| 591 } | 584 } |
| 592 } | 585 } |
| 593 | 586 |
| 587 | |
| 588 void Precompiler::DropUncompiledFunctions() { | |
| 589 Library& lib = Library::Handle(Z); | |
| 590 Class& cls = Class::Handle(Z); | |
| 591 Array& functions = Array::Handle(Z); | |
| 592 Function& function = Function::Handle(Z); | |
| 593 GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z); | |
| 594 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); | |
| 595 | |
| 596 for (intptr_t i = 0; i < libraries_.Length(); i++) { | |
| 597 lib ^= libraries_.At(i); | |
| 598 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); | |
| 599 while (it.HasNext()) { | |
| 600 cls = it.GetNextClass(); | |
| 601 if (cls.IsDynamicClass()) { | |
| 602 continue; // class 'dynamic' is in the read-only VM isolate. | |
| 603 } | |
| 604 | |
| 605 functions = cls.functions(); | |
| 606 retained_functions = GrowableObjectArray::New(); | |
| 607 for (intptr_t j = 0; j < functions.Length(); j++) { | |
| 608 function ^= functions.At(j); | |
| 609 if (function.HasCode()) { | |
| 610 retained_functions.Add(function); | |
| 611 } else { | |
| 612 dropped_function_count_++; | |
| 613 if (FLAG_trace_precompiler) { | |
| 614 OS::Print("Precompilation dropping %s\n", | |
|
srdjan
2015/08/05 18:20:08
ISL_Print
| |
| 615 function.ToLibNamePrefixedQualifiedCString()); | |
| 616 } | |
| 617 } | |
| 618 } | |
| 619 | |
| 620 functions = Array::New(retained_functions.Length(), Heap::kOld); | |
| 621 for (intptr_t j = 0; j < retained_functions.Length(); j++) { | |
| 622 function ^= retained_functions.At(j); | |
| 623 functions.SetAt(j, function); | |
| 624 } | |
| 625 cls.SetFunctions(functions); | |
| 626 | |
| 627 closures = cls.closures(); | |
| 628 if (!closures.IsNull()) { | |
| 629 for (intptr_t j = 0; j < closures.Length(); j++) { | |
| 630 function ^= closures.At(j); | |
| 631 ASSERT(function.HasCode()); | |
| 632 } | |
| 633 } | |
| 634 } | |
| 635 } | |
| 636 } | |
| 637 | |
| 594 } // namespace dart | 638 } // namespace dart |
| OLD | NEW |