summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/load_store_elimination.cc63
-rw-r--r--compiler/optimizing/optimizing_compiler_stats.h3
-rw-r--r--test/2242-checker-lse-acquire-release-operations/src/Main.java622
-rw-r--r--test/2247-checker-write-barrier-elimination/src/Main.java19
4 files changed, 621 insertions, 86 deletions
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 2e5ee84d76..e7b95c8d00 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -861,23 +861,33 @@ class LSEVisitor final : private HGraphDelegateVisitor {
}
void VisitInstanceFieldGet(HInstanceFieldGet* instruction) override {
+ HInstruction* object = instruction->InputAt(0);
if (instruction->IsVolatile()) {
- HandleAcquireLoad(instruction);
- return;
+ ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(
+ heap_location_collector_.HuntForOriginalReference(object));
+ if (!ref_info->IsSingletonAndRemovable()) {
+ HandleAcquireLoad(instruction);
+ return;
+ }
+ // Treat it as a normal load if it is a removable singleton.
}
- HInstruction* object = instruction->InputAt(0);
const FieldInfo& field = instruction->GetFieldInfo();
VisitGetLocation(instruction, heap_location_collector_.GetFieldHeapLocation(object, &field));
}
void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override {
+ HInstruction* object = instruction->InputAt(0);
if (instruction->IsVolatile()) {
- HandleReleaseStore(instruction);
- return;
+ ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(
+ heap_location_collector_.HuntForOriginalReference(object));
+ if (!ref_info->IsSingletonAndRemovable()) {
+ HandleReleaseStore(instruction);
+ return;
+ }
+ // Treat it as a normal store if it is a removable singleton.
}
- HInstruction* object = instruction->InputAt(0);
const FieldInfo& field = instruction->GetFieldInfo();
HInstruction* value = instruction->InputAt(1);
size_t idx = heap_location_collector_.GetFieldHeapLocation(object, &field);
@@ -890,8 +900,8 @@ class LSEVisitor final : private HGraphDelegateVisitor {
return;
}
- HInstruction* cls = instruction->InputAt(0);
const FieldInfo& field = instruction->GetFieldInfo();
+ HInstruction* cls = instruction->InputAt(0);
VisitGetLocation(instruction, heap_location_collector_.GetFieldHeapLocation(cls, &field));
}
@@ -901,14 +911,30 @@ class LSEVisitor final : private HGraphDelegateVisitor {
return;
}
- HInstruction* cls = instruction->InputAt(0);
const FieldInfo& field = instruction->GetFieldInfo();
+ HInstruction* cls = instruction->InputAt(0);
HInstruction* value = instruction->InputAt(1);
size_t idx = heap_location_collector_.GetFieldHeapLocation(cls, &field);
VisitSetLocation(instruction, idx, value);
}
void VisitMonitorOperation(HMonitorOperation* monitor_op) override {
+ HInstruction* object = monitor_op->InputAt(0);
+ ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(
+ heap_location_collector_.HuntForOriginalReference(object));
+ if (ref_info->IsSingletonAndRemovable()) {
+ // If the object is a removable singleton, we know that no other threads will have
+ // access to it, and we can remove the MonitorOperation instruction.
+ // MONITOR_ENTER throws when encountering a null object. If `object` is a removable
+ // singleton, it is guaranteed to be non-null so we don't have to worry about the NullCheck.
+ DCHECK(!object->CanBeNull());
+ monitor_op->GetBlock()->RemoveInstruction(monitor_op);
+ MaybeRecordStat(stats_, MethodCompilationStat::kRemovedMonitorOp);
+ return;
+ }
+
+ // We detected a monitor operation that we couldn't remove. See also LSEVisitor::Run().
+ monitor_op->GetBlock()->GetGraph()->SetHasMonitorOperations(true);
if (monitor_op->IsEnter()) {
HandleAcquireLoad(monitor_op);
} else {
@@ -2439,8 +2465,7 @@ void LSEVisitor::ProcessLoopPhiWithUnknownInput(PhiPlaceholder loop_phi_with_unk
if (load_or_store->GetBlock() != block) {
break; // End of instructions from the current block.
}
- bool is_store = load_or_store->GetSideEffects().DoesAnyWrite();
- DCHECK_EQ(is_store, IsStore(load_or_store));
+ const bool is_store = IsStore(load_or_store);
HInstruction* stored_value = nullptr;
if (is_store) {
auto it = store_records_.find(load_or_store);
@@ -2772,6 +2797,10 @@ void LSEVisitor::FindStoresWritingOldValues() {
}
void LSEVisitor::Run() {
+ // 0. Set HasMonitorOperations to false. If we encounter some MonitorOperations that we can't
+ // remove, we will set it to true in VisitMonitorOperation.
+ GetGraph()->SetHasMonitorOperations(false);
+
// 1. Process blocks and instructions in reverse post order.
for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
VisitBasicBlock(block);
@@ -2813,14 +2842,22 @@ void LSEVisitor::FinishFullLSE() {
load->ReplaceWith(substitute);
load->GetBlock()->RemoveInstruction(load);
+ if ((load->IsInstanceFieldGet() && load->AsInstanceFieldGet()->IsVolatile()) ||
+ (load->IsStaticFieldGet() && load->AsStaticFieldGet()->IsVolatile())) {
+ MaybeRecordStat(stats_, MethodCompilationStat::kRemovedVolatileLoad);
+ }
}
// Remove all the stores we can.
for (const LoadStoreRecord& record : loads_and_stores_) {
- bool is_store = record.load_or_store->GetSideEffects().DoesAnyWrite();
- DCHECK_EQ(is_store, IsStore(record.load_or_store));
- if (is_store && !kept_stores_.IsBitSet(record.load_or_store->GetId())) {
+ if (IsStore(record.load_or_store) && !kept_stores_.IsBitSet(record.load_or_store->GetId())) {
record.load_or_store->GetBlock()->RemoveInstruction(record.load_or_store);
+ if ((record.load_or_store->IsInstanceFieldSet() &&
+ record.load_or_store->AsInstanceFieldSet()->IsVolatile()) ||
+ (record.load_or_store->IsStaticFieldSet() &&
+ record.load_or_store->AsStaticFieldSet()->IsVolatile())) {
+ MaybeRecordStat(stats_, MethodCompilationStat::kRemovedVolatileStore);
+ }
}
}
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index 4549af3cbf..60d18d2f24 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -50,6 +50,9 @@ enum class MethodCompilationStat {
kRemovedDeadPhi,
kRemovedTry,
kRemovedNullCheck,
+ kRemovedVolatileLoad,
+ kRemovedVolatileStore,
+ kRemovedMonitorOp,
kNotCompiledSkipped,
kNotCompiledInvalidBytecode,
kNotCompiledThrowCatchLoop,
diff --git a/test/2242-checker-lse-acquire-release-operations/src/Main.java b/test/2242-checker-lse-acquire-release-operations/src/Main.java
index 433a4cd343..4db0f359ef 100644
--- a/test/2242-checker-lse-acquire-release-operations/src/Main.java
+++ b/test/2242-checker-lse-acquire-release-operations/src/Main.java
@@ -24,63 +24,126 @@ class TestClass {
public class Main {
public static void main(String[] args) {
// Volatile accesses.
- assertEquals($noinline$testVolatileAccessesMustBeKept(new TestClass()), 3);
+ assertEquals(3, $noinline$testVolatileAccessesMustBeKept(new TestClass()));
+ assertEquals(3, $noinline$testSingletonVolatileAccessesCanBeRemoved());
// Volatile loads - Different fields shouldn't alias.
- assertEquals($noinline$testVolatileLoadDifferentFields(new TestClass(), new TestClass()), 3);
+ assertEquals(3, $noinline$testVolatileLoadDifferentFields(new TestClass(), new TestClass()));
assertEquals(
- $noinline$testVolatileLoadDifferentFieldsBlocking(new TestClass(), new TestClass()),
- 3);
+ 3, $noinline$testVolatileLoadDifferentFieldsBlocking(new TestClass(), new TestClass()));
// Volatile loads - Redundant store.
- assertEquals($noinline$testVolatileLoadRedundantStore(new TestClass()), 2);
- assertEquals($noinline$testVolatileLoadRedundantStoreBlocking(new TestClass()), 2);
- assertEquals($noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
+ assertEquals(2, $noinline$testVolatileLoadRedundantStore(new TestClass()));
+ assertEquals(2, $noinline$testVolatileLoadRedundantStoreBlocking(new TestClass()));
+ assertEquals(2, $noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(new TestClass()));
// Volatile loads - Set and merge values.
- assertEquals($noinline$testVolatileLoadSetAndMergeValues(new TestClass(), true), 1);
- assertEquals($noinline$testVolatileLoadSetAndMergeValues(new TestClass(), false), 2);
- assertEquals($noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), true), 1);
- assertEquals($noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), false), 2);
+ assertEquals(1, $noinline$testVolatileLoadSetAndMergeValues(new TestClass(), true));
+ assertEquals(2, $noinline$testVolatileLoadSetAndMergeValues(new TestClass(), false));
+ assertEquals(1, $noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), true));
+ assertEquals(2, $noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), false));
- // Volatile stores - Different fields shouldn't alias.
- assertEquals($noinline$testVolatileStoreDifferentFields(new TestClass(), new TestClass()), 3);
+ // Volatile loads - Removal - Different fields shouldn't alias.
+ assertEquals(3,
+ $noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(
+ new TestClass(), new TestClass()));
+
+ // Volatile loads - Removal - Redundant store.
assertEquals(
- $noinline$testVolatileStoreDifferentFieldsBlocking(new TestClass(), new TestClass()),
- 3);
+ 2, $noinline$testVolatileLoadRedundantStoreRemovedSynchronization(new TestClass()));
+
+ // Volatile loads - Removal - Set and merge values.
+ assertEquals(1,
+ $noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), true));
+ assertEquals(2,
+ $noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), false));
+
+ // Volatile loads - Removal - with inlining
+ assertEquals(2, $noinline$testVolatileLoadInlineMethodWithSynchronizedScope(new TestClass()));
+
+ // Volatile stores - Different fields shouldn't alias.
+ assertEquals(3, $noinline$testVolatileStoreDifferentFields(new TestClass(), new TestClass()));
+ assertEquals(3,
+ $noinline$testVolatileStoreDifferentFieldsBlocking(new TestClass(), new TestClass()));
// Volatile stores - Redundant store.
- assertEquals($noinline$testVolatileStoreRedundantStore(new TestClass()), 2);
- assertEquals($noinline$testVolatileStoreRedundantStoreBlocking(new TestClass()), 2);
- assertEquals($noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
+ assertEquals(2, $noinline$testVolatileStoreRedundantStore(new TestClass()));
+ assertEquals(2, $noinline$testVolatileStoreRedundantStoreBlocking(new TestClass()));
+ assertEquals(2, $noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(new TestClass()));
// Volatile stores - Set and merge values.
- assertEquals($noinline$testVolatileStoreSetAndMergeValues(new TestClass(), true), 1);
- assertEquals($noinline$testVolatileStoreSetAndMergeValues(new TestClass(), false), 2);
- assertEquals($noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), true), 1);
- assertEquals($noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), false), 2);
+ assertEquals(1, $noinline$testVolatileStoreSetAndMergeValues(new TestClass(), true));
+ assertEquals(2, $noinline$testVolatileStoreSetAndMergeValues(new TestClass(), false));
+ assertEquals(1, $noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), true));
+ assertEquals(
+ 2, $noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), false));
+
+ // Volatile stores - Removal - Different fields shouldn't alias.
+ assertEquals(3,
+ $noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(
+ new TestClass(), new TestClass()));
+
+ // Volatile stores - Removal - Redundant store.
+ assertEquals(
+ 2, $noinline$testVolatileStoreRedundantStoreRemovedSynchronization(new TestClass()));
+
+ // Volatile stores - Removal - Set and merge values.
+ assertEquals(1,
+ $noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), true));
+ assertEquals(2,
+ $noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), false));
+
+ // Volatile stores - Removal - with inlining
+ assertEquals(2, $noinline$testVolatileStoreInlineMethodWithSynchronizedScope(new TestClass()));
// Monitor Operations - Different fields shouldn't alias.
+ // Make sure the static variable used for synchronization is non-null.
+ classForSync = new TestClass();
+
assertEquals(
- $noinline$testMonitorOperationDifferentFields(new TestClass(), new TestClass()), 3);
- assertEquals($noinline$testMonitorOperationDifferentFieldsBlocking(
- new TestClass(), new TestClass()),
- 3);
+ 3, $noinline$testMonitorOperationDifferentFields(new TestClass(), new TestClass()));
+ assertEquals(3,
+ $noinline$testMonitorOperationDifferentFieldsBlocking(
+ new TestClass(), new TestClass()));
// Monitor Operations - Redundant store.
- assertEquals($noinline$testMonitorOperationRedundantStore(new TestClass()), 2);
- assertEquals($noinline$testMonitorOperationRedundantStoreBlocking(new TestClass()), 2);
- assertEquals(
- $noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
- assertEquals($noinline$testMonitorOperationRedundantStoreBlockingExit(new TestClass()), 2);
+ assertEquals(2, $noinline$testMonitorOperationRedundantStore(new TestClass()));
+ assertEquals(2, $noinline$testMonitorOperationRedundantStoreBlocking(new TestClass()));
+ assertEquals(2, $noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(new TestClass()));
+ assertEquals(2, $noinline$testMonitorOperationRedundantStoreBlockingExit(new TestClass()));
// Monitor Operations - Set and merge values.
- assertEquals($noinline$testMonitorOperationSetAndMergeValues(new TestClass(), true), 1);
- assertEquals($noinline$testMonitorOperationSetAndMergeValues(new TestClass(), false), 2);
+ assertEquals(1, $noinline$testMonitorOperationSetAndMergeValues(new TestClass(), true));
+ assertEquals(2, $noinline$testMonitorOperationSetAndMergeValues(new TestClass(), false));
+ assertEquals(1, $noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), true));
+ assertEquals(
+ 2, $noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), false));
+
+ // Monitor Operations - Removal - Different fields shouldn't alias.
+ assertEquals(3,
+ $noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(
+ new TestClass(), new TestClass()));
+
+ // Monitor Operations - Removal - Redundant store.
assertEquals(
- $noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), true), 1);
+ 2, $noinline$testMonitorOperationRedundantStoreRemovedSynchronization(new TestClass()));
+
+ // Monitor Operations - Removal - Set and merge values.
+ assertEquals(1,
+ $noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), true));
+ assertEquals(2,
+ $noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(
+ new TestClass(), false));
+
+ // Monitor Operations - Removal - with inlining
+ assertEquals(2, $noinline$testMonitorOperationInlineSynchronizedMethod(new TestClass()));
assertEquals(
- $noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), false), 2);
+ 2, $noinline$testMonitorOperationInlineMethodWithSynchronizedScope(new TestClass()));
}
public static void assertEquals(int expected, int result) {
@@ -114,6 +177,31 @@ public class Main {
return result;
}
+ /// CHECK-START: int Main.$noinline$testSingletonVolatileAccessesCanBeRemoved() load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testSingletonVolatileAccessesCanBeRemoved() load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testSingletonVolatileAccessesCanBeRemoved() load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+ static int $noinline$testSingletonVolatileAccessesCanBeRemoved() {
+ Main m = new Main();
+ int result;
+ m.vi = 3;
+ // Redundant load can be removed.
+ result = m.vi;
+ result = m.vi;
+ // Redundant store can be removed.
+ m.vi = 3;
+ result = m.vi;
+ return result;
+ }
+
/// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
@@ -288,6 +376,136 @@ public class Main {
return obj.i;
}
+ /// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileLoadDifferentFieldsRemovedSynchronization(
+ TestClass obj1, TestClass obj2) {
+ Main m = new Main();
+
+ obj1.i = 1;
+ obj2.j = 2;
+ int unused = m.vi;
+
+ return obj1.i + obj2.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileLoadRedundantStoreRemovedSynchronization(TestClass obj) {
+ Main m = new Main();
+
+ obj.j = 1;
+ int unused = m.vi;
+ obj.j = 2;
+ unused = m.vi;
+
+ return obj.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (before)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldGet field_name:Main.vi
+ /// CHECK-DAG: InstanceFieldGet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK: Phi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileLoadSetAndMergeValuesRemovedSynchronization(
+ TestClass obj, boolean b) {
+ Main m = new Main();
+
+ if (b) {
+ obj.i = 1;
+ } else {
+ obj.i = 2;
+ }
+ int unused = m.vi;
+ return obj.i;
+ }
+
+ // Can't eliminate the setters, or volatile getters in this method.
+
+ /// CHECK-START: int Main.$inline$SetterWithVolatileLoads(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$inline$SetterWithVolatileLoads(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ int $inline$SetterWithVolatileLoads(TestClass obj) {
+ obj.j = 1;
+ int unused = this.vi;
+ obj.j = 2;
+ unused = this.vi;
+ return obj.j;
+ }
+
+ // But we can eliminate once inlined.
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileLoadInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK-NOT: InstanceFieldSet field_name:TestClass.j
+ static int $noinline$testVolatileLoadInlineMethodWithSynchronizedScope(TestClass obj) {
+ Main m = new Main();
+ return m.$inline$SetterWithVolatileLoads(obj);
+ }
+
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
@@ -462,6 +680,136 @@ public class Main {
return obj.i;
}
+ /// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileStoreDifferentFieldsRemovedSynchronization(
+ TestClass obj1, TestClass obj2) {
+ Main m = new Main();
+
+ obj1.i = 1;
+ obj2.j = 2;
+ m.vi = 123;
+
+ return obj1.i + obj2.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileStoreRedundantStoreRemovedSynchronization(TestClass obj) {
+ Main m = new Main();
+
+ obj.j = 1;
+ m.vi = 123;
+ obj.j = 2;
+ m.vi = 123;
+
+ return obj.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (before)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldGet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK: Phi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testVolatileStoreSetAndMergeValuesRemovedSynchronization(
+ TestClass obj, boolean b) {
+ Main m = new Main();
+
+ if (b) {
+ obj.i = 1;
+ } else {
+ obj.i = 2;
+ }
+ m.vi = 123;
+ return obj.i;
+ }
+
+ // Can't eliminate the setters in this method.
+
+ /// CHECK-START: int Main.$inline$SetterWithVolatileStores(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$inline$SetterWithVolatileStores(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ int $inline$SetterWithVolatileStores(TestClass obj) {
+ obj.j = 1;
+ this.vi = 123;
+ obj.j = 2;
+ this.vi = 123;
+ return obj.j;
+ }
+
+ // But we can eliminate once inlined.
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldSet field_name:Main.vi
+
+ /// CHECK-START: int Main.$noinline$testVolatileStoreInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet field_name:TestClass.j
+ /// CHECK-NOT: InstanceFieldSet field_name:TestClass.j
+ static int $noinline$testVolatileStoreInlineMethodWithSynchronizedScope(TestClass obj) {
+ Main m = new Main();
+ return m.$inline$SetterWithVolatileStores(obj);
+ }
+
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
@@ -483,15 +831,11 @@ public class Main {
// Unrelated monitor operations shouldn't block LSE.
static int $noinline$testMonitorOperationDifferentFields(TestClass obj1, TestClass obj2) {
- Main m = new Main();
- synchronized (m) {}
-
+ synchronized (classForSync) {}
obj1.i = 1;
obj2.j = 2;
int result = obj1.i + obj2.j;
-
- synchronized (m) {}
-
+ synchronized (classForSync) {}
return result;
}
@@ -513,11 +857,9 @@ public class Main {
// A synchronized operation blocks loads.
static int $noinline$testMonitorOperationDifferentFieldsBlocking(TestClass obj1, TestClass obj2) {
- Main m = new Main();
-
obj1.i = 1;
obj2.j = 2;
- synchronized (m) {
+ synchronized (classForSync) {
return obj1.i + obj2.j;
}
}
@@ -539,12 +881,10 @@ public class Main {
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStore(TestClass obj) {
- Main m = new Main();
- synchronized (m) {
+ synchronized (classForSync) {
obj.j = 1;
obj.j = 2;
}
-
return obj.j;
}
@@ -565,13 +905,10 @@ public class Main {
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlocking(TestClass obj) {
- Main m = new Main();
-
// This store must be kept due to the monitor operation.
obj.j = 1;
- synchronized (m) {}
+ synchronized (classForSync) {}
obj.j = 2;
-
return obj.j;
}
@@ -592,13 +929,10 @@ public class Main {
/// CHECK: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(TestClass obj) {
- Main m = new Main();
-
// This store can be safely removed.
obj.j = 1;
obj.j = 2;
- synchronized (m) {}
-
+ synchronized (classForSync) {}
// This load remains due to the monitor operation.
return obj.j;
}
@@ -622,16 +956,13 @@ public class Main {
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlockingExit(TestClass obj) {
- Main m = new Main();
-
- synchronized (m) {
+ synchronized (classForSync) {
// This store can be removed.
obj.j = 0;
// This store must be kept due to the monitor exit operation.
obj.j = 1;
}
obj.j = 2;
-
return obj.j;
}
@@ -658,13 +989,11 @@ public class Main {
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationSetAndMergeValues(TestClass obj, boolean b) {
- Main m = new Main();
-
if (b) {
- synchronized (m) {}
+ synchronized (classForSync) {}
obj.i = 1;
} else {
- synchronized (m) {}
+ synchronized (classForSync) {}
obj.i = 2;
}
return obj.i;
@@ -690,6 +1019,102 @@ public class Main {
/// CHECK: InstanceFieldGet
static int $noinline$testMonitorOperationSetAndMergeValuesBlocking(TestClass obj, boolean b) {
+ if (b) {
+ obj.i = 1;
+ } else {
+ obj.i = 2;
+ }
+ synchronized (classForSync) {}
+ return obj.i;
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (before)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(TestClass, TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+
+ static int $noinline$testMonitorOperationDifferentFieldsRemovedSynchronization(
+ TestClass obj1, TestClass obj2) {
+ Main m = new Main();
+
+ obj1.i = 1;
+ obj2.j = 2;
+ synchronized (m) {}
+
+ return obj1.i + obj2.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (before)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+ static int $noinline$testMonitorOperationRedundantStoreRemovedSynchronization(TestClass obj) {
+ Main m = new Main();
+
+ obj.j = 1;
+ synchronized (m) {}
+ obj.j = 2;
+ synchronized (m) {}
+
+ return obj.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (before)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldGet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: InstanceFieldSet
+ /// CHECK-DAG: Return
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (before)
+ /// CHECK-DAG: MonitorOperation kind:enter
+ /// CHECK-DAG: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK: Phi
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(TestClass, boolean) load_store_elimination (after)
+ /// CHECK-NOT: InstanceFieldGet
+ static int $noinline$testMonitorOperationSetAndMergeValuesRemovedSynchronization(
+ TestClass obj, boolean b) {
Main m = new Main();
if (b) {
@@ -700,4 +1125,75 @@ public class Main {
synchronized (m) {}
return obj.i;
}
+
+ synchronized int $inline$synchronizedSetter(TestClass obj) {
+ obj.j = 1;
+ obj.j = 2;
+ return obj.j;
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) inliner (before)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) inliner (after)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) load_store_elimination (before)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineSynchronizedMethod(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+ static int $noinline$testMonitorOperationInlineSynchronizedMethod(TestClass obj) {
+ Main m = new Main();
+ return m.$inline$synchronizedSetter(obj);
+ }
+
+ int $inline$SetterWithSynchronizedScope(TestClass obj) {
+ synchronized (this) {
+ obj.j = 1;
+ obj.j = 2;
+ return obj.j;
+ }
+ }
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) inliner (before)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) inliner (after)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (before)
+ /// CHECK: MonitorOperation kind:enter
+ /// CHECK: MonitorOperation kind:exit
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (before)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK-NOT: MonitorOperation
+
+ /// CHECK-START: int Main.$noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass) load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldSet
+ static int $noinline$testMonitorOperationInlineMethodWithSynchronizedScope(TestClass obj) {
+ Main m = new Main();
+ return m.$inline$SetterWithSynchronizedScope(obj);
+ }
+
+ static TestClass classForSync;
+ volatile int vi;
}
diff --git a/test/2247-checker-write-barrier-elimination/src/Main.java b/test/2247-checker-write-barrier-elimination/src/Main.java
index 76fb05a2c0..c03ada30b5 100644
--- a/test/2247-checker-write-barrier-elimination/src/Main.java
+++ b/test/2247-checker-write-barrier-elimination/src/Main.java
@@ -50,8 +50,8 @@ public class Main {
// instructions that can throw.
$noinline$testInstanceFieldSetsBlocked(
new Main(), new Object(), new Object(), new Object());
- $noinline$testStaticFieldSetsBlocked(new Object(), new Object(), new Object());
- $noinline$testArraySetsSameRTIBlocked();
+ $noinline$testStaticFieldSetsBlocked(new Main(), new Object(), new Object(), new Object());
+ $noinline$testArraySetsSameRTIBlocked(new Main());
}
/// CHECK-START: Main Main.$noinline$testInstanceFieldSets(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
@@ -273,46 +273,45 @@ public class Main {
return m;
}
- /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
+ /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
/// CHECK: StaticFieldSet field_name:Main.inner_static field_type:Reference write_barrier_kind:EmitWithNullCheck
/// CHECK: InvokeStaticOrDirect method_name:Main.$noinline$emptyMethod
/// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:EmitWithNullCheck
/// CHECK: MonitorOperation kind:enter
/// CHECK: StaticFieldSet field_name:Main.inner_static3 field_type:Reference write_barrier_kind:EmitWithNullCheck
- /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
+ /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
/// CHECK: ; card_table
/// CHECK: ; card_table
/// CHECK: ; card_table
/// CHECK-NOT: ; card_table
- private static void $noinline$testStaticFieldSetsBlocked(Object o, Object o2, Object o3) {
+ private static void $noinline$testStaticFieldSetsBlocked(
+ Main m, Object o, Object o2, Object o3) {
inner_static = o;
$noinline$emptyMethod();
inner_static2 = o2;
- Main m = new Main();
synchronized (m) {
inner_static3 = o3;
}
}
- /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked() disassembly (after)
+ /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked(Main) disassembly (after)
/// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
/// CHECK: InvokeStaticOrDirect method_name:Main.$noinline$emptyMethod
/// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
/// CHECK: MonitorOperation kind:enter
/// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
- /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked() disassembly (after)
+ /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked(Main) disassembly (after)
/// CHECK: ; card_table
/// CHECK: ; card_table
/// CHECK: ; card_table
/// CHECK-NOT: ; card_table
- private static java.lang.Object[] $noinline$testArraySetsSameRTIBlocked() {
+ private static java.lang.Object[] $noinline$testArraySetsSameRTIBlocked(Main m) {
Object[] arr = new Object[3];
arr[0] = inner_static;
$noinline$emptyMethod();
arr[1] = inner_static2;
- Main m = new Main();
synchronized (m) {
arr[2] = inner_static3;
}