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