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

Unified Diff: runtime/vm/precompiler.cc

Issue 1409523003: Trace through const objects instead of spying on flow graph construction to find closure functions.… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 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
« no previous file with comments | « runtime/vm/precompiler.h ('k') | sdk/lib/core/uri.dart » ('j') | 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 7000601bc549cc3da0aa236ab80d47122d4d798b..b69300250b85d153ad973905aedac3ef3e8e1f2a 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -60,35 +60,35 @@ Precompiler::Precompiler(Thread* thread, bool reset_fields) :
libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())),
pending_functions_(
GrowableObjectArray::Handle(Z, GrowableObjectArray::New())),
- collected_closures_(
- GrowableObjectArray::Handle(Z, GrowableObjectArray::New())),
sent_selectors_(),
+ enqueued_functions_(),
error_(Error::Handle(Z)) {
- I->set_collected_closures(collected_closures_);
}
void Precompiler::DoCompileAll(
Dart_QualifiedFunctionName embedder_entry_points[]) {
- // 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();
// Make sure class hierarchy is stable before compilation so that CHA
- // can be used.
+ // can be used. Also ensures lookup of entry points won't miss functions
+ // because their class hasn't been finalized yet.
FinalizeAllClasses();
// Start with the allocations and invocations that happen from C++.
AddRoots(embedder_entry_points);
- // TODO(rmacnak): Eagerly add field-invocation functions to all signature
- // classes so closure calls don't go through the runtime.
-
// Compile newly found targets and add their callees until we reach a fixed
// point.
Iterate();
- CleanUp();
+ DropUncompiledFunctions();
+
+ // TODO(rmacnak): DropEmptyClasses();
+
+ BindStaticCalls();
+
+ DedupStackmaps();
if (FLAG_trace_precompiler) {
THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types,"
@@ -191,6 +191,7 @@ void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) {
Dart_QualifiedFunctionName vm_entry_points[] = {
{ "dart:async", "::", "_setScheduleImmediateClosure" },
+ { "dart:core", "::", "_completeDeferredLoads"},
{ "dart:core", "AbstractClassInstantiationError",
"AbstractClassInstantiationError._create" },
{ "dart:core", "ArgumentError", "ArgumentError." },
@@ -297,30 +298,10 @@ void Precompiler::Iterate() {
}
CheckForNewDynamicFunctions();
-
- // Drain collected_closures last because additions to this list come from
- // outside the Precompiler and so do not flip our changed_ flag.
- while (collected_closures_.Length() > 0) {
- function ^= collected_closures_.RemoveLast();
- ProcessFunction(function);
- }
}
}
-void Precompiler::CleanUp() {
- I->set_collected_closures(GrowableObjectArray::Handle(Z));
-
- DropUncompiledFunctions();
-
- // TODO(rmacnak): DropEmptyClasses();
-
- BindStaticCalls();
-
- DedupStackmaps();
-}
-
-
void Precompiler::ProcessFunction(const Function& function) {
if (!function.HasCode()) {
function_count_++;
@@ -372,6 +353,8 @@ void Precompiler::AddCalleesOf(const Function& function) {
String& selector = String::Handle(Z);
Field& field = Field::Handle(Z);
Class& cls = Class::Handle(Z);
+ Instance& instance = Instance::Handle(Z);
+ Code& target_code = Code::Handle(Z);
for (intptr_t i = 0; i < pool.Length(); i++) {
if (pool.InfoAt(i) == ObjectPool::kTaggedObject) {
entry = pool.ObjectAt(i);
@@ -401,15 +384,71 @@ void Precompiler::AddCalleesOf(const Function& function) {
field ^= entry.raw();
AddField(field);
} else if (entry.IsInstance()) {
- // Potential const object.
- cls = entry.clazz();
- AddClass(cls);
+ // Const object, literal or args descriptor.
+ instance ^= entry.raw();
+ AddConstObject(instance);
+ } else if (entry.IsFunction()) {
+ // Local closure function.
+ target ^= entry.raw();
+ AddFunction(target);
+ } else if (entry.IsCode()) {
+ target_code ^= entry.raw();
+ if (target_code.IsAllocationStubCode()) {
+ cls ^= target_code.owner();
+ AddClass(cls);
+ }
}
}
}
}
+void Precompiler::AddConstObject(const Instance& instance) {
+ const Class& cls = Class::Handle(Z, instance.clazz());
+ AddClass(cls);
+
+ if (instance.IsClosure()) {
+ // An implicit static closure.
+ const Function& func = Function::Handle(Z, Closure::function(instance));
+ ASSERT(func.is_static());
+ AddFunction(func);
+ return;
+ }
+
+ // Can't ask immediate objects if they're canoncial.
+ if (instance.IsSmi()) return;
+
+ // Some Instances in the ObjectPool aren't const objects, such as
+ // argument descriptors.
+ if (!instance.IsCanonical()) return;
+
+ class ConstObjectVisitor : public ObjectPointerVisitor {
+ public:
+ ConstObjectVisitor(Precompiler* precompiler, Isolate* isolate) :
+ ObjectPointerVisitor(isolate),
+ precompiler_(precompiler),
+ subinstance_(Object::Handle()) {}
+
+ virtual void VisitPointers(RawObject** first, RawObject** last) {
+ for (RawObject** current = first; current <= last; current++) {
+ subinstance_ = *current;
+ if (subinstance_.IsInstance()) {
+ precompiler_->AddConstObject(Instance::Cast(subinstance_));
+ }
+ }
+ subinstance_ = Object::null();
+ }
+
+ private:
+ Precompiler* precompiler_;
+ Object& subinstance_;
+ };
+
+ ConstObjectVisitor visitor(this, I);
+ instance.raw()->VisitPointers(&visitor);
+}
+
+
void Precompiler::AddClosureCall(const ICData& call_site) {
const Array& arguments_descriptor =
Array::Handle(Z, call_site.arguments_descriptor());
@@ -428,11 +467,10 @@ void Precompiler::AddClosureCall(const ICData& call_site) {
void Precompiler::AddField(const Field& field) {
if (field.is_static()) {
- // Potential const object. Uninitialized field will harmlessly do a
- // redundant add of the Null class.
const Object& value = Object::Handle(Z, field.StaticValue());
- const Class& cls = Class::Handle(Z, value.clazz());
- AddClass(cls);
+ if (value.IsInstance()) {
+ AddConstObject(Instance::Cast(value));
+ }
if (field.has_initializer()) {
// Should not be in the middle of initialization while precompiling.
@@ -459,8 +497,9 @@ void Precompiler::AddField(const Field& field) {
void Precompiler::AddFunction(const Function& function) {
- if (function.HasCode()) return;
+ if (enqueued_functions_.Lookup(&function) != NULL) return;
+ enqueued_functions_.Insert(&Function::ZoneHandle(Z, function.raw()));
pending_functions_.Add(function);
changed_ = true;
}
@@ -525,43 +564,7 @@ void Precompiler::CheckForNewDynamicFunctions() {
while (it.HasNext()) {
cls = it.GetNextClass();
- if (!cls.is_allocated()) {
- bool has_compiled_constructor = false;
- if (cls.allocation_stub() != Code::null()) {
- // Regular objects.
- has_compiled_constructor = true;
- } else if (cls.is_synthesized_class()) {
- // Enums.
- has_compiled_constructor = true;
- } else {
- // Objects only allocated via const constructors, and not stored in a
- // static field or code.
- // E.g. A in
- // class A {
- // const A();
- // toString() => "Don't drop me!";
- // }
- // class B {
- // const a = const A();
- // const B();
- // static const theB = const B();
- // }
- // main() => print(B.theB.a);
- functions = cls.functions();
- for (intptr_t k = 0; k < functions.Length(); k++) {
- function ^= functions.At(k);
- if (function.IsGenerativeConstructor() &&
- function.HasCode()) {
- has_compiled_constructor = true;
- break;
- }
- }
- }
- if (!has_compiled_constructor) {
- continue;
- }
- AddClass(cls);
- }
+ if (!cls.is_allocated()) continue;
functions = cls.functions();
for (intptr_t k = 0; k < functions.Length(); k++) {
@@ -816,6 +819,10 @@ void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
for (intptr_t j = 0; j < functions.Length(); j++) {
function ^= functions.At(j);
visitor->VisitFunction(function);
+ if (function.HasImplicitClosureFunction()) {
+ function = function.ImplicitClosureFunction();
+ visitor->VisitFunction(function);
+ }
}
closures = cls.closures();
« no previous file with comments | « runtime/vm/precompiler.h ('k') | sdk/lib/core/uri.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698