Merge "Update patch version for release."
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
index eb58c4d..17ebfb5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.cf.TypeVerificationHelper;
+import com.android.tools.r8.graph.AppInfo.ResolutionResult;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -118,23 +119,49 @@
if (targets == null || targets.isEmpty()) {
return Constraint.NEVER;
}
+
Constraint result = Constraint.ALWAYS;
+
+ // Perform resolution and derive inlining constraints based on the accessibility of the
+ // resolution result.
+ ResolutionResult resolutionResult = info.resolveMethod(method.holder, method);
+ DexEncodedMethod resolutionTarget = resolutionResult.asResultOfResolve();
+ if (resolutionTarget == null) {
+ // This will fail at runtime.
+ return Constraint.NEVER;
+ }
+ DexType methodHolder = resolutionTarget.method.holder;
+ DexClass methodClass = info.definitionFor(methodHolder);
+ assert methodClass != null;
+ Constraint methodConstraint = Constraint
+ .deriveConstraint(invocationContext, methodHolder, resolutionTarget.accessFlags, info);
+ result = Constraint.min(result, methodConstraint);
+ // We also have to take the constraint of the enclosing class of the resolution result
+ // into account. We do not allow inlining this method if it is calling something that
+ // is inaccessible. Inlining in that case could move the code to another package making a
+ // call succeed that should not succeed. Conversely, if the resolution result is accessible,
+ // we have to make sure that inlining cannot make it inaccessible.
+ Constraint classConstraint = Constraint
+ .deriveConstraint(invocationContext, methodHolder, methodClass.accessFlags, info);
+ result = Constraint.min(result, classConstraint);
+ if (result == Constraint.NEVER) {
+ return result;
+ }
+
+ // For each of the actual potential targets, derive constraints based on the accessibility
+ // of the method itself.
for (DexEncodedMethod target : targets) {
- DexType methodHolder = target.method.holder;
- DexClass methodClass = info.definitionFor(methodHolder);
- if ((methodClass != null)) {
- Constraint methodConstraint = Constraint
- .deriveConstraint(invocationContext, methodHolder, target.accessFlags, info);
- result = Constraint.min(result, methodConstraint);
- // We also have to take the constraint of the enclosing class into account.
- Constraint classConstraint = Constraint
- .deriveConstraint(invocationContext, methodHolder, methodClass.accessFlags, info);
- result = Constraint.min(result, classConstraint);
- }
+ methodHolder = target.method.holder;
+ methodClass = info.definitionFor(methodHolder);
+ assert methodClass != null;
+ methodConstraint = Constraint
+ .deriveConstraint(invocationContext, methodHolder, target.accessFlags, info);
+ result = Constraint.min(result, methodConstraint);
if (result == Constraint.NEVER) {
- break;
+ return result;
}
}
+
return result;
}
diff --git a/src/test/examples/inlining/IFace.java b/src/test/examples/inlining/IFace.java
new file mode 100644
index 0000000..d0402f2
--- /dev/null
+++ b/src/test/examples/inlining/IFace.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package inlining;
+
+public interface IFace {
+ int foo();
+}
diff --git a/src/test/examples/inlining/Inlining.java b/src/test/examples/inlining/Inlining.java
index 77b2979..0705587 100644
--- a/src/test/examples/inlining/Inlining.java
+++ b/src/test/examples/inlining/Inlining.java
@@ -4,6 +4,7 @@
package inlining;
import inlining.Nullability.Factor;
+import inlining.pkg.InterfaceImplementationContainer;
import inlining.pkg.OtherPublicClass;
import inlining.pkg.PublicClass;
import inlining.pkg.Subclass;
@@ -211,6 +212,8 @@
} catch (Throwable unexpected) {
System.out.println("Unexpected exception for notInlinableOnThrow");
}
+
+ System.out.println(callInterfaceMethod(InterfaceImplementationContainer.getIFace()));
}
private static boolean intCmpExpression(A a, A b) {
@@ -218,6 +221,11 @@
}
@CheckDiscarded
+ private static int callInterfaceMethod(IFace i) {
+ return i.foo();
+ }
+
+ @CheckDiscarded
private static int intConstantInline() {
return 42;
}
diff --git a/src/test/examples/inlining/pkg/InterfaceImplementationContainer.java b/src/test/examples/inlining/pkg/InterfaceImplementationContainer.java
new file mode 100644
index 0000000..5135fa2
--- /dev/null
+++ b/src/test/examples/inlining/pkg/InterfaceImplementationContainer.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package inlining.pkg;
+
+import inlining.IFace;
+
+public class InterfaceImplementationContainer {
+ private static class IFaceImplementation implements IFace {
+ @Override
+ public int foo() {
+ return 42;
+ }
+ }
+
+ public static IFace getIFace() {
+ return new IFaceImplementation();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTestRunner.java b/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTestRunner.java
index 54c906b..ca2f53f 100644
--- a/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTestRunner.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.debug;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import java.util.Collections;
@@ -48,6 +49,8 @@
@Test
public void testHitOnEntryOnly() throws Throwable {
Assume.assumeFalse("b/72933440", name.equals("D8/reorder"));
+ Assume.assumeFalse("b/73803266",
+ name.equals("D8") && ToolHelper.getDexVm() == DexVm.ART_6_0_1_HOST);
runDebugTest(
config,
NAME,
diff --git a/src/test/java/com/android/tools/r8/debug/LocalChangeOnSameLineTestRunner.java b/src/test/java/com/android/tools/r8/debug/LocalChangeOnSameLineTestRunner.java
index 002635f..9fe7e23 100644
--- a/src/test/java/com/android/tools/r8/debug/LocalChangeOnSameLineTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debug/LocalChangeOnSameLineTestRunner.java
@@ -4,8 +4,10 @@
package com.android.tools.r8.debug;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -17,6 +19,7 @@
private static final String FILE = CLASS.getSimpleName() + ".java";
private static final String NAME = CLASS.getCanonicalName();
+ private final String name;
private final DebugTestConfig config;
@Parameterized.Parameters(name = "{0}")
@@ -29,12 +32,15 @@
}
public LocalChangeOnSameLineTestRunner(String name, DelayedDebugTestConfig config) {
+ this.name = name;
this.config = config.getConfig(temp);
}
/** Test that only hit the break point at line 15 once. */
@Test
public void testHitBreakpointOnce() throws Throwable {
+ Assume.assumeFalse("b/73803266",
+ name.equals("D8") && ToolHelper.getDexVm() == DexVm.ART_6_0_1_HOST);
runDebugTest(
config,
NAME,
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
index 9c03ee7..1c72986 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
@@ -39,6 +39,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -111,9 +112,13 @@
assertEquals(javaResult.stdout, artOutput);
}
- private void checkAbsent(ClassSubject clazz, String name) {
+ private void checkAbsentBooleanMethod(ClassSubject clazz, String name) {
+ checkAbsent(clazz, "boolean", name, Collections.emptyList());
+ }
+
+ private void checkAbsent(ClassSubject clazz, String returnType, String name, List<String> args) {
assertTrue(clazz.isPresent());
- MethodSubject method = clazz.method("boolean", name, Collections.emptyList());
+ MethodSubject method = clazz.method(returnType, name, args);
assertFalse(method.isPresent());
}
@@ -134,20 +139,24 @@
DexInspector inspector = new DexInspector(getGeneratedDexFile().toAbsolutePath(),
getGeneratedProguardMap());
ClassSubject clazz = inspector.clazz("inlining.Inlining");
+
// Simple constant inlining.
- checkAbsent(clazz, "longExpression");
- checkAbsent(clazz, "intExpression");
- checkAbsent(clazz, "doubleExpression");
- checkAbsent(clazz, "floatExpression");
+ checkAbsentBooleanMethod(clazz, "longExpression");
+ checkAbsentBooleanMethod(clazz, "intExpression");
+ checkAbsentBooleanMethod(clazz, "doubleExpression");
+ checkAbsentBooleanMethod(clazz, "floatExpression");
// Simple return argument inlining.
- checkAbsent(clazz, "longArgumentExpression");
- checkAbsent(clazz, "intArgumentExpression");
- checkAbsent(clazz, "doubleArgumentExpression");
- checkAbsent(clazz, "floatArgumentExpression");
+ checkAbsentBooleanMethod(clazz, "longArgumentExpression");
+ checkAbsentBooleanMethod(clazz, "intArgumentExpression");
+ checkAbsentBooleanMethod(clazz, "doubleArgumentExpression");
+ checkAbsentBooleanMethod(clazz, "floatArgumentExpression");
+ // Static method calling interface method. The interface method implementation is in
+ // a private class in another package.
+ checkAbsent(clazz, "int", "callInterfaceMethod", ImmutableList.of("inlining.IFace"));
clazz = inspector.clazz("inlining.Nullability");
- checkAbsent(clazz, "inlinableWithPublicField");
- checkAbsent(clazz, "inlinableWithControlFlow");
+ checkAbsentBooleanMethod(clazz, "inlinableWithPublicField");
+ checkAbsentBooleanMethod(clazz, "inlinableWithControlFlow");
}
@Test
diff --git a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
index f3fac51..bdedf43 100644
--- a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
+++ b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
@@ -117,7 +117,7 @@
static final Map<String, TestPredicate> FAILING_TESTS =
ImmutableMap.<String, TestPredicate>builder()
// Other failures on various older runtimes.
- .put("LineTableDuplicatesTest", or(RunJdwpTests::isJava, RunJdwpTests::isAndroidLOrAbove))
+ .put("LineTableDuplicatesTest", or(RunJdwpTests::isJava, RunJdwpTests::isAndroidNOrAbove))
.put("ArrayReference.GetValuesTest", RunJdwpTests::isAndroidLOrAbove)
.put("ArrayReference.LengthTest", RunJdwpTests::isAndroidLOrAbove)
.put("ArrayReference.SetValues003Test", RunJdwpTests::isAndroidNOrAbove)