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