Precompilation: Don't drop an uncompiled function if it has a compiled implicit closure function.

This ensures the implicit closure function is enumerated in later steps. Fixes crash in co19 test reducible as

import 'dart:math';
main() {
  print(const [1, 2.0, "3"].fold(0, max));
}

Also enumerate invocation dispatchers to avoid a similar situation there, though I cannot find a crashing example involving them.

R=fschneider@google.com

Review URL: https://codereview.chromium.org/1489203004 .
This commit is contained in:
Ryan Macnak
2015-12-03 11:03:23 -08:00
parent 6fd2fba704
commit d94b68cb41
2 changed files with 30 additions and 2 deletions
+1
View File
@@ -1485,6 +1485,7 @@ class Class : public Object {
friend class Object;
friend class Type;
friend class Intrinsifier;
friend class Precompiler;
};
+29 -2
View File
@@ -713,6 +713,7 @@ void Precompiler::DropUncompiledFunctions() {
Class& cls = Class::Handle(Z);
Array& functions = Array::Handle(Z);
Function& function = Function::Handle(Z);
Function& function2 = Function::Handle(Z);
GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z);
GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
@@ -729,7 +730,16 @@ void Precompiler::DropUncompiledFunctions() {
retained_functions = GrowableObjectArray::New();
for (intptr_t j = 0; j < functions.Length(); j++) {
function ^= functions.At(j);
if (function.HasCode()) {
bool retain = function.HasCode();
if (!retain && function.HasImplicitClosureFunction()) {
// It can happen that all uses of an implicit closure inline their
// target function, leaving the target function uncompiled. Keep
// the target function anyway so we can enumerate it to bind its
// static calls, etc.
function2 = function.ImplicitClosureFunction();
retain = function2.HasCode();
}
if (retain) {
retained_functions.Add(function);
function.DropUncompiledImplicitClosureFunction();
} else {
@@ -780,7 +790,10 @@ void Precompiler::BindStaticCalls() {
}
void VisitFunction(const Function& function) {
ASSERT(function.HasCode());
if (!function.HasCode()) {
ASSERT(function.HasImplicitClosureFunction());
return;
}
code_ = function.CurrentCode();
table_ = code_.static_calls_target_table();
@@ -837,6 +850,10 @@ void Precompiler::DedupStackmaps() {
}
void VisitFunction(const Function& function) {
if (!function.HasCode()) {
ASSERT(function.HasImplicitClosureFunction());
return;
}
code_ = function.CurrentCode();
stackmaps_ = code_.stackmaps();
if (stackmaps_.IsNull()) return;
@@ -876,6 +893,7 @@ void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& functions = Array::Handle(Z);
Object& object = Object::Handle(Z);
Function& function = Function::Handle(Z);
GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
@@ -897,6 +915,15 @@ void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
visitor->VisitFunction(function);
}
}
functions = cls.invocation_dispatcher_cache();
for (intptr_t j = 0; j < functions.Length(); j++) {
object = functions.At(j);
if (object.IsFunction()) {
function ^= functions.At(j);
visitor->VisitFunction(function);
}
}
}
}
closures = isolate()->object_store()->closure_functions();