xref: /aosp_15_r20/art/test/2272-checker-codegen-honor-write-barrier-kind/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2024 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker public class Main {
main(String[] args)18*795d594fSAndroid Build Coastguard Worker     public static void main(String[] args) {
19*795d594fSAndroid Build Coastguard Worker         $noinline$testHonorWriteBarrier();
20*795d594fSAndroid Build Coastguard Worker         $noinline$testDontSkipWriteBarrier();
21*795d594fSAndroid Build Coastguard Worker     }
22*795d594fSAndroid Build Coastguard Worker 
$noinline$testHonorWriteBarrier()23*795d594fSAndroid Build Coastguard Worker     public static void $noinline$testHonorWriteBarrier() {
24*795d594fSAndroid Build Coastguard Worker         String[] arr = {"Hello", "World"};
25*795d594fSAndroid Build Coastguard Worker         // We first run the gc to make sure the card is clean.
26*795d594fSAndroid Build Coastguard Worker         Runtime.getRuntime().gc();
27*795d594fSAndroid Build Coastguard Worker         // Continually call $noinline$testArraySetsHonorWriteBarrier while allocating over 64 MiB of
28*795d594fSAndroid Build Coastguard Worker         // memory (with heap size limited to 16 MiB), in order to increase memory pressure and
29*795d594fSAndroid Build Coastguard Worker         // eventually trigger a concurrent garbage collection, which will start by putting the GC in
30*795d594fSAndroid Build Coastguard Worker         // marking mode to trigger the bug.
31*795d594fSAndroid Build Coastguard Worker         for (int i = 0; i != 64 * 1024; ++i) {
32*795d594fSAndroid Build Coastguard Worker             $noinline$allocateAtLeast1KiB();
33*795d594fSAndroid Build Coastguard Worker             $noinline$testArraySetsHonorWriteBarrier(arr, "Universe");
34*795d594fSAndroid Build Coastguard Worker         }
35*795d594fSAndroid Build Coastguard Worker     }
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker     // When the bug was present, $noinline$testArraySetsHonorWriteBarrier would never set the card
38*795d594fSAndroid Build Coastguard Worker     // as dirty (which is incorrect). arr[1]'s' write barrier depends on arr[0]'s write barrier. The
39*795d594fSAndroid Build Coastguard Worker     // disappeared BoundType in prepare_for_register_allocation shouldn't skip marking the card
40*795d594fSAndroid Build Coastguard Worker     // dirty.
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsHonorWriteBarrier(java.lang.String[], java.lang.String) prepare_for_register_allocation (before)
43*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<Null:l\d+>>   NullConstant
44*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<BT:l\d+>>     BoundType [<<Null>>]
45*795d594fSAndroid Build Coastguard Worker     /// CHECK: ArraySet [<<arr:l\d+>>,<<index:i\d+>>,<<BT>>] value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
46*795d594fSAndroid Build Coastguard Worker     /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNotBeingReliedOn
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsHonorWriteBarrier(java.lang.String[], java.lang.String) prepare_for_register_allocation (after)
49*795d594fSAndroid Build Coastguard Worker     /// CHECK: <<Null:l\d+>>   NullConstant
50*795d594fSAndroid Build Coastguard Worker     /// CHECK: ArraySet [<<arr:l\d+>>,<<index:i\d+>>,<<Null>>] value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
51*795d594fSAndroid Build Coastguard Worker     /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNotBeingReliedOn
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsHonorWriteBarrier(java.lang.String[], java.lang.String) prepare_for_register_allocation (after)
54*795d594fSAndroid Build Coastguard Worker     /// CHECK-NOT: BoundType
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsHonorWriteBarrier(java.lang.String[], java.lang.String) disassembly (after)
57*795d594fSAndroid Build Coastguard Worker     /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
58*795d594fSAndroid Build Coastguard Worker     /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNotBeingReliedOn
$noinline$testArraySetsHonorWriteBarrier( String[] arr, String o2)59*795d594fSAndroid Build Coastguard Worker     private static java.lang.String[] $noinline$testArraySetsHonorWriteBarrier(
60*795d594fSAndroid Build Coastguard Worker             String[] arr, String o2) {
61*795d594fSAndroid Build Coastguard Worker         Object o = null;
62*795d594fSAndroid Build Coastguard Worker         arr[0] = (String) o;
63*795d594fSAndroid Build Coastguard Worker         arr[1] = o2;
64*795d594fSAndroid Build Coastguard Worker         return arr;
65*795d594fSAndroid Build Coastguard Worker     }
66*795d594fSAndroid Build Coastguard Worker 
$noinline$testDontSkipWriteBarrier()67*795d594fSAndroid Build Coastguard Worker     public static void $noinline$testDontSkipWriteBarrier() {
68*795d594fSAndroid Build Coastguard Worker         String[] arr = {"Hello", "World"};
69*795d594fSAndroid Build Coastguard Worker         // We first run the gc to make sure the card is clean.
70*795d594fSAndroid Build Coastguard Worker         Runtime.getRuntime().gc();
71*795d594fSAndroid Build Coastguard Worker         // Continually call $noinline$testArraySets while allocating over 64 MiB of memory (with
72*795d594fSAndroid Build Coastguard Worker         // heap size limited to 16 MiB), in order to increase memory pressure and eventually trigger
73*795d594fSAndroid Build Coastguard Worker         // a concurrent garbage collection, which will start by putting the GC in marking mode to
74*795d594fSAndroid Build Coastguard Worker         // trigger the bug.
75*795d594fSAndroid Build Coastguard Worker         for (int i = 0; i != 64 * 1024; ++i) {
76*795d594fSAndroid Build Coastguard Worker             $noinline$allocateAtLeast1KiB();
77*795d594fSAndroid Build Coastguard Worker             $noinline$testArraySetsDontSkipWriteBarrier(arr, null, "Universe");
78*795d594fSAndroid Build Coastguard Worker         }
79*795d594fSAndroid Build Coastguard Worker     }
80*795d594fSAndroid Build Coastguard Worker 
81*795d594fSAndroid Build Coastguard Worker     // When the bug was present, $noinline$testArraySetsDontSkipWriteBarrier would never set the
82*795d594fSAndroid Build Coastguard Worker     // card as dirty (which is incorrect). arr[1]'s write barrier depends on arr[0]'s write barrier.
83*795d594fSAndroid Build Coastguard Worker     // The code path should mark the card dirty without a null check on `o` in `arr[0] = o`.
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker     /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsDontSkipWriteBarrier(java.lang.String[], java.lang.String, java.lang.String) disassembly (after)
86*795d594fSAndroid Build Coastguard Worker     /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
87*795d594fSAndroid Build Coastguard Worker     /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
$noinline$testArraySetsDontSkipWriteBarrier( String[] arr, String o, String o2)88*795d594fSAndroid Build Coastguard Worker     private static java.lang.String[] $noinline$testArraySetsDontSkipWriteBarrier(
89*795d594fSAndroid Build Coastguard Worker             String[] arr, String o, String o2) {
90*795d594fSAndroid Build Coastguard Worker         arr[0] = o;
91*795d594fSAndroid Build Coastguard Worker         arr[1] = o2;
92*795d594fSAndroid Build Coastguard Worker         return arr;
93*795d594fSAndroid Build Coastguard Worker     }
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker     // Allocate at least 1 KiB of memory on the managed heap.
96*795d594fSAndroid Build Coastguard Worker     // Retain some allocated memory and release old allocations so that the
97*795d594fSAndroid Build Coastguard Worker     // garbage collector has something to do.
$noinline$allocateAtLeast1KiB()98*795d594fSAndroid Build Coastguard Worker     public static void $noinline$allocateAtLeast1KiB() {
99*795d594fSAndroid Build Coastguard Worker         memory[allocationIndex] = new Object[1024 / 4];
100*795d594fSAndroid Build Coastguard Worker         ++allocationIndex;
101*795d594fSAndroid Build Coastguard Worker         if (allocationIndex == memory.length) {
102*795d594fSAndroid Build Coastguard Worker             allocationIndex = 0;
103*795d594fSAndroid Build Coastguard Worker         }
104*795d594fSAndroid Build Coastguard Worker     }
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker     public static Object[] memory = new Object[1024];
107*795d594fSAndroid Build Coastguard Worker     public static int allocationIndex = 0;
108*795d594fSAndroid Build Coastguard Worker }
109