| 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/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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 | 93 |
| 88 // TODO(rmacnak): We should be able to do a more thorough job and drop some | 94 // TODO(rmacnak): We should be able to do a more thorough job and drop some |
| 89 // - implicit static closures | 95 // - implicit static closures |
| 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 |
| 103 CollectDynamicFunctionNames(); |
| 104 |
| 97 // Start with the allocations and invocations that happen from C++. | 105 // Start with the allocations and invocations that happen from C++. |
| 98 AddRoots(embedder_entry_points); | 106 AddRoots(embedder_entry_points); |
| 99 | 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 |
| (...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 whose owner is neither |
| 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 } |
| 846 THR_Print("%" Pd " of %" Pd " dynamic selectors are unique\n", |
| 847 functions_set.NumOccupied(), table.NumOccupied()); |
| 848 } |
| 849 |
| 850 isolate()->object_store()->set_unique_dynamic_targets( |
| 851 functions_set.Release()); |
| 852 table.Release(); |
| 853 } |
| 854 |
| 855 |
| 856 void Precompiler::GetUniqueDynamicTarget(Isolate* isolate, |
| 857 const String& fname, |
| 858 Object* function) { |
| 859 UniqueFunctionsSet functions_set( |
| 860 isolate->object_store()->unique_dynamic_targets()); |
| 861 ASSERT(fname.IsSymbol()); |
| 862 *function = functions_set.GetOrNull(fname); |
| 863 ASSERT(functions_set.Release().raw() == |
| 864 isolate->object_store()->unique_dynamic_targets()); |
| 865 } |
| 866 |
| 867 |
| 711 void Precompiler::DropUncompiledFunctions() { | 868 void Precompiler::DropUncompiledFunctions() { |
| 712 Library& lib = Library::Handle(Z); | 869 Library& lib = Library::Handle(Z); |
| 713 Class& cls = Class::Handle(Z); | 870 Class& cls = Class::Handle(Z); |
| 714 Array& functions = Array::Handle(Z); | 871 Array& functions = Array::Handle(Z); |
| 715 Function& function = Function::Handle(Z); | 872 Function& function = Function::Handle(Z); |
| 716 Function& function2 = Function::Handle(Z); | 873 Function& function2 = Function::Handle(Z); |
| 717 GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z); | 874 GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z); |
| 718 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); | 875 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); |
| 719 | 876 |
| 720 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 877 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 984 cls = it.GetNextClass(); | 1141 cls = it.GetNextClass(); |
| 985 if (cls.IsDynamicClass()) { | 1142 if (cls.IsDynamicClass()) { |
| 986 continue; // class 'dynamic' is in the read-only VM isolate. | 1143 continue; // class 'dynamic' is in the read-only VM isolate. |
| 987 } | 1144 } |
| 988 cls.set_is_allocated(false); | 1145 cls.set_is_allocated(false); |
| 989 } | 1146 } |
| 990 } | 1147 } |
| 991 } | 1148 } |
| 992 | 1149 |
| 993 } // namespace dart | 1150 } // namespace dart |
| OLD | NEW |