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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/precompiler.cc
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index c691a807f2f4ec5b3d8550d57e5b5dd2ffa47adc..d218d7fd306dcfc496bfba0b0cb1a39e14e26ca7 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -4,8 +4,10 @@
#include "vm/precompiler.h"
+#include "vm/cha.h"
#include "vm/code_patcher.h"
#include "vm/compiler.h"
+#include "vm/hash_table.h"
#include "vm/isolate.h"
#include "vm/log.h"
#include "vm/longjump.h"
@@ -22,6 +24,10 @@ namespace dart {
#define Z (zone())
+DEFINE_FLAG(bool, collect_dynamic_function_names, false,
+ "In precompilation collects all dynamic function names in order to"
+ " identify unique targets");
+DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets");
DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler.");
@@ -97,6 +103,8 @@ void Precompiler::DoCompileAll(
// Start with the allocations and invocations that happen from C++.
AddRoots(embedder_entry_points);
+ 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.
+
// Compile newly found targets and add their callees until we reach a fixed
// point.
Iterate();
@@ -708,6 +716,153 @@ void Precompiler::CheckForNewDynamicFunctions() {
}
+class NameFunctionsTraits {
+ public:
+ static bool IsMatch(const Object& a, const Object& b) {
+ return a.IsString() && b.IsString() &&
+ String::Cast(a).Equals(String::Cast(b));
+ }
+ static uword Hash(const Object& obj) {
+ return String::Cast(obj).Hash();
+ }
+ static RawObject* NewKey(const String& str) {
+ return str.raw();
+ }
+};
+
+typedef UnorderedHashMap<NameFunctionsTraits> Table;
+
+
+class FunctionsTraits {
+ public:
+ static bool IsMatch(const Object& a, const Object& b) {
+ Zone* zone = Thread::Current()->zone();
+ String& a_s = String::Handle(zone);
+ String& b_s = String::Handle(zone);
+ a_s = a.IsFunction() ? Function::Cast(a).name() : String::Cast(a).raw();
+ b_s = b.IsFunction() ? Function::Cast(b).name() : String::Cast(b).raw();
+ ASSERT(a_s.IsSymbol() && b_s.IsSymbol());
+ return a_s.raw() == b_s.raw();
+ }
+ static uword Hash(const Object& obj) {
+ if (obj.IsFunction()) {
+ return String::Handle(Function::Cast(obj).name()).Hash();
+ } else {
+ ASSERT(String::Cast(obj).IsSymbol());
+ return String::Cast(obj).Hash();
+ }
+ }
+ static RawObject* NewKey(const Function& function) {
+ return function.raw();
+ }
+};
+
+typedef UnorderedHashSet<FunctionsTraits> UniqueFunctionsSet;
+
+
+static void AddNameToFunctionsTable(Zone* zone,
+ Table* table,
+ const String& fname,
+ const Function& function) {
+ Array& farray = Array::Handle(zone);
+ farray ^= table->InsertNewOrGetValue(fname, Array::empty_array());
+ farray = Array::Grow(farray, farray.Length() + 1);
+ farray.SetAt(farray.Length() - 1, function);
+ table->UpdateValue(fname, farray);
+}
+
+
+void Precompiler::CollectDynamicFunctionNames() {
+ if (!FLAG_collect_dynamic_function_names) {
+ return;
+ }
+ Library& lib = Library::Handle(Z);
+ Class& cls = Class::Handle(Z);
+ Array& functions = Array::Handle(Z);
+ Function& function = Function::Handle(Z);
+ String& fname = String::Handle(Z);
+ Array& farray = Array::Handle(Z);
+
+ Table table(HashTables::New<Table>(100));
+ for (intptr_t i = 0; i < libraries_.Length(); i++) {
+ lib ^= libraries_.At(i);
+ ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+ while (it.HasNext()) {
+ cls = it.GetNextClass();
+ if (cls.IsDynamicClass()) {
+ continue; // class 'dynamic' is in the read-only VM isolate.
+ }
+ functions = cls.functions();
+ for (intptr_t j = 0; j < functions.Length(); j++) {
+ function ^= functions.At(j);
+ if (function.IsDynamicFunction()) {
+ fname = function.name();
+ if (function.IsSetterFunction() ||
+ function.IsImplicitSetterFunction()) {
+ AddNameToFunctionsTable(zone(), &table, fname, function);
+ } else if (function.IsGetterFunction() ||
+ function.IsImplicitGetterFunction()) {
+ // Enter both getter and non getter name.
+ AddNameToFunctionsTable(zone(), &table, fname, function);
+ fname = Field::NameFromGetter(fname);
+ AddNameToFunctionsTable(zone(), &table, fname, function);
+ } else {
+ // Regular function. Enter both getter and non getter name.
+ AddNameToFunctionsTable(zone(), &table, fname, function);
+ fname = Field::GetterName(fname);
+ AddNameToFunctionsTable(zone(), &table, fname, function);
+ }
+ }
+ }
+ }
+ }
+
+ // 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.
+ // subclassed nor implemented.
+ Table::Iterator iter(&table);
+ String& key = String::Handle(Z);
+ UniqueFunctionsSet functions_set(HashTables::New<UniqueFunctionsSet>(20));
+ while (iter.MoveNext()) {
+ intptr_t curr_key = iter.Current();
+ key ^= table.GetKey(curr_key);
+ farray ^= table.GetOrNull(key);
+ ASSERT(!farray.IsNull());
+ if (farray.Length() == 1) {
+ function ^= farray.At(0);
+ cls = function.Owner();
+ if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) {
+ functions_set.Insert(function);
+ }
+ }
+ }
+
+ if (FLAG_print_unique_targets) {
+ UniqueFunctionsSet::Iterator unique_iter(&functions_set);
+ while (unique_iter.MoveNext()) {
+ intptr_t curr_key = unique_iter.Current();
+ function ^= functions_set.GetKey(curr_key);
+ THR_Print("* %s\n", function.ToQualifiedCString());
+ }
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/
+ }
+
+ isolate()->object_store()->set_unique_dynamic_targets(
+ functions_set.Release());
+ table.Release();
+}
+
+
+void Precompiler::GetUniqueDynamicTarget(Isolate* isolate,
+ const String& fname,
+ Object* function) {
+ UniqueFunctionsSet functions_set(
+ isolate->object_store()->unique_dynamic_targets());
+ ASSERT(fname.IsSymbol());
+ *function = functions_set.GetOrNull(fname);
+ ASSERT(functions_set.Release().raw() ==
+ isolate->object_store()->unique_dynamic_targets());
+}
+
+
void Precompiler::DropUncompiledFunctions() {
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
« 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