1 /* 2 * Copyright (C) 2021 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 // We make the methods below directly throw instead of using the $noinline$ 19 // directive to get the inliner actually try to inline but decide not to. 20 // This will then make the compiler try to generate an HInvokeVirtual instead 21 // of an HInvokeInterface. 22 m()23 public default void m() throws Exception { 24 throw new Exception("Don't inline me"); 25 } mConflict()26 public default void mConflict() throws Exception { 27 throw new Exception("Don't inline me"); 28 } 29 } 30 31 // This is redefined in src2 with a mConflict method. 32 interface Itf2 { 33 } 34 35 interface Itf3 extends Itf, Itf2 { 36 } 37 38 class Itf3Impl implements Itf3 { 39 } 40 41 interface Itf4 extends Itf, Itf2 { m()42 public default void m() throws Exception { 43 throw new Exception("Don't inline me"); 44 } 45 } 46 47 class Itf4Impl implements Itf4 { 48 } 49 50 51 public class Main implements Itf, Itf2 { 52 main(String[] args)53 public static void main(String[] args) { 54 System.loadLibrary(args[0]); 55 56 // Execute enough time to populate inline caches. 57 for (int i = 0; i < 100000; ++i) { 58 try { 59 $noinline$doCallDefault(); 60 } catch (Exception e) { 61 // Expected. 62 } 63 } 64 ensureJitCompiled(Main.class, "$noinline$doCallDefault"); 65 try { 66 $noinline$doCallDefault(); 67 throw new Error("Expected exception"); 68 } catch (Exception e) { 69 // Expected. 70 } 71 72 ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflict"); 73 try { 74 $noinline$doCallDefaultConflict(); 75 throw new Error("Expected IncompatibleClassChangeError"); 76 } catch (Exception e) { 77 throw new Error("Unexpected exception"); 78 } catch (IncompatibleClassChangeError e) { 79 // Expected. 80 } 81 82 // Execute enough time to populate inline caches. 83 for (int i = 0; i < 100000; ++i) { 84 try { 85 $noinline$doCallDefaultConflictItf3(); 86 } catch (Throwable t) { 87 // Expected. 88 } 89 } 90 ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflictItf3"); 91 try { 92 $noinline$doCallDefaultConflictItf3(); 93 throw new Error("Expected IncompatibleClassChangeError"); 94 } catch (Exception e) { 95 throw new Error("Unexpected exception " + e); 96 } catch (IncompatibleClassChangeError e) { 97 // Expected. 98 } 99 100 ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflictItf4"); 101 try { 102 $noinline$doCallDefaultConflictItf4(); 103 throw new Error("Expected IncompatibleClassChangeError"); 104 } catch (Exception e) { 105 throw new Error("Unexpected exception"); 106 } catch (IncompatibleClassChangeError e) { 107 // Expected. 108 } 109 } 110 $noinline$doCallDefault()111 public static void $noinline$doCallDefault() throws Exception { 112 itf.m(); 113 } 114 $noinline$doCallDefaultConflict()115 public static void $noinline$doCallDefaultConflict() throws Exception { 116 itf.mConflict(); 117 } 118 $noinline$doCallDefaultConflictItf3()119 public static void $noinline$doCallDefaultConflictItf3() throws Exception { 120 itf3.mConflict(); 121 } 122 $noinline$doCallDefaultConflictItf4()123 public static void $noinline$doCallDefaultConflictItf4() throws Exception { 124 itf4.mConflict(); 125 } 126 127 static Itf itf = new Main(); 128 static Itf3 itf3 = new Itf3Impl(); 129 static Itf4 itf4 = new Itf4Impl(); 130 ensureJitCompiled(Class<?> cls, String methodName)131 private static native void ensureJitCompiled(Class<?> cls, String methodName); 132 } 133