1 /* 2 * Copyright (C) 2016 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 interface Itf { sameInvokeInterface()18 public Class<?> sameInvokeInterface(); sameInvokeInterface2()19 public Class<?> sameInvokeInterface2(); sameInvokeInterface3()20 public Class<?> sameInvokeInterface3(); 21 } 22 23 public class Main implements Itf { assertEquals(Object expected, Object actual)24 public static void assertEquals(Object expected, Object actual) { 25 if (expected != actual) { 26 throw new Error("Expected " + expected + ", got " + actual); 27 } 28 } 29 assertEquals(int expected, int actual)30 public static void assertEquals(int expected, int actual) { 31 if (expected != actual) { 32 throw new Error("Expected " + expected + ", got " + actual); 33 } 34 } 35 main(String[] args)36 public static void main(String[] args) throws Exception { 37 System.loadLibrary(args[0]); 38 Main[] mains = new Main[3]; 39 Itf[] itfs = new Itf[3]; 40 itfs[0] = mains[0] = new Main(); 41 itfs[1] = mains[1] = new Subclass(); 42 itfs[2] = mains[2] = new OtherSubclass(); 43 44 // Create the profiling info eagerly to make sure they are filled. 45 ensureProfilingInfo566(); 46 47 // Make $noinline$testInvokeVirtual and $noinline$testInvokeInterface hot to get them jitted. 48 // We pass Main and Subclass to get polymorphic inlining based on calling 49 // the same method. 50 for (int i = 0; i < 1000000; ++i) { 51 $noinline$testInvokeVirtual(mains[0]); 52 $noinline$testInvokeVirtual(mains[1]); 53 $noinline$testInvokeInterface(itfs[0]); 54 $noinline$testInvokeInterface(itfs[1]); 55 $noinline$testInvokeInterface2(itfs[0]); 56 $noinline$testInvokeInterface2(itfs[1]); 57 $noinline$testInlineToSameTarget(mains[0]); 58 $noinline$testInlineToSameTarget(mains[1]); 59 } 60 61 ensureJittedAndPolymorphicInline566(); 62 63 // At this point, the JIT should have compiled both methods, and inline 64 // sameInvokeVirtual and sameInvokeInterface. 65 assertEquals(Main.class, $noinline$testInvokeVirtual(mains[0])); 66 assertEquals(Main.class, $noinline$testInvokeVirtual(mains[1])); 67 68 assertEquals(Itf.class, $noinline$testInvokeInterface(itfs[0])); 69 assertEquals(Itf.class, $noinline$testInvokeInterface(itfs[1])); 70 71 assertEquals(Itf.class, $noinline$testInvokeInterface2(itfs[0])); 72 assertEquals(Itf.class, $noinline$testInvokeInterface2(itfs[1])); 73 74 // This will trigger a deoptimization of the compiled code. 75 assertEquals(OtherSubclass.class, $noinline$testInvokeVirtual(mains[2])); 76 assertEquals(OtherSubclass.class, $noinline$testInvokeInterface(itfs[2])); 77 assertEquals(null, $noinline$testInvokeInterface2(itfs[2])); 78 79 // Run this once to make sure we execute the JITted code. 80 $noinline$testInlineToSameTarget(mains[0]); 81 assertEquals(2000001, counter); 82 } 83 sameInvokeVirtual()84 public Class<?> sameInvokeVirtual() { 85 field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo. 86 return Main.class; 87 } 88 sameInvokeInterface()89 public Class<?> sameInvokeInterface() { 90 field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo. 91 return Itf.class; 92 } 93 sameInvokeInterface2()94 public Class<?> sameInvokeInterface2() { 95 field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo. 96 return Itf.class; 97 } 98 sameInvokeInterface3()99 public Class<?> sameInvokeInterface3() { 100 field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo. 101 return Itf.class; 102 } 103 $noinline$testInvokeInterface(Itf i)104 public static Class<?> $noinline$testInvokeInterface(Itf i) { 105 return i.sameInvokeInterface(); 106 } 107 $noinline$testInvokeInterface2(Itf i)108 public static Class<?> $noinline$testInvokeInterface2(Itf i) { 109 // Make three interface calls that will do a ClassTableGet to ensure bogus code 110 // generation of ClassTableGet will crash. 111 i.sameInvokeInterface(); 112 i.sameInvokeInterface2(); 113 return i.sameInvokeInterface3(); 114 } 115 $noinline$testInvokeVirtual(Main m)116 public static Class<?> $noinline$testInvokeVirtual(Main m) { 117 return m.sameInvokeVirtual(); 118 } 119 $noinline$testInlineToSameTarget(Main m)120 public static void $noinline$testInlineToSameTarget(Main m) { 121 if (doThrow) throw new Error(""); 122 m.increment(); 123 } 124 125 public Object field = new Object(); 126 ensureJittedAndPolymorphicInline566()127 public static native void ensureJittedAndPolymorphicInline566(); ensureProfilingInfo566()128 public static native void ensureProfilingInfo566(); 129 increment()130 public void increment() { 131 field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo 132 counter++; 133 } 134 public static int counter = 0; 135 public static boolean doThrow = false; 136 } 137 138 class Subclass extends Main { 139 } 140 141 class OtherSubclass extends Main { sameInvokeVirtual()142 public Class<?> sameInvokeVirtual() { 143 return OtherSubclass.class; 144 } 145 sameInvokeInterface()146 public Class<?> sameInvokeInterface() { 147 return OtherSubclass.class; 148 } 149 sameInvokeInterface2()150 public Class<?> sameInvokeInterface2() { 151 return null; 152 } sameInvokeInterface3()153 public Class<?> sameInvokeInterface3() { 154 return null; 155 } 156 } 157