Merge "Ignore monitor exit for field load elimination"
diff --git a/src/main/java/com/android/tools/r8/ir/code/Monitor.java b/src/main/java/com/android/tools/r8/ir/code/Monitor.java
index 6b3c89c..3b1b2d1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Monitor.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Monitor.java
@@ -34,6 +34,14 @@
return inValues.get(0);
}
+ public boolean isEnter() {
+ return type == Type.ENTER;
+ }
+
+ public boolean isExit() {
+ return type == Type.EXIT;
+ }
+
@Override
public void buildDex(DexBuilder builder) {
// If the monitor object is an argument, we use the argument register for all the monitor
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
index dee935e..905d4a8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
@@ -132,7 +132,8 @@
}
}
}
- if (instruction.isMonitor() || instruction.isInvokeMethod()) {
+ if ((instruction.isMonitor() && instruction.asMonitor().isEnter())
+ || instruction.isInvokeMethod()) {
killAllActiveFields();
}
}
diff --git a/src/test/java/com/android/tools/r8/regress/b111250398/B111250398.java b/src/test/java/com/android/tools/r8/regress/b111250398/B111250398.java
index 90fba5f..84fc5c4 100644
--- a/src/test/java/com/android/tools/r8/regress/b111250398/B111250398.java
+++ b/src/test/java/com/android/tools/r8/regress/b111250398/B111250398.java
@@ -91,6 +91,16 @@
t = f;
}
+ public void mfWithMonitor() {
+ t = f;
+ synchronized (this) {
+ t = f;
+ t = f;
+ }
+ t = f;
+ t = f;
+ }
+
public void msf() {
t = sf;
t = sf;
@@ -231,6 +241,8 @@
assertThat(classA, isPresent());
MethodSubject mfOnA = classA.method("void", "mf", ImmutableList.of());
assertThat(mfOnA, isPresent());
+ MethodSubject mfWithMonitorOnA = classA.method("void", "mfWithMonitor", ImmutableList.of());
+ assertThat(mfWithMonitorOnA, isPresent());
MethodSubject msfOnA = classA.method("void", "msf", ImmutableList.of());
assertThat(msfOnA, isPresent());
MethodSubject mvOnA = classA.method("void", "mv", ImmutableList.of());
@@ -264,6 +276,13 @@
// compilation (R8) will eliminate field loads on non-volatile fields.
assertEquals(1, countIget(mfOnA.getMethod().getCode().asDexCode(), fOnA.getField().field));
assertEquals(1, countSget(msfOnA.getMethod().getCode().asDexCode(), sfOnA.getField().field));
+ // TODO(111380066). This could be 2 in stead of 4, but right now the optimization tracks the
+ // combined set of fields for all successors, and for synchronized code all blocks have
+ // exceptional edges for ensuring monitor exit causing the active load to be invalidated for
+ // both normal and exceptional successors.
+ assertEquals(4,
+ countIget(mfWithMonitorOnA.getMethod().getCode().asDexCode(), fOnA.getField().field));
+
// For fields on other class both separate compilation (D8) and whole program
// compilation (R8) will differ in the eliminated field loads of non-volatile fields.
assertEquals(mfOnBGets,