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

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

Issue 1496713002: --collect_dynamic_function_names (default false): find unique virtual function names and use them t… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fixes Created 5 years 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/cha.h"
7 #include "vm/code_patcher.h" 8 #include "vm/code_patcher.h"
8 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/hash_table.h"
9 #include "vm/isolate.h" 11 #include "vm/isolate.h"
10 #include "vm/log.h" 12 #include "vm/log.h"
11 #include "vm/longjump.h" 13 #include "vm/longjump.h"
12 #include "vm/object.h" 14 #include "vm/object.h"
13 #include "vm/object_store.h" 15 #include "vm/object_store.h"
14 #include "vm/resolver.h" 16 #include "vm/resolver.h"
15 #include "vm/symbols.h" 17 #include "vm/symbols.h"
16 18
17 namespace dart { 19 namespace dart {
18 20
19 21
20 #define T (thread()) 22 #define T (thread())
21 #define I (isolate()) 23 #define I (isolate())
22 #define Z (zone()) 24 #define Z (zone())
23 25
24 26
27 DEFINE_FLAG(bool, collect_dynamic_function_names, false,
28 "In precompilation collects all dynamic function names in order to"
29 " identify unique targets");
30 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets");
25 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); 31 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler.");
26 32
27 33
28 static void Jump(const Error& error) { 34 static void Jump(const Error& error) {
29 Thread::Current()->long_jump_base()->Jump(1, error); 35 Thread::Current()->long_jump_base()->Jump(1, error);
30 } 36 }
31 37
32 38
33 RawError* Precompiler::CompileAll( 39 RawError* Precompiler::CompileAll(
34 Dart_QualifiedFunctionName embedder_entry_points[], 40 Dart_QualifiedFunctionName embedder_entry_points[],
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 // - field initializers 96 // - field initializers
91 // - invoke-field-dispatchers 97 // - invoke-field-dispatchers
92 // - method-extractors 98 // - method-extractors
93 // that are needed in early iterations but optimized away in later 99 // that are needed in early iterations but optimized away in later
94 // iterations. 100 // iterations.
95 ClearAllCode(); 101 ClearAllCode();
96 102
97 // Start with the allocations and invocations that happen from C++. 103 // Start with the allocations and invocations that happen from C++.
98 AddRoots(embedder_entry_points); 104 AddRoots(embedder_entry_points);
99 105
106 CollectDynamicFunctionNames();
rmacnak 2015/12/04 19:37:23 Nit: Move up to keep AddRoots and Iterate together
srdjan 2015/12/04 20:40:19 Done.
107
100 // Compile newly found targets and add their callees until we reach a fixed 108 // Compile newly found targets and add their callees until we reach a fixed
101 // point. 109 // point.
102 Iterate(); 110 Iterate();
103 } 111 }
104 112
105 DropUncompiledFunctions(); 113 DropUncompiledFunctions();
106 114
107 // TODO(rmacnak): DropEmptyClasses(); 115 // TODO(rmacnak): DropEmptyClasses();
108 116
109 BindStaticCalls(); 117 BindStaticCalls();
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 function2 = function.GetMethodExtractor(selector2); 709 function2 = function.GetMethodExtractor(selector2);
702 AddFunction(function2); 710 AddFunction(function2);
703 } 711 }
704 } 712 }
705 } 713 }
706 } 714 }
707 } 715 }
708 } 716 }
709 717
710 718
719 class NameFunctionsTraits {
720 public:
721 static bool IsMatch(const Object& a, const Object& b) {
722 return a.IsString() && b.IsString() &&
723 String::Cast(a).Equals(String::Cast(b));
724 }
725 static uword Hash(const Object& obj) {
726 return String::Cast(obj).Hash();
727 }
728 static RawObject* NewKey(const String& str) {
729 return str.raw();
730 }
731 };
732
733 typedef UnorderedHashMap<NameFunctionsTraits> Table;
734
735
736 class FunctionsTraits {
737 public:
738 static bool IsMatch(const Object& a, const Object& b) {
739 Zone* zone = Thread::Current()->zone();
740 String& a_s = String::Handle(zone);
741 String& b_s = String::Handle(zone);
742 a_s = a.IsFunction() ? Function::Cast(a).name() : String::Cast(a).raw();
743 b_s = b.IsFunction() ? Function::Cast(b).name() : String::Cast(b).raw();
744 ASSERT(a_s.IsSymbol() && b_s.IsSymbol());
745 return a_s.raw() == b_s.raw();
746 }
747 static uword Hash(const Object& obj) {
748 if (obj.IsFunction()) {
749 return String::Handle(Function::Cast(obj).name()).Hash();
750 } else {
751 ASSERT(String::Cast(obj).IsSymbol());
752 return String::Cast(obj).Hash();
753 }
754 }
755 static RawObject* NewKey(const Function& function) {
756 return function.raw();
757 }
758 };
759
760 typedef UnorderedHashSet<FunctionsTraits> UniqueFunctionsSet;
761
762
763 static void AddNameToFunctionsTable(Zone* zone,
764 Table* table,
765 const String& fname,
766 const Function& function) {
767 Array& farray = Array::Handle(zone);
768 farray ^= table->InsertNewOrGetValue(fname, Array::empty_array());
769 farray = Array::Grow(farray, farray.Length() + 1);
770 farray.SetAt(farray.Length() - 1, function);
771 table->UpdateValue(fname, farray);
772 }
773
774
775 void Precompiler::CollectDynamicFunctionNames() {
776 if (!FLAG_collect_dynamic_function_names) {
777 return;
778 }
779 Library& lib = Library::Handle(Z);
780 Class& cls = Class::Handle(Z);
781 Array& functions = Array::Handle(Z);
782 Function& function = Function::Handle(Z);
783 String& fname = String::Handle(Z);
784 Array& farray = Array::Handle(Z);
785
786 Table table(HashTables::New<Table>(100));
787 for (intptr_t i = 0; i < libraries_.Length(); i++) {
788 lib ^= libraries_.At(i);
789 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
790 while (it.HasNext()) {
791 cls = it.GetNextClass();
792 if (cls.IsDynamicClass()) {
793 continue; // class 'dynamic' is in the read-only VM isolate.
794 }
795 functions = cls.functions();
796 for (intptr_t j = 0; j < functions.Length(); j++) {
797 function ^= functions.At(j);
798 if (function.IsDynamicFunction()) {
799 fname = function.name();
800 if (function.IsSetterFunction() ||
801 function.IsImplicitSetterFunction()) {
802 AddNameToFunctionsTable(zone(), &table, fname, function);
803 } else if (function.IsGetterFunction() ||
804 function.IsImplicitGetterFunction()) {
805 // Enter both getter and non getter name.
806 AddNameToFunctionsTable(zone(), &table, fname, function);
807 fname = Field::NameFromGetter(fname);
808 AddNameToFunctionsTable(zone(), &table, fname, function);
809 } else {
810 // Regular function. Enter both getter and non getter name.
811 AddNameToFunctionsTable(zone(), &table, fname, function);
812 fname = Field::GetterName(fname);
813 AddNameToFunctionsTable(zone(), &table, fname, function);
814 }
815 }
816 }
817 }
818 }
819
820 // Locate all entries with one function only, and which owner is neither
rmacnak 2015/12/04 19:37:23 whose owner
srdjan 2015/12/04 20:40:19 Done.
821 // subclassed nor implemented.
822 Table::Iterator iter(&table);
823 String& key = String::Handle(Z);
824 UniqueFunctionsSet functions_set(HashTables::New<UniqueFunctionsSet>(20));
825 while (iter.MoveNext()) {
826 intptr_t curr_key = iter.Current();
827 key ^= table.GetKey(curr_key);
828 farray ^= table.GetOrNull(key);
829 ASSERT(!farray.IsNull());
830 if (farray.Length() == 1) {
831 function ^= farray.At(0);
832 cls = function.Owner();
833 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) {
834 functions_set.Insert(function);
835 }
836 }
837 }
838
839 if (FLAG_print_unique_targets) {
840 UniqueFunctionsSet::Iterator unique_iter(&functions_set);
841 while (unique_iter.MoveNext()) {
842 intptr_t curr_key = unique_iter.Current();
843 function ^= functions_set.GetKey(curr_key);
844 THR_Print("* %s\n", function.ToQualifiedCString());
845 }
rmacnak 2015/12/04 19:37:23 Consider something like THR_PRINT("%d of %d dynam
srdjan 2015/12/04 20:40:19 Done. s/Size/NumOccupied/
846 }
847
848 isolate()->object_store()->set_unique_dynamic_targets(
849 functions_set.Release());
850 table.Release();
851 }
852
853
854 void Precompiler::GetUniqueDynamicTarget(Isolate* isolate,
855 const String& fname,
856 Object* function) {
857 UniqueFunctionsSet functions_set(
858 isolate->object_store()->unique_dynamic_targets());
859 ASSERT(fname.IsSymbol());
860 *function = functions_set.GetOrNull(fname);
861 ASSERT(functions_set.Release().raw() ==
862 isolate->object_store()->unique_dynamic_targets());
863 }
864
865
711 void Precompiler::DropUncompiledFunctions() { 866 void Precompiler::DropUncompiledFunctions() {
712 Library& lib = Library::Handle(Z); 867 Library& lib = Library::Handle(Z);
713 Class& cls = Class::Handle(Z); 868 Class& cls = Class::Handle(Z);
714 Array& functions = Array::Handle(Z); 869 Array& functions = Array::Handle(Z);
715 Function& function = Function::Handle(Z); 870 Function& function = Function::Handle(Z);
716 Function& function2 = Function::Handle(Z); 871 Function& function2 = Function::Handle(Z);
717 GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z); 872 GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z);
718 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); 873 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
719 874
720 for (intptr_t i = 0; i < libraries_.Length(); i++) { 875 for (intptr_t i = 0; i < libraries_.Length(); i++) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 cls = it.GetNextClass(); 1139 cls = it.GetNextClass();
985 if (cls.IsDynamicClass()) { 1140 if (cls.IsDynamicClass()) {
986 continue; // class 'dynamic' is in the read-only VM isolate. 1141 continue; // class 'dynamic' is in the read-only VM isolate.
987 } 1142 }
988 cls.set_is_allocated(false); 1143 cls.set_is_allocated(false);
989 } 1144 }
990 } 1145 }
991 } 1146 }
992 1147
993 } // namespace dart 1148 } // 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