blob: 1142d49eeda6295e9d4eaa01ba491761d1cce102 [file] [log] [blame]
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +00001/*
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
17public class Main {
18 public static void main(String[] args) {
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000019 new SubMain();
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000020 System.loadLibrary(args[0]);
21 if ($noinline$returnInt() != 53) {
22 throw new Error("Unexpected return value");
23 }
24 if ($noinline$returnFloat() != 42.2f) {
25 throw new Error("Unexpected return value");
26 }
27 if ($noinline$returnDouble() != Double.longBitsToDouble(0xF000000000001111L)) {
28 throw new Error("Unexpected return value ");
29 }
30 if ($noinline$returnLong() != 0xFFFF000000001111L) {
31 throw new Error("Unexpected return value");
32 }
33
34 try {
35 $noinline$deopt();
36 } catch (Exception e) {}
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000037 DeoptimizationController.stopDeoptimization();
38
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +000039 $noinline$inlineCache(new Main(), /* isSecondInvocation */ false);
40 if ($noinline$inlineCache(new SubMain(), /* isSecondInvocation */ true) != SubMain.class) {
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000041 throw new Error("Unexpected return value");
42 }
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +000043
44 $noinline$stackOverflow(new Main(), /* isSecondInvocation */ false);
45 $noinline$stackOverflow(new SubMain(), /* isSecondInvocation */ true);
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000046 }
47
48 public static int $noinline$returnInt() {
49 if (doThrow) throw new Error("");
50 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000051 for (; i < 100000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000052 }
53 while (!ensureInOsrCode()) {}
54 System.out.println(i);
55 return 53;
56 }
57
58 public static float $noinline$returnFloat() {
59 if (doThrow) throw new Error("");
60 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000061 for (; i < 200000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000062 }
63 while (!ensureInOsrCode()) {}
64 System.out.println(i);
65 return 42.2f;
66 }
67
68 public static double $noinline$returnDouble() {
69 if (doThrow) throw new Error("");
70 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000071 for (; i < 300000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000072 }
73 while (!ensureInOsrCode()) {}
74 System.out.println(i);
75 return Double.longBitsToDouble(0xF000000000001111L);
76 }
77
78 public static long $noinline$returnLong() {
79 if (doThrow) throw new Error("");
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000080 int i = 0;
81 for (; i < 400000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000082 }
83 while (!ensureInOsrCode()) {}
84 System.out.println(i);
85 return 0xFFFF000000001111L;
86 }
87
88 public static void $noinline$deopt() {
89 if (doThrow) throw new Error("");
90 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000091 for (; i < 100000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000092 }
93 while (!ensureInOsrCode()) {}
94 DeoptimizationController.startDeoptimization();
95 }
96
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +000097 public static Class $noinline$inlineCache(Main m, boolean isSecondInvocation) {
98 // If we are running in non-JIT mode, or were unlucky enough to get this method
99 // already JITted, just return the expected value.
100 if (!ensureInInterpreter()) {
101 return SubMain.class;
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000102 }
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000103
104 ensureHasProfilingInfo();
105
106 // Ensure that we have OSR code to jump to.
107 if (isSecondInvocation) {
108 ensureHasOsrCode();
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000109 }
110
111 // This call will be optimized in the OSR compiled code
112 // to check and deoptimize if m is not of type 'Main'.
113 Main other = m.inlineCache();
114
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000115 // Jump to OSR compiled code. The second run
116 // of this method will have 'm' as a SubMain, and the compiled
117 // code we are jumping to will have wrongly optimize other as being a
118 // 'Main'.
119 if (isSecondInvocation) {
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000120 while (!ensureInOsrCode()) {}
121 }
122
123 // We used to wrongly optimize this call and assume 'other' was a 'Main'.
124 return other.returnClass();
125 }
126
127 public Main inlineCache() {
128 return new Main();
129 }
130
131 public Class returnClass() {
132 return Main.class;
133 }
134
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000135 public void otherInlineCache() {
136 return;
137 }
138
139 public static void $noinline$stackOverflow(Main m, boolean isSecondInvocation) {
140 // If we are running in non-JIT mode, or were unlucky enough to get this method
141 // already JITted, just return the expected value.
142 if (!ensureInInterpreter()) {
143 return;
144 }
145
146 // We need a ProfilingInfo object to populate the 'otherInlineCache' call.
147 ensureHasProfilingInfo();
148
149 if (isSecondInvocation) {
150 // Ensure we have an OSR code and we jump to it.
151 while (!ensureInOsrCode()) {}
152 }
153
154 for (int i = 0; i < (isSecondInvocation ? 10000000 : 1); ++i) {
155 // The first invocation of $noinline$stackOverflow will populate the inline
156 // cache with Main. The second invocation of the method, will see a SubMain
157 // and will therefore trigger deoptimization.
158 m.otherInlineCache();
159 }
160 }
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000161
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000162 public static native boolean ensureInInterpreter();
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000163 public static native boolean ensureInOsrCode();
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000164 public static native void ensureHasProfilingInfo();
165 public static native void ensureHasOsrCode();
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000166
167 public static boolean doThrow = false;
168}
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000169
170class SubMain extends Main {
171 public Class returnClass() {
172 return SubMain.class;
173 }
174
175 public Main inlineCache() {
176 return new SubMain();
177 }
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000178
179 public void otherInlineCache() {
180 return;
181 }
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000182}