1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // DeadReferenceSafeTest, but with a ReachabilitySensitive annotation.
18 
19 import dalvik.annotation.optimization.DeadReferenceSafe;
20 import dalvik.annotation.optimization.ReachabilitySensitive;
21 import java.util.concurrent.atomic.AtomicInteger;
22 
23 @DeadReferenceSafe
24 public final class ReachabilitySensitiveFunTest {
25   static AtomicInteger nFinalized = new AtomicInteger(0);
26   private static final int INNER_ITERS = 10;
27   static int count;
28   int n = 1;
29   @ReachabilitySensitive
getN()30   int getN() {
31     return n;
32   }
33 
$noinline$loop()34   private static void $noinline$loop() {
35     ReachabilitySensitiveFunTest x;
36     // The loop allocates INNER_ITERS ReachabilitySensitiveTest objects.
37     for (int i = 0; i < INNER_ITERS; ++i) {
38       // We've allocated i objects so far.
39       x = new ReachabilitySensitiveFunTest();
40       // ReachabilitySensitive reference.
41       count += x.getN();
42       // x is dead here.
43       if (i == 5) {
44         // Since there is a ReachabilitySensitive call, x should be kept live
45         // until it is reassigned. Thus the last instance should not be finalized.
46         Main.$noinline$gcAndCheck(nFinalized, 5, "ReachabilitySensitiveFun",
47             "@ReachabilitySensitive call failed to keep object live.");
48       }
49     }
50   }
51 
reset(int expected_count)52   private static void reset(int expected_count) {
53     Runtime.getRuntime().gc();
54     System.runFinalization();
55     if (nFinalized.get() != expected_count) {
56       System.out.println("ReachabilitySensitiveFunTest: Wrong number of finalized objects:"
57                          + nFinalized.get());
58     }
59     nFinalized.set(0);
60   }
61 
finalize()62   protected void finalize() {
63     nFinalized.incrementAndGet();
64   }
65 
runTest()66   public static void runTest() {
67     try {
68       Main.ensureCompiled(ReachabilitySensitiveFunTest.class, "$noinline$loop");
69     } catch (NoSuchMethodException e) {
70       System.out.println("Unexpectedly threw " + e);
71     }
72 
73     $noinline$loop();
74 
75     if (count != INNER_ITERS) {
76       System.out.println("ReachabilitySensitiveFunTest: Final count wrong: " + count);
77     }
78     reset(INNER_ITERS);
79   }
80 }
81