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

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

Issue 1387613003: Dedup stackmaps. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 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
« no previous file with comments | « 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/code_patcher.h" 7 #include "vm/code_patcher.h"
8 #include "vm/compiler.h" 8 #include "vm/compiler.h"
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/log.h" 10 #include "vm/log.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 reset_fields_(reset_fields), 53 reset_fields_(reset_fields),
54 changed_(false), 54 changed_(false),
55 function_count_(0), 55 function_count_(0),
56 class_count_(0), 56 class_count_(0),
57 selector_count_(0), 57 selector_count_(0),
58 dropped_function_count_(0), 58 dropped_function_count_(0),
59 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())), 59 libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())),
60 pending_functions_(GrowableObjectArray::Handle(Z, 60 pending_functions_(GrowableObjectArray::Handle(Z,
61 GrowableObjectArray::New())), 61 GrowableObjectArray::New())),
62 collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())), 62 collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())),
63 sent_selectors_(Z), 63 sent_selectors_(),
64 error_(Error::Handle(Z)) { 64 error_(Error::Handle(Z)) {
65 } 65 }
66 66
67 67
68 void Precompiler::DoCompileAll( 68 void Precompiler::DoCompileAll(
69 Dart_QualifiedFunctionName embedder_entry_points[]) { 69 Dart_QualifiedFunctionName embedder_entry_points[]) {
70 // Drop all existing code so we can use the presence of code as an indicator 70 // Drop all existing code so we can use the presence of code as an indicator
71 // that we have already looked for the function's callees. 71 // that we have already looked for the function's callees.
72 ClearAllCode(); 72 ClearAllCode();
73 73
(...skipping 16 matching lines...) Expand all
90 class_count_, 90 class_count_,
91 selector_count_, 91 selector_count_,
92 dropped_function_count_); 92 dropped_function_count_);
93 } 93 }
94 94
95 I->set_compilation_allowed(false); 95 I->set_compilation_allowed(false);
96 } 96 }
97 97
98 98
99 void Precompiler::ClearAllCode() { 99 void Precompiler::ClearAllCode() {
100 Library& lib = Library::Handle(Z); 100 class CodeCodeFunctionVisitor : public FunctionVisitor {
101 Class& cls = Class::Handle(Z); 101 void VisitFunction(const Function& function) {
102 Array& functions = Array::Handle(Z); 102 function.ClearCode();
103 Function& function = Function::Handle(Z);
104
105 for (intptr_t i = 0; i < libraries_.Length(); i++) {
106 lib ^= libraries_.At(i);
107 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
108 while (it.HasNext()) {
109 cls = it.GetNextClass();
110 error_ = cls.EnsureIsFinalized(thread_);
111 if (!error_.IsNull()) {
112 Jump(error_);
113 }
114 } 103 }
115 } 104 };
116 105 CodeCodeFunctionVisitor visitor;
117 for (intptr_t i = 0; i < libraries_.Length(); i++) { 106 VisitFunctions(&visitor);
118 lib ^= libraries_.At(i);
119 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
120 while (it.HasNext()) {
121 cls = it.GetNextClass();
122 functions = cls.functions();
123 for (intptr_t i = 0; i < functions.Length(); i++) {
124 function ^= functions.At(i);
125 function.ClearCode();
126 }
127 }
128 }
129 } 107 }
130 108
131 109
132 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { 110 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) {
133 // Note that <rootlibrary>.main is not a root. The appropriate main will be 111 // Note that <rootlibrary>.main is not a root. The appropriate main will be
134 // discovered through _getMainClosure. 112 // discovered through _getMainClosure.
135 113
136 AddSelector(Symbols::NoSuchMethod()); 114 AddSelector(Symbols::NoSuchMethod());
137 115
138 AddSelector(Symbols::Call()); // For speed, not correctness. 116 AddSelector(Symbols::Call()); // For speed, not correctness.
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 302
325 303
326 void Precompiler::CleanUp() { 304 void Precompiler::CleanUp() {
327 I->set_collected_closures(GrowableObjectArray::Handle(Z)); 305 I->set_collected_closures(GrowableObjectArray::Handle(Z));
328 306
329 DropUncompiledFunctions(); 307 DropUncompiledFunctions();
330 308
331 // TODO(rmacnak): DropEmptyClasses(); 309 // TODO(rmacnak): DropEmptyClasses();
332 310
333 BindStaticCalls(); 311 BindStaticCalls();
312
313 DedupStackmaps();
334 } 314 }
335 315
336 316
337 void Precompiler::ProcessFunction(const Function& function) { 317 void Precompiler::ProcessFunction(const Function& function) {
338 if (!function.HasCode()) { 318 if (!function.HasCode()) {
339 function_count_++; 319 function_count_++;
340 320
341 if (FLAG_trace_precompiler) { 321 if (FLAG_trace_precompiler) {
342 THR_Print("Precompiling %" Pd " %s (%" Pd ", %s)\n", 322 THR_Print("Precompiling %" Pd " %s (%" Pd ", %s)\n",
343 function_count_, 323 function_count_,
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 456
477 pending_functions_.Add(function); 457 pending_functions_.Add(function);
478 changed_ = true; 458 changed_ = true;
479 } 459 }
480 460
481 461
482 bool Precompiler::IsSent(const String& selector) { 462 bool Precompiler::IsSent(const String& selector) {
483 if (selector.IsNull()) { 463 if (selector.IsNull()) {
484 return false; 464 return false;
485 } 465 }
486 return sent_selectors_.Includes(selector); 466 return sent_selectors_.Lookup(&selector) != NULL;
487 } 467 }
488 468
489 469
490 void Precompiler::AddSelector(const String& selector) { 470 void Precompiler::AddSelector(const String& selector) {
491 ASSERT(!selector.IsNull()); 471 ASSERT(!selector.IsNull());
492 472
493 if (!IsSent(selector)) { 473 if (!IsSent(selector)) {
494 sent_selectors_.Add(selector); 474 sent_selectors_.Insert(&String::ZoneHandle(Z, selector.raw()));
495 selector_count_++; 475 selector_count_++;
496 changed_ = true; 476 changed_ = true;
497 477
498 if (FLAG_trace_precompiler) { 478 if (FLAG_trace_precompiler) {
499 THR_Print("Enqueueing selector %" Pd " %s\n", 479 THR_Print("Enqueueing selector %" Pd " %s\n",
500 selector_count_, 480 selector_count_,
501 selector.ToCString()); 481 selector.ToCString());
502 } 482 }
503 } 483 }
504 } 484 }
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 function ^= closures.At(j); 669 function ^= closures.At(j);
690 ASSERT(function.HasCode()); 670 ASSERT(function.HasCode());
691 } 671 }
692 } 672 }
693 } 673 }
694 } 674 }
695 } 675 }
696 676
697 677
698 void Precompiler::BindStaticCalls() { 678 void Precompiler::BindStaticCalls() {
679 class BindStaticCallsVisitor : public FunctionVisitor {
680 public:
681 explicit BindStaticCallsVisitor(Zone* zone) :
682 code_(Code::Handle(zone)),
683 table_(Array::Handle(zone)),
684 pc_offset_(Smi::Handle(zone)),
685 target_(Function::Handle(zone)),
686 target_code_(Code::Handle(zone)) {
687 }
688
689 void VisitFunction(const Function& function) {
690 ASSERT(function.HasCode());
691 code_ = function.CurrentCode();
692 table_ = code_.static_calls_target_table();
693
694 for (intptr_t i = 0;
695 i < table_.Length();
696 i += Code::kSCallTableEntryLength) {
697 pc_offset_ ^= table_.At(i + Code::kSCallTableOffsetEntry);
698 target_ ^= table_.At(i + Code::kSCallTableFunctionEntry);
699 if (target_.IsNull()) {
700 target_code_ ^= table_.At(i + Code::kSCallTableCodeEntry);
701 ASSERT(!target_code_.IsNull());
702 ASSERT(!target_code_.IsFunctionCode());
703 // Allocation stub or AllocateContext or AllocateArray or ...
704 } else {
705 // Static calls initially call the CallStaticFunction stub because
706 // their target might not be compiled yet. After tree shaking, all
707 // static call targets are compiled.
708 // Cf. runtime entry PatchStaticCall called from CallStaticFunction
709 // stub.
710 ASSERT(target_.HasCode());
711 target_code_ ^= target_.CurrentCode();
712 uword pc = pc_offset_.Value() + code_.EntryPoint();
713 CodePatcher::PatchStaticCallAt(pc, code_, target_code_);
714 }
715 }
716
717 // We won't patch static calls anymore, so drop the static call table to
718 // save space.
719 code_.set_static_calls_target_table(Object::empty_array());
720 }
721
722 private:
723 Code& code_;
724 Array& table_;
725 Smi& pc_offset_;
726 Function& target_;
727 Code& target_code_;
728 };
729
730 BindStaticCallsVisitor visitor(Z);
731 VisitFunctions(&visitor);
732 }
733
734
735 void Precompiler::DedupStackmaps() {
736 class DedupStackmapsVisitor : public FunctionVisitor {
737 public:
738 explicit DedupStackmapsVisitor(Zone* zone) :
739 zone_(zone),
740 canonical_stackmaps_(),
741 code_(Code::Handle(zone)),
742 stackmaps_(Array::Handle(zone)),
743 stackmap_(Stackmap::Handle(zone)) {
744 }
745
746 void VisitFunction(const Function& function) {
747 code_ = function.CurrentCode();
748 stackmaps_ = code_.stackmaps();
749 if (stackmaps_.IsNull()) return;
750 for (intptr_t i = 0; i < stackmaps_.Length(); i++) {
751 stackmap_ ^= stackmaps_.At(i);
752 stackmap_ = DedupStackmap(stackmap_);
753 stackmaps_.SetAt(i, stackmap_);
754 }
755 }
756
757 RawStackmap* DedupStackmap(const Stackmap& stackmap) {
758 const Stackmap* canonical_stackmap =
759 canonical_stackmaps_.Lookup(&stackmap);
760 if (canonical_stackmap == NULL) {
761 canonical_stackmaps_.Insert(
762 &Stackmap::ZoneHandle(zone_, stackmap.raw()));
763 return stackmap.raw();
764 } else {
765 return canonical_stackmap->raw();
766 }
767 }
768
769 private:
770 Zone* zone_;
771 StackmapSet canonical_stackmaps_;
772 Code& code_;
773 Array& stackmaps_;
774 Stackmap& stackmap_;
775 };
776
777 DedupStackmapsVisitor visitor(Z);
778 VisitFunctions(&visitor);
779 }
780
781
782 void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
699 Library& lib = Library::Handle(Z); 783 Library& lib = Library::Handle(Z);
700 Class& cls = Class::Handle(Z); 784 Class& cls = Class::Handle(Z);
701 Array& functions = Array::Handle(Z); 785 Array& functions = Array::Handle(Z);
702 Function& function = Function::Handle(Z); 786 Function& function = Function::Handle(Z);
703 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); 787 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
704 788
705 for (intptr_t i = 0; i < libraries_.Length(); i++) { 789 for (intptr_t i = 0; i < libraries_.Length(); i++) {
706 lib ^= libraries_.At(i); 790 lib ^= libraries_.At(i);
707 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); 791 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
708 while (it.HasNext()) { 792 while (it.HasNext()) {
709 cls = it.GetNextClass(); 793 cls = it.GetNextClass();
710 if (cls.IsDynamicClass()) { 794 if (cls.IsDynamicClass()) {
711 continue; // class 'dynamic' is in the read-only VM isolate. 795 continue; // class 'dynamic' is in the read-only VM isolate.
712 } 796 }
713 797
714 functions = cls.functions(); 798 functions = cls.functions();
715 for (intptr_t j = 0; j < functions.Length(); j++) { 799 for (intptr_t j = 0; j < functions.Length(); j++) {
716 function ^= functions.At(j); 800 function ^= functions.At(j);
717 BindStaticCalls(function); 801 visitor->VisitFunction(function);
718 } 802 }
719 803
720 closures = cls.closures(); 804 closures = cls.closures();
721 if (!closures.IsNull()) { 805 if (!closures.IsNull()) {
722 for (intptr_t j = 0; j < closures.Length(); j++) { 806 for (intptr_t j = 0; j < closures.Length(); j++) {
723 function ^= closures.At(j); 807 function ^= closures.At(j);
724 BindStaticCalls(function); 808 visitor->VisitFunction(function);
725 } 809 }
726 } 810 }
727 } 811 }
728 } 812 }
729 } 813 }
730 814
731
732 void Precompiler::BindStaticCalls(const Function& function) {
733 ASSERT(function.HasCode());
734
735 const Code& code = Code::Handle(Z, function.CurrentCode());
736
737 const Array& table = Array::Handle(Z, code.static_calls_target_table());
738 Smi& pc_offset = Smi::Handle(Z);
739 Function& target = Function::Handle(Z);
740 Code& target_code = Code::Handle(Z);
741
742 for (intptr_t i = 0; i < table.Length(); i += Code::kSCallTableEntryLength) {
743 pc_offset ^= table.At(i + Code::kSCallTableOffsetEntry);
744 target ^= table.At(i + Code::kSCallTableFunctionEntry);
745 if (target.IsNull()) {
746 target_code ^= table.At(i + Code::kSCallTableCodeEntry);
747 ASSERT(!target_code.IsNull());
748 ASSERT(!target_code.IsFunctionCode());
749 // Allocation stub or AllocateContext or AllocateArray or ...
750 } else {
751 // Static calls initially call the CallStaticFunction stub because
752 // their target might not be compiled yet. After tree shaking, all
753 // static call targets are compiled.
754 // Cf. runtime entry PatchStaticCall called from CallStaticFunction stub.
755 ASSERT(target.HasCode());
756 target_code ^= target.CurrentCode();
757 CodePatcher::PatchStaticCallAt(pc_offset.Value() + code.EntryPoint(),
758 code, target_code);
759 }
760 }
761
762 // We won't patch static calls anymore, so drop the static call table to save
763 // space.
764 code.set_static_calls_target_table(Object::empty_array());
765 }
766
767 } // namespace dart 815 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698