1 /* 2 * Copyright (C) 2022 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 class Main { 18 int field = 42; 19 20 // Test that deoptimization preserves objects that are singletons. $noinline$foo(Main arg)21 public static int $noinline$foo(Main arg) { 22 Main m = new Main(); 23 arg.returnValue(); 24 return m.field; 25 } 26 27 // Test that doing OSR after deoptimization works. $noinline$foo2(Main arg, boolean osr)28 public static int $noinline$foo2(Main arg, boolean osr) { 29 Main m = new Main(); 30 arg.returnValue(); 31 if (osr) { 32 while (!isInOsrCode("$noinline$foo2")) {} 33 } 34 return m.field; 35 } 36 main(String[] args)37 public static void main(String[] args) throws Throwable { 38 System.loadLibrary(args[0]); 39 if (isDebuggable()) { 40 // We do not deoptimize with inline caches when the app is debuggable, so just don't run the 41 // test. 42 return; 43 } 44 test1(); 45 test2(); 46 } 47 assertEquals(int expected, int actual)48 public static void assertEquals(int expected, int actual) { 49 if (expected != actual) { 50 throw new Error("Expected " + expected + ", got " + actual); 51 } 52 } 53 test1()54 public static void test1() { 55 ensureJitBaselineCompiled(Main.class, "$noinline$foo"); 56 // Surround the call with GCs to increase chances we execute $noinline$foo 57 // while the GC isn't marking. This makes sure the inline cache is populated. 58 Runtime.getRuntime().gc(); 59 assertEquals(42, $noinline$foo(new Main())); 60 Runtime.getRuntime().gc(); 61 62 ensureJitCompiled(Main.class, "$noinline$foo"); 63 assertEquals(42, $noinline$foo(new SubMain())); 64 } 65 test2()66 public static void test2() { 67 ensureJitBaselineCompiled(Main.class, "$noinline$foo2"); 68 // Surround the call with GCs to increase chances we execute $noinline$foo 69 // while the GC isn't marking. This makes sure the inline cache is populated. 70 Runtime.getRuntime().gc(); 71 assertEquals(42, $noinline$foo2(new Main(), false)); 72 Runtime.getRuntime().gc(); 73 74 ensureJitCompiled(Main.class, "$noinline$foo2"); 75 assertEquals(42, $noinline$foo2(new SubMain(), true)); 76 } 77 returnValue()78 public String returnValue() { 79 return "Main"; 80 } 81 ensureJitCompiled(Class<?> cls, String methodName)82 public static native void ensureJitCompiled(Class<?> cls, String methodName); ensureJitBaselineCompiled(Class<?> cls, String methodName)83 public static native void ensureJitBaselineCompiled(Class<?> cls, String methodName); isInOsrCode(String methodName)84 public static native boolean isInOsrCode(String methodName); isDebuggable()85 public static native boolean isDebuggable(); 86 } 87 88 // Define a subclass with another implementation of returnValue to deoptimize $noinline$foo and 89 // $noinline$foo2. 90 class SubMain extends Main { returnValue()91 public String returnValue() { 92 return "SubMain"; 93 } 94 } 95