Ensure synthetic Unsafe helper class is placed in base split
Ensure that synthetic UNSAFE_HELPER class is mapped to FeatureSplit.BASE
so that it is always placed in the base split DEX and accessible from base
and all feature splits.
Update reproduction test to assert that the Unsafe synthetic class is
placed in base split.
Fixes: b/537973315
Change-Id: Ieee83b23a1b040aa28ce941dc1b0d03556bfede9
diff --git a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
index 742e3ce..58a313c 100644
--- a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
+++ b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
@@ -176,7 +176,8 @@
FeatureSplit feature;
boolean isSynthetic = syntheticItems.isSyntheticClass(type);
if (isSynthetic) {
- if (syntheticItems.isSyntheticOfKind(type, k -> k.ENUM_UNBOXING_SHARED_UTILITY_CLASS)) {
+ if (syntheticItems.isSyntheticOfKind(type, k -> k.ENUM_UNBOXING_SHARED_UTILITY_CLASS)
+ || syntheticItems.isSyntheticOfKind(type, k -> k.UNSAFE_HELPER)) {
return FeatureSplit.BASE;
}
feature = syntheticItems.getContextualFeatureSplitOrDefault(type, FeatureSplit.BASE);
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index 53dad9c..478d727 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -629,7 +629,8 @@
public FeatureSplit getContextualFeatureSplitOrDefault(DexType type, FeatureSplit defaultValue) {
assert isSyntheticClass(type);
- if (isSyntheticOfKind(type, kinds -> kinds.ENUM_UNBOXING_SHARED_UTILITY_CLASS)) {
+ if (isSyntheticOfKind(type, kinds -> kinds.ENUM_UNBOXING_SHARED_UTILITY_CLASS)
+ || isSyntheticOfKind(type, kinds -> kinds.UNSAFE_HELPER)) {
return FeatureSplit.BASE;
}
List<SynthesizingContext> contexts = getSynthesizingContexts(type);
diff --git a/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/AtomicFieldUpdaterFeatureSplitTest.java b/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/AtomicFieldUpdaterFeatureSplitTest.java
index 0cef0f1..aff4958 100644
--- a/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/AtomicFieldUpdaterFeatureSplitTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/AtomicFieldUpdaterFeatureSplitTest.java
@@ -20,6 +20,7 @@
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
+// This is a regression test for b/537973315.
@RunWith(Parameterized.class)
public class AtomicFieldUpdaterFeatureSplitTest extends SplitterTestBase {
@@ -43,16 +44,16 @@
.addKeepClassRules(AFeatureClass.class)
.setMinApi(parameters)
.compile()
- // TODO(b/537973315): Unsafe synthetic class is incorrectly placed in feature split.
.inspect(
- ConsumerUtils.emptyThrowingConsumer(),
- featureInspector ->
+ // The context for the Unsafe synthetic is the feature class, but it is in the base.
+ baseInspector ->
assertThat(
- featureInspector.clazz(
+ baseInspector.clazz(
SyntheticItemsTestUtils.syntheticUnsafeClass(AFeatureClass.class)),
- isPresent()))
+ isPresent()),
+ ConsumerUtils.emptyThrowingConsumer())
.run(parameters.getRuntime(), BBaseClass.class)
- .assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
+ .assertSuccessWithOutputLines("World!");
}
public static class AFeatureClass {}