Revert "Enhance visibility check when rebinding fields."
This reverts commit 72c2306fcacc2e98e790f83b42c02705db8123cf.
Reason: causes failures on the AOSP build.
Bug: 77944861, 76025099, 76447395, 76191597
Change-Id: I71e85c3d05e1d0332aa2a8a2418b87b594513180
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 678ddae..7eb771c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -205,7 +205,7 @@
}
return NEVER;
} else {
- /* package-private */
+ /* package-private */
return targetHolder.isSamePackage(contextHolder) ? PACKAGE : NEVER;
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 3372a20..de171a3 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -11,9 +11,8 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
-import java.util.Map;
+import com.google.common.collect.Sets;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -125,7 +124,7 @@
// Rebind to the lowest library class or program class.
if (target != null && target.method != method) {
DexClass targetClass = appInfo.definitionFor(target.method.holder);
- // If the target class is not public but the targeted method is, we might run into
+ // If the targetclass is not public but the targeted method is, we might run into
// visibility problems when rebinding.
if (!targetClass.accessFlags.isPublic() && target.accessFlags.isPublic()) {
// If the original class is public and this method is public, it might have been called
@@ -179,37 +178,27 @@
return null;
}
- private void computeFieldRebinding(Map<DexField, Set<DexEncodedMethod>> fields,
+ private void computeFieldRebinding(Set<DexField> fields,
BiFunction<DexType, DexField, DexEncodedField> lookup,
BiFunction<DexClass, DexField, DexEncodedField> lookupTargetOnClass) {
- for (Map.Entry<DexField, Set<DexEncodedMethod>> entry : fields.entrySet()) {
- DexField field = entry.getKey();
+ for (DexField field : fields) {
field = lense.lookupField(field, null);
DexEncodedField target = lookup.apply(field.getHolder(), field);
// Rebind to the lowest library class or program class. Do not rebind accesses to fields that
- // are not visible from the access context.
- Set<DexEncodedMethod> contexts = entry.getValue();
- if (target != null && target.field != field && contexts.stream().allMatch(context ->
- isVisibleFromOriginalContext(context.method.getHolder(), target))) {
+ // are not public, as this might lead to access violation errors.
+ if (target != null && target.field != field && isVisibleFromOtherClasses(target)) {
builder.map(field, validTargetFor(target.field, field, lookupTargetOnClass));
}
}
}
- private boolean isVisibleFromOriginalContext(DexType context, DexEncodedField field) {
- DexType holderType = field.field.getHolder();
- DexClass holder = appInfo.definitionFor(holderType);
- if (holder == null) {
- return false;
+ private boolean isVisibleFromOtherClasses(DexEncodedField field) {
+ // If the field is not public, the visibility on the class can not be a further constraint.
+ if (!field.accessFlags.isPublic()) {
+ return true;
}
- Constraint classVisibility =
- Constraint.deriveConstraint(context, holderType, holder.accessFlags, appInfo);
- if (classVisibility == Constraint.NEVER) {
- return false;
- }
- Constraint fieldVisibility =
- Constraint.deriveConstraint(context, holderType, field.accessFlags, appInfo);
- return fieldVisibility != Constraint.NEVER;
+ // If the field is public, then a non-public holder class will further constrain visibility.
+ return appInfo.definitionFor(field.field.getHolder()).accessFlags.isPublic();
}
public GraphLense run() {
@@ -224,15 +213,10 @@
// Likewise static invokes.
computeMethodRebinding(appInfo.staticInvokes, this::anyLookup);
- computeFieldRebinding(appInfo.staticFieldReads,
+ computeFieldRebinding(Sets.union(appInfo.staticFieldReads, appInfo.staticFieldWrites),
appInfo::resolveFieldOn, DexClass::lookupField);
- computeFieldRebinding(appInfo.staticFieldWrites,
+ computeFieldRebinding(Sets.union(appInfo.instanceFieldReads, appInfo.instanceFieldWrites),
appInfo::resolveFieldOn, DexClass::lookupField);
- computeFieldRebinding(appInfo.instanceFieldReads,
- appInfo::resolveFieldOn, DexClass::lookupField);
- computeFieldRebinding(appInfo.instanceFieldWrites,
- appInfo::resolveFieldOn, DexClass::lookupField);
-
return builder.build(appInfo.dexItemFactory, lense);
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index cd04989..3a31203 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -102,14 +102,10 @@
Maps.newIdentityHashMap();
private final Map<DexType, Set<DexMethod>> directInvokes = Maps.newIdentityHashMap();
private final Map<DexType, Set<DexMethod>> staticInvokes = Maps.newIdentityHashMap();
- private final Map<DexType, Set<TargetWithContext<DexField>>> instanceFieldsWritten =
- Maps.newIdentityHashMap();
- private final Map<DexType, Set<TargetWithContext<DexField>>> instanceFieldsRead =
- Maps.newIdentityHashMap();
- private final Map<DexType, Set<TargetWithContext<DexField>>> staticFieldsRead =
- Maps.newIdentityHashMap();
- private final Map<DexType, Set<TargetWithContext<DexField>>> staticFieldsWritten =
- Maps.newIdentityHashMap();
+ private final Map<DexType, Set<DexField>> instanceFieldsWritten = Maps.newIdentityHashMap();
+ private final Map<DexType, Set<DexField>> instanceFieldsRead = Maps.newIdentityHashMap();
+ private final Map<DexType, Set<DexField>> staticFieldsRead = Maps.newIdentityHashMap();
+ private final Map<DexType, Set<DexField>> staticFieldsWritten = Maps.newIdentityHashMap();
private final ProtoLiteExtension protoLiteExtension;
private final Set<DexField> protoLiteFields = Sets.newIdentityHashSet();
@@ -368,7 +364,7 @@
@Override
public boolean registerInstanceFieldWrite(DexField field) {
- if (!registerItemWithTargetAndContext(instanceFieldsWritten, field, currentMethod)) {
+ if (!registerItemWithTarget(instanceFieldsWritten, field)) {
return false;
}
if (Log.ENABLED) {
@@ -381,7 +377,7 @@
@Override
public boolean registerInstanceFieldRead(DexField field) {
- if (!registerItemWithTargetAndContext(instanceFieldsRead, field, currentMethod)) {
+ if (!registerItemWithTarget(instanceFieldsRead, field)) {
return false;
}
if (Log.ENABLED) {
@@ -399,7 +395,7 @@
@Override
public boolean registerStaticFieldRead(DexField field) {
- if (!registerItemWithTargetAndContext(staticFieldsRead, field, currentMethod)) {
+ if (!registerItemWithTarget(staticFieldsRead, field)) {
return false;
}
if (Log.ENABLED) {
@@ -411,7 +407,7 @@
@Override
public boolean registerStaticFieldWrite(DexField field) {
- if (!registerItemWithTargetAndContext(staticFieldsWritten, field, currentMethod)) {
+ if (!registerItemWithTarget(staticFieldsWritten, field)) {
return false;
}
if (Log.ENABLED) {
@@ -1239,41 +1235,34 @@
}
}
- private Map<DexField, Set<DexEncodedMethod>> collectFields(
- Map<DexType, Set<TargetWithContext<DexField>>> map) {
- Map<DexField, Set<DexEncodedMethod>> result = new IdentityHashMap<>();
- for (Map.Entry<DexType, Set<TargetWithContext<DexField>>> entry : map.entrySet()) {
- for (TargetWithContext<DexField> fieldWithContext : entry.getValue()) {
- DexField field = fieldWithContext.getTarget();
- DexEncodedMethod context = fieldWithContext.getContext();
- result.computeIfAbsent(field, k -> Sets.newIdentityHashSet())
- .add(context);
- }
- }
- return result;
+ private Set<DexField> collectFields(Map<DexType, Set<DexField>> map) {
+ return map.values().stream().flatMap(Collection::stream)
+ .collect(Collectors.toCollection(Sets::newIdentityHashSet));
}
- Map<DexField, Set<DexEncodedMethod>> collectInstanceFieldsRead() {
- return Collections.unmodifiableMap(collectFields(instanceFieldsRead));
+ SortedSet<DexField> collectInstanceFieldsRead() {
+ return ImmutableSortedSet.copyOf(
+ PresortedComparable<DexField>::slowCompareTo, collectFields(instanceFieldsRead));
}
- Map<DexField, Set<DexEncodedMethod>> collectInstanceFieldsWritten() {
- return Collections.unmodifiableMap(collectFields(instanceFieldsWritten));
+ SortedSet<DexField> collectInstanceFieldsWritten() {
+ return ImmutableSortedSet.copyOf(
+ PresortedComparable<DexField>::slowCompareTo, collectFields(instanceFieldsWritten));
}
- Map<DexField, Set<DexEncodedMethod>> collectStaticFieldsRead() {
- return Collections.unmodifiableMap(collectFields(staticFieldsRead));
+ SortedSet<DexField> collectStaticFieldsRead() {
+ return ImmutableSortedSet.copyOf(
+ PresortedComparable<DexField>::slowCompareTo, collectFields(staticFieldsRead));
}
- Map<DexField, Set<DexEncodedMethod>> collectStaticFieldsWritten() {
- return Collections.unmodifiableMap(collectFields(staticFieldsWritten));
+ SortedSet<DexField> collectStaticFieldsWritten() {
+ return ImmutableSortedSet.copyOf(
+ PresortedComparable<DexField>::slowCompareTo, collectFields(staticFieldsWritten));
}
- private Set<DexField> collectReachedFields(
- Set<DexField> set, Function<DexField, DexField> lookup) {
- return set.stream()
- .map(lookup)
- .filter(Objects::nonNull)
+ private Set<DexField> collectReachedFields(Map<DexType, Set<DexField>> map,
+ Function<DexField, DexField> lookup) {
+ return map.values().stream().flatMap(set -> set.stream().map(lookup).filter(Objects::nonNull))
.collect(Collectors.toCollection(Sets::newIdentityHashSet));
}
@@ -1287,11 +1276,16 @@
return target == null ? null : target.field;
}
- SortedSet<DexField> mergeFieldAccesses(Set<DexField> instanceFields, Set<DexField> staticFields) {
+ SortedSet<DexField> collectFieldsRead() {
return ImmutableSortedSet.copyOf(PresortedComparable<DexField>::slowCompareTo,
- Sets.union(
- collectReachedFields(instanceFields, this::tryLookupInstanceField),
- collectReachedFields(staticFields, this::tryLookupStaticField)));
+ Sets.union(collectReachedFields(instanceFieldsRead, this::tryLookupInstanceField),
+ collectReachedFields(staticFieldsRead, this::tryLookupStaticField)));
+ }
+
+ SortedSet<DexField> collectFieldsWritten() {
+ return ImmutableSortedSet.copyOf(PresortedComparable<DexField>::slowCompareTo,
+ Sets.union(collectReachedFields(instanceFieldsWritten, this::tryLookupInstanceField),
+ collectReachedFields(staticFieldsWritten, this::tryLookupStaticField)));
}
private void markClassAsInstantiatedWithCompatRule(DexClass clazz) {
@@ -1462,21 +1456,21 @@
*/
public final SortedSet<DexField> fieldsWritten;
/**
- * Set of all field ids used in instance field reads, along with access context.
+ * Set of all field ids used in instance field reads.
*/
- public final Map<DexField, Set<DexEncodedMethod>> instanceFieldReads;
+ public final SortedSet<DexField> instanceFieldReads;
/**
- * Set of all field ids used in instance field writes, along with access context.
+ * Set of all field ids used in instance field writes.
*/
- public final Map<DexField, Set<DexEncodedMethod>> instanceFieldWrites;
+ public final SortedSet<DexField> instanceFieldWrites;
/**
- * Set of all field ids used in static static field reads, along with access context.
+ * Set of all field ids used in static static field reads.
*/
- public final Map<DexField, Set<DexEncodedMethod>> staticFieldReads;
+ public final SortedSet<DexField> staticFieldReads;
/**
- * Set of all field ids used in static field writes, along with access context.
+ * Set of all field ids used in static field writes.
*/
- public final Map<DexField, Set<DexEncodedMethod>> staticFieldWrites;
+ public final SortedSet<DexField> staticFieldWrites;
/**
* Set of all methods referenced in virtual invokes;
*/
@@ -1548,10 +1542,8 @@
this.instanceFieldWrites = enqueuer.collectInstanceFieldsWritten();
this.staticFieldReads = enqueuer.collectStaticFieldsRead();
this.staticFieldWrites = enqueuer.collectStaticFieldsWritten();
- this.fieldsRead = enqueuer.mergeFieldAccesses(
- instanceFieldReads.keySet(), staticFieldReads.keySet());
- this.fieldsWritten = enqueuer.mergeFieldAccesses(
- instanceFieldWrites.keySet(), staticFieldWrites.keySet());
+ this.fieldsRead = enqueuer.collectFieldsRead();
+ this.fieldsWritten = enqueuer.collectFieldsWritten();
this.pinnedItems = rewritePinnedItemsToDescriptors(enqueuer.pinnedItems);
this.virtualInvokes = joinInvokedMethods(enqueuer.virtualInvokes);
this.interfaceInvokes = joinInvokedMethods(enqueuer.interfaceInvokes);
@@ -1567,8 +1559,8 @@
this.prunedTypes = Collections.emptySet();
this.switchMaps = Collections.emptyMap();
this.ordinalsMaps = Collections.emptyMap();
- assert Sets.intersection(instanceFieldReads.keySet(), staticFieldReads.keySet()).isEmpty();
- assert Sets.intersection(instanceFieldWrites.keySet(), staticFieldWrites.keySet()).isEmpty();
+ assert Sets.intersection(instanceFieldReads, staticFieldReads).size() == 0;
+ assert Sets.intersection(instanceFieldWrites, staticFieldWrites).size() == 0;
}
private AppInfoWithLiveness(AppInfoWithLiveness previous, DexApplication application,
@@ -1601,8 +1593,8 @@
this.prunedTypes = mergeSets(previous.prunedTypes, removedClasses);
this.switchMaps = previous.switchMaps;
this.ordinalsMaps = previous.ordinalsMaps;
- assert Sets.intersection(instanceFieldReads.keySet(), staticFieldReads.keySet()).isEmpty();
- assert Sets.intersection(instanceFieldWrites.keySet(), staticFieldWrites.keySet()).isEmpty();
+ assert Sets.intersection(instanceFieldReads, staticFieldReads).size() == 0;
+ assert Sets.intersection(instanceFieldWrites, staticFieldWrites).size() == 0;
}
private AppInfoWithLiveness(AppInfoWithLiveness previous,
@@ -1614,14 +1606,10 @@
this.targetedMethods = rewriteItems(previous.targetedMethods, lense::lookupMethod);
this.liveMethods = rewriteItems(previous.liveMethods, lense::lookupMethod);
this.liveFields = rewriteItems(previous.liveFields, lense::lookupField);
- this.instanceFieldReads =
- rewriteKeysWhileMergingValues(previous.instanceFieldReads, lense::lookupField);
- this.instanceFieldWrites =
- rewriteKeysWhileMergingValues(previous.instanceFieldWrites, lense::lookupField);
- this.staticFieldReads =
- rewriteKeysWhileMergingValues(previous.staticFieldReads, lense::lookupField);
- this.staticFieldWrites =
- rewriteKeysWhileMergingValues(previous.staticFieldWrites, lense::lookupField);
+ this.instanceFieldReads = rewriteItems(previous.instanceFieldReads, lense::lookupField);
+ this.instanceFieldWrites = rewriteItems(previous.instanceFieldWrites, lense::lookupField);
+ this.staticFieldReads = rewriteItems(previous.staticFieldReads, lense::lookupField);
+ this.staticFieldWrites = rewriteItems(previous.staticFieldWrites, lense::lookupField);
this.fieldsRead = rewriteItems(previous.fieldsRead, lense::lookupField);
this.fieldsWritten = rewriteItems(previous.fieldsWritten, lense::lookupField);
this.pinnedItems = rewriteMixedItems(previous.pinnedItems, lense);
@@ -1647,8 +1635,8 @@
this.ordinalsMaps = rewriteKeys(previous.ordinalsMaps, lense::lookupType);
this.protoLiteFields = previous.protoLiteFields;
// Sanity check sets after rewriting.
- assert Sets.intersection(instanceFieldReads.keySet(), staticFieldReads.keySet()).isEmpty();
- assert Sets.intersection(instanceFieldWrites.keySet(), staticFieldWrites.keySet()).isEmpty();
+ assert Sets.intersection(instanceFieldReads, staticFieldReads).isEmpty();
+ assert Sets.intersection(instanceFieldWrites, staticFieldWrites).isEmpty();
}
public AppInfoWithLiveness(AppInfoWithLiveness previous,
@@ -1783,18 +1771,6 @@
return builder.build();
}
- private static <T extends PresortedComparable<T>, S> Map<T, Set<S>>
- rewriteKeysWhileMergingValues(
- Map<T, Set<S>> original, BiFunction<T, DexEncodedMethod, T> rewrite) {
- Map<T, Set<S>> result = new IdentityHashMap<>();
- for (T item : original.keySet()) {
- T rewrittenKey = rewrite.apply(item, null);
- result.computeIfAbsent(rewrittenKey, k -> Sets.newIdentityHashSet())
- .addAll(original.get(item));
- }
- return Collections.unmodifiableMap(result);
- }
-
private static ImmutableSet<DexItem> rewriteMixedItems(
Set<DexItem> original, GraphLense lense) {
ImmutableSet.Builder<DexItem> builder = ImmutableSet.builder();
@@ -2146,10 +2122,6 @@
return target;
}
- public DexEncodedMethod getContext() {
- return context;
- }
-
@Override
public int hashCode() {
return target.hashCode() * 31 + context.hashCode();
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index 923398d..4d7240e 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -550,6 +550,24 @@
// Tests where the output of R8 fails when run with Art.
private static final Multimap<String, TestCondition> failingRunWithArt =
new ImmutableListMultimap.Builder<String, TestCondition>()
+ // This test relies on specific field access patterns, which we rewrite.
+ .put("064-field-access",
+ TestCondition.match(
+ TestCondition.R8DEX_NOT_AFTER_D8_COMPILER,
+ TestCondition.runtimesUpTo(DexVm.Version.V4_4_4)))
+ .put("064-field-access",
+ TestCondition.match(
+ TestCondition.R8DEX_COMPILER,
+ TestCondition.runtimes(
+ DexVm.Version.DEFAULT, DexVm.Version.V7_0_0, DexVm.Version.V6_0_1,
+ DexVm.Version.V5_1_1)))
+ .put("064-field-access",
+ TestCondition.match(
+ TestCondition.tools(DexTool.NONE),
+ TestCondition.D8_AFTER_R8CF_COMPILER,
+ TestCondition.runtimes(
+ DexVm.Version.DEFAULT, DexVm.Version.V7_0_0, DexVm.Version.V6_0_1,
+ DexVm.Version.V5_1_1)))
// The growth limit test fails after processing by R8 because R8 will eliminate an
// "unneeded" const store. The following reflective call to the VM's GC will then see the
// large array as still live and the subsequent allocations will fail to reach the desired
diff --git a/src/test/java/com/android/tools/r8/regress/B76025099.java b/src/test/java/com/android/tools/r8/regress/B76025099.java
index 767420b..9fa694d 100644
--- a/src/test/java/com/android/tools/r8/regress/B76025099.java
+++ b/src/test/java/com/android/tools/r8/regress/B76025099.java
@@ -3,9 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.regress;
-import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
@@ -13,113 +11,50 @@
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.VmTestRunner;
-import com.android.tools.r8.code.InvokeDirect;
-import com.android.tools.r8.code.IputObject;
-import com.android.tools.r8.code.ReturnVoid;
-import com.android.tools.r8.graph.DexCode;
-import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.DexInspector;
-import com.android.tools.r8.utils.DexInspector.ClassSubject;
-import com.android.tools.r8.utils.DexInspector.MethodSubject;
import com.android.tools.r8.utils.FileUtils;
import com.google.common.collect.ImmutableList;
-import java.io.File;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import regress_76025099.Main;
-import regress_76025099.impl.Impl;
@RunWith(VmTestRunner.class)
public class B76025099 extends TestBase {
+
private static final String PRG =
ToolHelper.EXAMPLES_BUILD_DIR + "regress_76025099" + FileUtils.JAR_EXTENSION;
- private AndroidApp runR8(AndroidApp app) throws Exception {
+ private AndroidApp runR8(AndroidApp app, Class main, Path out) throws Exception {
R8Command command =
ToolHelper.addProguardConfigurationConsumer(
ToolHelper.prepareR8CommandBuilder(app),
pgConfig -> {
pgConfig.setPrintMapping(true);
- pgConfig.setPrintMappingFile(map);
+ pgConfig.setPrintMappingFile(out.resolve(ToolHelper.DEFAULT_PROGUARD_MAP_FILE));
})
- .addProguardConfigurationFiles(pgConfig)
- .setOutput(tempRoot.toPath(), OutputMode.DexIndexed)
+ .addProguardConfiguration(
+ ImmutableList.of(keepMainProguardConfiguration(main)),
+ Origin.unknown())
+ .setOutput(out, OutputMode.DexIndexed)
.build();
return ToolHelper.runR8(command, o -> {
o.enableMinification = false;
});
}
- private File tempRoot;
- private Path jarPath;
- private AndroidApp originalApp;
- private String mainName;
- private Path pgConfig;
- private Path map;
-
- @Before
- public void setUp() throws Exception {
- tempRoot = temp.getRoot();
- jarPath = Paths.get(PRG);
- originalApp = readJar(jarPath);
- mainName = Main.class.getCanonicalName();
- pgConfig = File.createTempFile("keep-rules", ".config", tempRoot).toPath();
- String config = keepMainProguardConfiguration(Main.class);
- config += System.lineSeparator() + "-dontobfuscate";
- Files.write(pgConfig, config.getBytes());
- map = File.createTempFile("proguard", ".map", tempRoot).toPath();
- }
-
+ @Ignore("b/76025099")
@Test
- public void testProguardAndD8() throws Exception {
- if (!isRunProguard()) {
- return;
- }
-
+ public void test() throws Exception {
+ Path out = temp.getRoot().toPath();
+ Path jarPath = Paths.get(PRG);
+ String mainName = Main.class.getCanonicalName();
ProcessResult jvmOutput = ToolHelper.runJava(ImmutableList.of(jarPath), mainName);
assertEquals(0, jvmOutput.exitCode);
-
- Path proguarded =
- File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, tempRoot).toPath();
- ProcessResult proguardResult = ToolHelper.runProguardRaw(jarPath, proguarded, pgConfig, map);
- assertEquals(0, proguardResult.exitCode);
-
- AndroidApp processedApp = ToolHelper.runD8(readJar(proguarded));
- verifyFieldAccess(processedApp, jvmOutput);
- }
-
- @Test
- public void testR8() throws Exception {
- ProcessResult jvmOutput = ToolHelper.runJava(ImmutableList.of(jarPath), mainName);
- assertEquals(0, jvmOutput.exitCode);
-
- AndroidApp processedApp = runR8(originalApp);
- verifyFieldAccess(processedApp, jvmOutput);
- }
-
- private void verifyFieldAccess(AndroidApp processedApp, ProcessResult jvmOutput)
- throws Exception {
- DexInspector inspector = new DexInspector(processedApp);
- ClassSubject impl = inspector.clazz(Impl.class);
- assertThat(impl, isPresent());
- MethodSubject init = impl.init(ImmutableList.of("java.lang.String"));
- assertThat(init, isPresent());
- DexCode dexCode = init.getMethod().getCode().asDexCode();
- checkInstructions(dexCode, ImmutableList.of(
- InvokeDirect.class,
- IputObject.class,
- ReturnVoid.class
- ));
- IputObject iput = (IputObject) dexCode.instructions[1];
- DexField fld = iput.getField();
- assertEquals("name", fld.name.toString());
- assertEquals("regress_76025099.impl.Impl", fld.getHolder().toSourceString());
-
+ AndroidApp processedApp = runR8(readJar(jarPath), Main.class, out);
ProcessResult artOutput = runOnArtRaw(processedApp, mainName);
assertEquals(0, artOutput.exitCode);
assertEquals(jvmOutput.stdout, artOutput.stdout);
diff --git a/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTestRunner.java b/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTestRunner.java
index 6642352..b13a08e 100644
--- a/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTestRunner.java
+++ b/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTestRunner.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.resolution;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.CompilationMode;
@@ -45,11 +46,12 @@
assertEquals(0, runInput.exitCode);
Path outDex = temp.getRoot().toPath().resolve("dex.zip");
build(new DexIndexedConsumer.ArchiveConsumer(outDex));
- ProcessResult runDex = ToolHelper.runArtNoVerificationErrorsRaw(
+ // TODO(b/76191597): Change to runArtNoVerificationErrors + assertEquals when bug is fixed
+ ProcessResult runDex = ToolHelper.runArtRaw(
outDex.toString(), CLASS.getCanonicalName());
- assertEquals(runInput.stdout, runDex.stdout);
- assertEquals(runInput.exitCode, runDex.exitCode);
- assertEquals(
+ assertNotEquals(runInput.stdout, runDex.stdout);
+ assertNotEquals(runInput.exitCode, runDex.exitCode);
+ assertNotEquals(
-1,
runDex.stderr.indexOf("java.lang.NoSuchFieldError"));
}