Merge "Do not interrupt RunReporter thread" into ub-jack-brest
diff --git a/jack-tests/tests/com/android/jack/inner/InnerTests.java b/jack-tests/tests/com/android/jack/inner/InnerTests.java
index 710f271..8634495 100644
--- a/jack-tests/tests/com/android/jack/inner/InnerTests.java
+++ b/jack-tests/tests/com/android/jack/inner/InnerTests.java
@@ -135,6 +135,10 @@
AbstractTestTools.getTestRootDir("com.android.jack.inner.test026"),
"com.android.jack.inner.test026.dx.Tests");
+ private RuntimeTestInfo TEST028 = new RuntimeTestInfo(
+ AbstractTestTools.getTestRootDir("com.android.jack.inner.test028"),
+ "com.android.jack.inner.test028.dx.Tests");
+
@Test
@Category(RuntimeRegressionTest.class)
@@ -297,6 +301,12 @@
}
@Test
+ @Category(RuntimeRegressionTest.class)
+ public void test028() throws Exception {
+ new RuntimeTestHelper(TEST028).compileAndRunTest();
+ }
+
+ @Test
public void testCheckStructure20() throws Exception {
//TODO: find out why debug info check fails
checkStructure("test020");
@@ -341,5 +351,6 @@
rtTestInfos.add(TEST023);
rtTestInfos.add(TEST024);
rtTestInfos.add(TEST026);
+ rtTestInfos.add(TEST028);
}
}
diff --git a/jack-tests/tests/com/android/jack/inner/test028/dx/Tests.java b/jack-tests/tests/com/android/jack/inner/test028/dx/Tests.java
new file mode 100644
index 0000000..e3e0421
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/inner/test028/dx/Tests.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package com.android.jack.inner.test028.dx;
+
+
+import com.android.jack.inner.test028.jack.Outer;
+
+import org.junit.Test;
+
+public class Tests {
+
+ @Test
+ public void test() {
+ Outer outer = new Outer();
+ outer.getInner();
+ outer.resetInner();
+ }
+}
diff --git a/jack-tests/tests/com/android/jack/inner/test028/jack/Outer.java b/jack-tests/tests/com/android/jack/inner/test028/jack/Outer.java
new file mode 100644
index 0000000..2db27c8
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/inner/test028/jack/Outer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package com.android.jack.inner.test028.jack;
+
+public class Outer {
+
+ private Inner inner = null;
+
+ public final static class Inner {
+
+ private Inner() {
+ }
+
+ private Inner(Inner i) {
+ }
+ }
+
+ public void resetInner() {
+ inner = new Inner();
+ }
+
+ public Inner getInner() {
+ return new Inner(inner);
+ }
+}
diff --git a/jack/src/com/android/jack/Jack.java b/jack/src/com/android/jack/Jack.java
index a618c26..58bb934 100644
--- a/jack/src/com/android/jack/Jack.java
+++ b/jack/src/com/android/jack/Jack.java
@@ -980,7 +980,6 @@
methodPlan2.append(IncDecRemover.class);
methodPlan2.append(CompoundAssignmentRemover.class);
methodPlan2.append(ConcatRemover.class);
- methodPlan2.append(InnerAccessorGenerator.class);
}
}
}
@@ -988,6 +987,7 @@
{
SubPlanBuilder<JDefinedClassOrInterface> typePlan =
planBuilder.appendSubPlan(ExcludeTypeFromLibAdapter.class);
+ typePlan.append(InnerAccessorGenerator.class);
SubPlanBuilder<JMethod> methodPlan = typePlan.appendSubPlan(JMethodAdapter.class);
methodPlan.append(SwitchEnumSupport.class);
}
diff --git a/jack/src/com/android/jack/transformations/ast/inner/InnerAccessorGenerator.java b/jack/src/com/android/jack/transformations/ast/inner/InnerAccessorGenerator.java
index 16a27e2..c6aae70 100644
--- a/jack/src/com/android/jack/transformations/ast/inner/InnerAccessorGenerator.java
+++ b/jack/src/com/android/jack/transformations/ast/inner/InnerAccessorGenerator.java
@@ -16,11 +16,15 @@
package com.android.jack.transformations.ast.inner;
+import com.google.common.collect.Ordering;
+
+import com.android.jack.Jack;
import com.android.jack.Options;
import com.android.jack.ir.SideEffectOperation;
import com.android.jack.ir.ast.JAlloc;
import com.android.jack.ir.ast.JAsgOperation;
import com.android.jack.ir.ast.JBinaryOperation;
+import com.android.jack.ir.ast.JClassOrInterface;
import com.android.jack.ir.ast.JConstructor;
import com.android.jack.ir.ast.JDefinedClass;
import com.android.jack.ir.ast.JDefinedClassOrInterface;
@@ -38,6 +42,7 @@
import com.android.jack.ir.ast.JNullLiteral;
import com.android.jack.ir.ast.JVisitor;
import com.android.jack.ir.ast.MethodKind;
+import com.android.jack.ir.formatter.TypePackageAndMethodFormatter;
import com.android.jack.ir.impl.ResolutionTargetMarker;
import com.android.jack.ir.sourceinfo.SourceInfo;
import com.android.jack.transformations.ast.NewInstanceRemoved;
@@ -53,6 +58,9 @@
import com.android.sched.schedulable.Transform;
import com.android.sched.util.config.ThreadConfig;
+import java.util.Comparator;
+
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/**
@@ -70,27 +78,21 @@
InnerAccessorSchedulingSeparator.SeparatorTag.class},
remove = {ThreeAddressCodeForm.class, NewInstanceRemoved.class})
@Constraint(no = {SideEffectOperation.class, JAlloc.class})
-public class InnerAccessorGenerator implements RunnableSchedulable<JMethod> {
+public class InnerAccessorGenerator implements RunnableSchedulable<JDefinedClassOrInterface> {
@Nonnull
static final String THIS_PARAM_NAME = NamingTools.getNonSourceConflictingName("this");
- @Nonnull
- private final Filter<JMethod> filter = ThreadConfig.get(Options.METHOD_FILTER);
-
- private static class Visitor extends JVisitor {
+ private class Visitor extends JVisitor {
@Nonnull
- private final TransformationRequest tr;
+ protected final Filter<JMethod> filter = ThreadConfig.get(Options.METHOD_FILTER);
- @Nonnull
- private final JDefinedClassOrInterface currentType;
+ @CheckForNull
+ protected TransformationRequest tr;
- public Visitor(@Nonnull TransformationRequest tr,
- @Nonnull JDefinedClassOrInterface currentType) {
- this.tr = tr;
- this.currentType = currentType;
- }
+ @CheckForNull
+ private JDefinedClassOrInterface currentType = null;
/**
* Determines where the accessor must be located in case of super invocation
@@ -102,6 +104,7 @@
@Nonnull JDefinedClassOrInterface declaringType) {
// if the instance is the super of an enclosing class, we have to retrieve it
+ assert currentType != null;
JDefinedClass enclosing = (JDefinedClass) currentType;
while (!isSuperClassOf((JDefinedClass) declaringType, enclosing)) {
enclosing = (JDefinedClass) enclosing.getEnclosingType();
@@ -169,6 +172,8 @@
assert field != null;
JDefinedClassOrInterface accessorClass = getAccessorClass(field.getModifier(),
field.getEnclosingType());
+ assert currentType != null;
+ assert tr != null;
if (!accessorClass.isSameType(currentType)) {
assert accessorClass.getSourceInfo().getFileSourceInfo()
.equals(currentType.getSourceInfo().getFileSourceInfo());
@@ -244,6 +249,8 @@
method.getEnclosingType());
}
+ assert currentType != null;
+ assert tr != null;
if (!accessorClass.isSameType(currentType)) {
assert accessorClass.getSourceInfo().getFileSourceInfo()
.equals(currentType.getSourceInfo().getFileSourceInfo());
@@ -297,19 +304,75 @@
}
return super.visit(x);
}
+
+ @Override
+ public boolean visit(@Nonnull JDefinedClassOrInterface type) {
+ currentType = type;
+ tr = new TransformationRequest(type);
+ // Sort types and methods to make this visitor deterministic
+ for (JMethod method : methodOrdering.sortedCopy(type.getMethods())) {
+ if (!method.isNative() && !method.isAbstract()
+ && filter.accept(InnerAccessorGenerator.class, method)) {
+ this.accept(method);
+ }
+ }
+ assert tr != null;
+ tr.commit();
+
+ for (JClassOrInterface innerType : typeOrdering.sortedCopy(type.getMemberTypes())) {
+ if (innerType instanceof JDefinedClassOrInterface) {
+ visit((JDefinedClassOrInterface) innerType);
+ }
+ }
+ return false;
+ }
}
+ @Nonnull
+ TypePackageAndMethodFormatter formatter = Jack.getLookupFormatter();
+
+ private int compareSourceInfo(@Nonnull JNode n1, @Nonnull JNode n2) {
+ return n1.getSourceInfo().getStartLine() - n2.getSourceInfo().getStartLine();
+ }
+
+ @Nonnull
+ private final Ordering<JMethod> methodOrdering = Ordering.from(new Comparator<JMethod>() {
+ @Override
+ public int compare(@Nonnull JMethod m1, @Nonnull JMethod m2) {
+ int compareSourceInfo = compareSourceInfo(m1, m2);
+ if (compareSourceInfo != 0) {
+ return compareSourceInfo;
+ }
+ return formatter.getName(m1).compareTo(formatter.getName(m2));
+ }
+ });
+
+ @Nonnull
+ private final Ordering<JClassOrInterface> typeOrdering =
+ Ordering.from(new Comparator<JClassOrInterface>() {
+ @Override
+ public int compare(@Nonnull JClassOrInterface t1, @Nonnull JClassOrInterface t2) {
+ int compareSourceInfo = compareSourceInfo((JNode) t1, (JNode) t2);
+ if (compareSourceInfo != 0) {
+ return compareSourceInfo;
+ }
+ return formatter.getName(t1).compareTo(formatter.getName(t2));
+ }
+ });
+
@Override
- public synchronized void run(@Nonnull JMethod method) throws Exception {
- if (method.getEnclosingType().isExternal() || method.isNative() || method.isAbstract()
- || !filter.accept(this.getClass(), method)) {
+ public synchronized void run(@Nonnull JDefinedClassOrInterface type) throws Exception {
+ // Start visit on outer types for a deterministic visit order.
+ if (type.getEnclosingType() != null) {
return;
}
- TransformationRequest tr = new TransformationRequest(method);
- Visitor visitor = new Visitor(tr, method.getEnclosingType());
- visitor.accept(method);
- tr.commit();
+ // No need to visit types without inner classes.
+ if (type.getMemberTypes().isEmpty()) {
+ return;
+ }
+
+ new Visitor().accept(type);
}