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

Unified 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 side-by-side diff with in-line comments
Download patch
« runtime/vm/precompiler.h ('K') | « 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 52287f3abc2b0e86dcfca35cdedd9115052c1164..59a4b7b712d5c2f07398963b926f227bf565cb58 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -6,6 +6,7 @@
#include "vm/compiler.h"
#include "vm/isolate.h"
+#include "vm/log.h"
#include "vm/longjump.h"
#include "vm/object.h"
#include "vm/object_store.h"
@@ -49,16 +50,20 @@ Precompiler::Precompiler(Thread* thread) :
changed_(false),
function_count_(0),
class_count_(0),
+ selector_count_(0),
+ dropped_function_count_(0),
libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())),
pending_functions_(GrowableObjectArray::Handle(Z,
GrowableObjectArray::New())),
collected_closures_(GrowableObjectArray::Handle(Z, I->collected_closures())),
- sent_selectors_(GrowableObjectArray::Handle(Z, GrowableObjectArray::New())),
+ sent_selectors_(Z),
error_(Error::Handle(Z)) {
}
void Precompiler::DoCompileAll() {
+ LogBlock lb(thread_);
+
// Drop all existing code so we can use the presence of code as an indicator
// that we have already looked for the function's callees.
ClearAllCode();
@@ -76,11 +81,12 @@ void Precompiler::DoCompileAll() {
CleanUp();
if (FLAG_trace_precompiler) {
- OS::Print("Precompiled %" Pd " functions, %" Pd " dynamic types,"
- " %" Pd " dynamic selectors\n",
+ ISL_Print("Precompiled %" Pd " functions, %" Pd " dynamic types,"
+ " %" Pd " dynamic selectors.\n Dropped %" Pd " functions.\n",
function_count_,
class_count_,
- sent_selectors_.Length());
+ selector_count_,
+ dropped_function_count_);
}
I->set_compilation_allowed(false);
@@ -270,7 +276,7 @@ void Precompiler::AddRoots() {
lib = Library::LookupLibrary(library_name);
if (lib.IsNull()) {
if (FLAG_trace_precompiler) {
- OS::Print("WARNING: Missing %s\n", kExternallyCalled[i].library_);
+ ISL_Print("WARNING: Missing %s\n", kExternallyCalled[i].library_);
}
continue;
}
@@ -281,7 +287,7 @@ void Precompiler::AddRoots() {
cls = lib.LookupClassAllowPrivate(class_name);
if (cls.IsNull()) {
if (FLAG_trace_precompiler) {
- OS::Print("WARNING: Missing %s %s\n",
+ ISL_Print("WARNING: Missing %s %s\n",
kExternallyCalled[i].library_,
kExternallyCalled[i].class_);
}
@@ -294,7 +300,7 @@ void Precompiler::AddRoots() {
if (func.IsNull()) {
if (FLAG_trace_precompiler) {
- OS::Print("WARNING: Missing %s %s %s\n",
+ ISL_Print("WARNING: Missing %s %s %s\n",
kExternallyCalled[i].library_,
kExternallyCalled[i].class_,
kExternallyCalled[i].function_);
@@ -333,7 +339,9 @@ void Precompiler::Iterate() {
void Precompiler::CleanUp() {
I->set_collected_closures(GrowableObjectArray::Handle(Z));
- // TODO(rmacnak): Drop functions without code, classes without functions, etc.
+ DropUncompiledFunctions();
+
+ // TODO(rmacnak): DropEmptyClasses();
}
@@ -342,7 +350,7 @@ void Precompiler::ProcessFunction(const Function& function) {
function_count_++;
if (FLAG_trace_precompiler) {
- OS::Print("Precompiling %" Pd " %s (%" Pd ", %s)\n",
+ ISL_Print("Precompiling %" Pd " %s (%" Pd ", %s)\n",
function_count_,
function.ToLibNamePrefixedQualifiedCString(),
function.token_pos(),
@@ -434,7 +442,7 @@ void Precompiler::AddField(const Field& field) {
if (field.initializer() != Function::null()) return;
if (FLAG_trace_precompiler) {
- OS::Print("Precompiling initializer for %s\n", field.ToCString());
+ ISL_Print("Precompiling initializer for %s\n", field.ToCString());
}
Compiler::CompileStaticInitializer(field);
@@ -454,36 +462,26 @@ void Precompiler::AddFunction(const Function& function) {
bool Precompiler::IsSent(const String& selector) {
- ASSERT(selector.IsSymbol());
-
- // TODO(rmacnak): Use a proper set.
- for (intptr_t i = 0; i < sent_selectors_.Length(); i++) {
- if (sent_selectors_.At(i) == selector.raw()) {
- return true;
- }
- }
-
- return false;
+ return sent_selectors_.Includes(selector);
}
void Precompiler::AddSelector(const String& selector) {
if (!IsSent(selector)) {
+ sent_selectors_.Add(selector);
+ selector_count_++;
+ changed_ = true;
+
if (FLAG_trace_precompiler) {
- OS::Print("Enqueueing selector %" Pd " %s\n",
- sent_selectors_.Length(),
+ ISL_Print("Enqueueing selector %" Pd " %s\n",
+ selector_count_,
selector.ToCString());
}
- sent_selectors_.Add(selector);
- changed_ = true;
-
if (!Field::IsGetterName(selector) &&
!Field::IsSetterName(selector)) {
// Regular method may be call-through-getter.
- // TODO(rmacnak): Do not create the symbol if it does not already exist.
- String& getter = String::Handle(Field::GetterName(selector));
- getter = Symbols::New(getter);
+ const String& getter = String::Handle(Field::GetterSymbol(selector));
AddSelector(getter);
}
}
@@ -498,7 +496,7 @@ void Precompiler::AddClass(const Class& cls) {
changed_ = true;
if (FLAG_trace_precompiler) {
- OS::Print("Allocation %" Pd " %s\n", class_count_, cls.ToCString());
+ ISL_Print("Allocation %" Pd " %s\n", class_count_, cls.ToCString());
}
const Class& superclass = Class::Handle(cls.SuperClass());
@@ -577,10 +575,7 @@ void Precompiler::CheckForNewDynamicFunctions() {
if (function.kind() == RawFunction::kRegularFunction &&
!Field::IsGetterName(selector) &&
!Field::IsSetterName(selector)) {
- // TODO(rmacnak): Do not create the symbol if it does not already
- // exist.
- selector = Field::GetterName(selector);
- selector = Symbols::New(selector);
+ selector = Field::GetterSymbol(selector);
if (IsSent(selector)) {
function = function.ImplicitClosureFunction();
AddFunction(function);
@@ -591,4 +586,55 @@ void Precompiler::CheckForNewDynamicFunctions() {
}
}
+
+void Precompiler::DropUncompiledFunctions() {
+ Library& lib = Library::Handle(Z);
+ Class& cls = Class::Handle(Z);
+ Array& functions = Array::Handle(Z);
+ Function& function = Function::Handle(Z);
+ GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z);
+ GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
+
+ 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();
+ retained_functions = GrowableObjectArray::New();
+ for (intptr_t j = 0; j < functions.Length(); j++) {
+ function ^= functions.At(j);
+ if (function.HasCode()) {
+ retained_functions.Add(function);
+ } else {
+ dropped_function_count_++;
+ if (FLAG_trace_precompiler) {
+ ISL_Print("Precompilation dropping %s\n",
+ function.ToLibNamePrefixedQualifiedCString());
+ }
+ }
+ }
+
+ functions = Array::New(retained_functions.Length(), Heap::kOld);
+ for (intptr_t j = 0; j < retained_functions.Length(); j++) {
+ function ^= retained_functions.At(j);
+ functions.SetAt(j, function);
+ }
+ cls.SetFunctions(functions);
+
+ closures = cls.closures();
+ if (!closures.IsNull()) {
+ for (intptr_t j = 0; j < closures.Length(); j++) {
+ function ^= closures.At(j);
+ ASSERT(function.HasCode());
+ }
+ }
+ }
+ }
+}
+
} // namespace dart
« 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