Chromium Code Reviews| Index: runtime/vm/precompiler.cc |
| diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc |
| index 52287f3abc2b0e86dcfca35cdedd9115052c1164..2cff2f57df7a36943628035a891a55fd38779509 100644 |
| --- a/runtime/vm/precompiler.cc |
| +++ b/runtime/vm/precompiler.cc |
| @@ -49,11 +49,13 @@ 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)) { |
| } |
| @@ -80,7 +82,9 @@ void Precompiler::DoCompileAll() { |
| " %" Pd " dynamic selectors\n", |
| function_count_, |
| class_count_, |
| - sent_selectors_.Length()); |
| + selector_count_); |
| + OS::Print("Dropped %" Pd " functions\n", |
| + dropped_function_count_); |
|
srdjan
2015/08/05 18:20:08
ISL_Print
Cutch
2015/08/05 18:25:05
DBC: You may also want to put a:
LogBlock lb(Thre
rmacnak
2015/08/05 19:51:50
Done.
|
| } |
| I->set_compilation_allowed(false); |
| @@ -333,7 +337,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(); |
| } |
| @@ -454,36 +460,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(), |
| + 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. |
|
rmacnak
2015/08/05 18:11:54
Turns out the vast majority of these selectors alr
|
| - String& getter = String::Handle(Field::GetterName(selector)); |
| - getter = Symbols::New(getter); |
| + const String& getter = String::Handle(Field::GetterSymbol(selector)); |
| AddSelector(getter); |
| } |
| } |
| @@ -577,10 +573,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 +584,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) { |
| + OS::Print("Precompilation dropping %s\n", |
|
srdjan
2015/08/05 18:20:08
ISL_Print
|
| + 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 |