Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Side by Side Diff: runtime/vm/precompiler.cc

Issue 1275653002: Tree-shaking: use a hash set for tracking live selectors, drop uncompiled functions. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« runtime/vm/precompiler.h ('K') | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« runtime/vm/precompiler.h ('K') | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698