1 /*
2  * Copyright (C) 2018 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 public class Main {
18     // We run this test for AOT to verify that there is a HDeoptimize with dex pc 0.
19     /// CHECK-START: int Main.$noinline$getInt(byte[], int) BCE (after)
20     /// CHECK:          Deoptimize dex_pc:0
$noinline$getInt(byte[] array, int offset)21     public static int $noinline$getInt(byte[] array, int offset) {
22         // The aget for `array[offset]` is at dex pc 0, so the Deoptimize
23         // from dynamic BCE shall also be at dex pc 0.
24         return ((array[offset    ] & 0xFF) <<  0) +
25                ((array[offset + 1] & 0xFF) <<  8) +
26                ((array[offset + 2] & 0xFF) << 16) +
27                ((array[offset + 3] & 0xFF) << 24);
28     }
29 
main(String[] args)30     public static void main(String[] args) {
31         System.loadLibrary(args[0]);
32         if (hasJit()) {
33             byte[] array = { 0, 1, 2, 3 };
34             ensureJitCompiled(Main.class, "$noinline$getInt");
35             if (!hasJitCompiledEntrypoint(Main.class, "$noinline$getInt")) {
36                 throw new Error("Unexpected entrypoint!");
37             }
38             if ($noinline$getInt(array, 0) != 0x03020100) {
39                 throw new Error();
40             }
41             try {
42                 // The HDeoptimize at dex pc 0 was previously handled poorly as the dex pc 0
43                 // was used to detect whether we entered the method. This meant that the
44                 // instrumentation would have reported MethodEnteredEvent and we would have
45                 // told JIT that the method was entered. With JIT-on-first-use we would also
46                 // immediatelly recompile the method and run the compiled code leading to
47                 // a an infinite deoptimization recursion, yielding StackOverflowError.
48                 $noinline$getInt(array, 1);
49             } catch (ArrayIndexOutOfBoundsException ignored) {}
50         }
51         System.out.println("passed");
52     }
53 
hasJit()54     public static native boolean hasJit();
hasJitCompiledEntrypoint(Class<?> cls, String methodName)55     public native static boolean hasJitCompiledEntrypoint(Class<?> cls, String methodName);
ensureJitCompiled(Class<?> cls, String methodName)56     public native static void ensureJitCompiled(Class<?> cls, String methodName);
57 }
58