Fix unexpected circular dependency check
The PruneObjectReferenceVisitor, responsible for traversal instances of
a class, to avoid circular dependenceis which makes infinite recursion,
should only record an object received if it's not a ClassClass, because
the processing of ClassClass objects will be forwarded to
PruneAppImageClassInternal, which will first check circular
dependencies.
Test: make test-art-host -j64
Change-Id: Ib056d3fcd02135992b09f7d28176da3a1173d42e
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index fc7cd01..f4e8a89 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -770,18 +770,18 @@
*result_ = true;
}
- // Record the object visited in case of circular reference.
- visited_->emplace(ref);
if (ref->IsClass()) {
*result_ = *result_ ||
image_writer_->PruneAppImageClassInternal(ref->AsClass(), early_exit_, visited_);
} else {
+ // Record the object visited in case of circular reference.
+ visited_->emplace(ref);
*result_ = *result_ ||
image_writer_->PruneAppImageClassInternal(klass, early_exit_, visited_);
ref->VisitReferences(*this, *this);
+ // Clean up before exit for next call of this function.
+ visited_->erase(ref);
}
- // Clean up before exit for next call of this function.
- visited_->erase(ref);
}
ALWAYS_INLINE void operator() (ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
diff --git a/test/660-clinit/profile b/test/660-clinit/profile
new file mode 100644
index 0000000..0239f22
--- /dev/null
+++ b/test/660-clinit/profile
@@ -0,0 +1,10 @@
+LMain;
+LClInit;
+LDay;
+LA;
+LB;
+LC;
+LG;
+LGs;
+LObjectRef;
+
diff --git a/test/660-clinit/run b/test/660-clinit/run
new file mode 100644
index 0000000..d24ef42
--- /dev/null
+++ b/test/660-clinit/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+exec ${RUN} $@ --profile
diff --git a/test/660-clinit/src/Main.java b/test/660-clinit/src/Main.java
index 96ba627..f9b068e 100644
--- a/test/660-clinit/src/Main.java
+++ b/test/660-clinit/src/Main.java
@@ -34,6 +34,10 @@
expectNotPreInit(Gs.class); // should fail
expectNotPreInit(Gss.class); // should fail
+ expectNotPreInit(Add.class);
+ expectNotPreInit(Mul.class);
+ expectNotPreInit(ObjectRef.class);
+
A x = new A();
System.out.println("A.a: " + A.a);
@@ -165,3 +169,22 @@
// but G's status will be StatusVerified. INVOKE_DIRECT will not initialize class.
class Gs extends G {} // fail because super class can't be initialized
class Gss extends Gs {}
+
+// pruned because holding reference to non-image class
+class ObjectRef {
+ static Class<?> klazz[] = new Class<?>[]{Add.class, Mul.class};
+}
+
+// non-image
+class Add {
+ static int exec(int a, int b) {
+ return a + b;
+ }
+}
+
+// non-image
+class Mul {
+ static int exec(int a, int b) {
+ return a * b;
+ }
+}