Add phi check when checking in value definition in service rewriter
Bug: 162568140
Change-Id: I193475d8fbff5e8b53775d38a159181b392c1183
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
index 71a2a18..3b3d15d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
@@ -137,8 +137,11 @@
continue;
}
- // Check that ClassLoader used is the ClassLoader defined for the the service configuration
+ // Check that ClassLoader used is the ClassLoader defined for the service configuration
// that we are instantiating or NULL.
+ if (serviceLoaderLoad.inValues().get(1).isPhi()) {
+ continue;
+ }
InvokeVirtual classLoaderInvoke =
serviceLoaderLoad.inValues().get(1).definition.asInvokeVirtual();
boolean isGetClassLoaderOnConstClassOrNull =
diff --git a/src/test/java/com/android/tools/r8/rewrite/ServiceLoaderRewritingTest.java b/src/test/java/com/android/tools/r8/rewrite/ServiceLoaderRewritingTest.java
index 5e18734..cd7964f 100644
--- a/src/test/java/com/android/tools/r8/rewrite/ServiceLoaderRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/ServiceLoaderRewritingTest.java
@@ -135,6 +135,20 @@
}
}
+ public static class LoadWhereClassLoaderIsPhi {
+
+ public static void main(String[] args) {
+ ServiceLoader.load(
+ Service.class,
+ System.currentTimeMillis() > 0
+ ? Thread.currentThread().getContextClassLoader()
+ : null)
+ .iterator()
+ .next()
+ .print();
+ }
+ }
+
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimesAndApiLevels().build();
@@ -207,7 +221,7 @@
testForR8(parameters.getBackend())
.addInnerClasses(ServiceLoaderRewritingTest.class)
.addKeepMainRule(MainWithTryCatchRunner.class)
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.addDataEntryResources(
DataEntryResource.fromBytes(
StringUtils.lines(ServiceImpl.class.getTypeName(), ServiceImpl2.class.getTypeName())
@@ -267,7 +281,7 @@
.addInnerClasses(ServiceLoaderRewritingTest.class)
.addKeepMainRule(EscapingRunner.class)
.enableInliningAnnotations()
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.noMinification()
.addDataEntryResources(
DataEntryResource.fromBytes(
@@ -291,6 +305,37 @@
}
@Test
+ public void testDoNoRewriteWhenClassLoaderIsPhi()
+ throws IOException, CompilationFailedException, ExecutionException {
+ Path path = temp.newFile("out.zip").toPath();
+ CodeInspector inspector =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(ServiceLoaderRewritingTest.class)
+ .addKeepMainRule(LoadWhereClassLoaderIsPhi.class)
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .addDataEntryResources(
+ DataEntryResource.fromBytes(
+ StringUtils.lines(ServiceImpl.class.getTypeName()).getBytes(),
+ "META-INF/services/" + Service.class.getTypeName(),
+ Origin.unknown()))
+ .compile()
+ .writeToZip(path)
+ .run(parameters.getRuntime(), LoadWhereClassLoaderIsPhi.class)
+ .assertSuccessWithOutputLines("Hello World!")
+ .inspector();
+
+ // Check that we have not rewritten the calls to ServiceLoader.load.
+ assertEquals(1, getServiceLoaderLoads(inspector, LoadWhereClassLoaderIsPhi.class));
+
+ // Check that we have not removed the service configuration from META-INF/services.
+ ZipFile zip = new ZipFile(path.toFile());
+ ClassSubject serviceImpl = inspector.clazz(ServiceImpl.class);
+ assertTrue(serviceImpl.isPresent());
+ assertNotNull(zip.getEntry("META-INF/services/" + serviceImpl.getFinalName()));
+ }
+
+ @Test
public void testKeepAsOriginal()
throws IOException, CompilationFailedException, ExecutionException {
// The CL that changed behaviour after Nougat is: