1 /*
  2  * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /**
 25  * @test
 26  * @key randomness
 27  * @summary Test value class calling convention with compiled to compiled calls.
 28  * @library /test/lib /compiler/whitebox /
 29  * @enablePreview
 30  * @build jdk.test.whitebox.WhiteBox
 31  * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 32  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
 33  *                   TestC2CCalls
 34  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
 35  *                   -XX:-UseBimorphicInlining -Xbatch
 36  *                   -XX:CompileCommand=compileonly,TestC2CCalls*::test*
 37  *                   -XX:CompileCommand=dontinline,TestC2CCalls*::test*
 38  *                   TestC2CCalls
 39  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
 40  *                   -XX:-UseBimorphicInlining -Xbatch -XX:-ProfileInterpreter
 41  *                   -XX:CompileCommand=compileonly,TestC2CCalls*::test*
 42  *                   -XX:CompileCommand=dontinline,TestC2CCalls*::test*
 43  *                   TestC2CCalls
 44  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
 45  *                   -XX:-UseBimorphicInlining -Xbatch
 46  *                   -XX:CompileCommand=compileonly,TestC2CCalls::test*
 47  *                   -XX:CompileCommand=dontinline,TestC2CCalls*::test*
 48  *                   TestC2CCalls
 49  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
 50  *                   -XX:-UseBimorphicInlining -Xbatch -XX:-ProfileInterpreter
 51  *                   -XX:CompileCommand=compileonly,TestC2CCalls::test*
 52  *                   -XX:CompileCommand=dontinline,TestC2CCalls*::test*
 53  *                   TestC2CCalls
 54  */
 55 
 56 import java.lang.reflect.Method;
 57 import java.util.ArrayList;
 58 import java.util.Collections;
 59 
 60 import jdk.test.lib.Asserts;
 61 import jdk.test.lib.Utils;
 62 
 63 import jdk.test.whitebox.WhiteBox;
 64 
 65 public class TestC2CCalls {
 66     public static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
 67     public static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; // C2 or JVMCI
 68     public static final int rI = Utils.getRandomInstance().nextInt() % 1000;
 69 
 70     static value class OtherVal {
 71         public int x;
 72 
 73         private OtherVal(int x) {
 74             this.x = x;
 75         }
 76     }
 77 
 78     static interface MyInterface1 {
 79         public MyInterface1 test1(OtherVal other, int y);
 80         public MyInterface1 test2(OtherVal other1, OtherVal other2, int y);
 81         public MyInterface1 test3(OtherVal other1, OtherVal other2, int y, boolean deopt);
 82         public MyInterface1 test4(OtherVal other1, OtherVal other2, int y);
 83         public MyInterface1 test5(OtherVal other1, OtherVal other2, int y);
 84         public MyInterface1 test6();
 85         public MyInterface1 test7(int i1, int i2, int i3, int i4, int i5, int i6);
 86         public MyInterface1 test8(int i1, int i2, int i3, int i4, int i5, int i6, int i7);
 87         public MyInterface1 test9(MyValue3 other, int i1, int i2, int i3, int i4, int i5, int i6);
 88         public MyInterface1 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6);
 89 
 90         public int getValue();
 91     }
 92 
 93     static value class MyValue1 implements MyInterface1 {
 94         public int x;
 95 
 96         private MyValue1(int x) {
 97             this.x = x;
 98         }
 99 
100         @Override
101         public int getValue() {
102             return x;
103         }
104 
105         @Override
106         public MyValue1 test1(OtherVal other, int y) {
107             return new MyValue1(x + other.x + y);
108         }
109 
110         @Override
111         public MyValue1 test2(OtherVal other1, OtherVal other2, int y) {
112             return new MyValue1(x + other1.x + other2.x + y);
113         }
114 
115         @Override
116         public MyValue1 test3(OtherVal other1, OtherVal other2, int y, boolean deopt) {
117             if (!deopt) {
118               return new MyValue1(x + other1.x + other2.x + y);
119             } else {
120               // Uncommon trap
121               return test1(other1, y);
122             }
123         }
124 
125         @Override
126         public MyValue1 test4(OtherVal other1, OtherVal other2, int y) {
127             return new MyValue1(x + other1.x + other2.x + y);
128         }
129 
130         @Override
131         public MyValue1 test5(OtherVal other1, OtherVal other2, int y) {
132             return new MyValue1(x + other1.x + other2.x + y);
133         }
134 
135         @Override
136         public MyValue1 test6() {
137             return this;
138         }
139 
140         @Override
141         public MyValue1 test7(int i1, int i2, int i3, int i4, int i5, int i6) {
142             return new MyValue1(x + i1 + i2 + i3 + i4 + i5 + i6);
143         }
144 
145         @Override
146         public MyValue1 test8(int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
147             return new MyValue1(x + i1 + i2 + i3 + i4 + i5 + i6 + i7);
148         }
149 
150         public MyValue1 test9(MyValue3 other, int i1, int i2, int i3, int i4, int i5, int i6) {
151             return new MyValue1(x + (int)(other.d1 + other.d2 + other.d3 + other.d4) + i1 + i2 + i3 + i4 + i5 + i6);
152         }
153 
154         public MyValue1 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) {
155             return new MyValue1(x + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6);
156         }
157     }
158 
159     static value class MyValue2 implements MyInterface1 {
160         public int x;
161 
162         private MyValue2(int x) {
163             this.x = x;
164         }
165 
166         @Override
167         public int getValue() {
168             return x;
169         }
170 
171         @Override
172         public MyValue2 test1(OtherVal other, int y) {
173             return new MyValue2(x + other.x + y);
174         }
175 
176         @Override
177         public MyValue2 test2(OtherVal other1, OtherVal other2, int y) {
178             return new MyValue2(x + other1.x + other2.x + y);
179         }
180 
181         @Override
182         public MyValue2 test3(OtherVal other1, OtherVal other2, int y, boolean deopt) {
183             if (!deopt) {
184               return new MyValue2(x + other1.x + other2.x + y);
185             } else {
186               // Uncommon trap
187               return test1(other1, y);
188             }
189         }
190 
191         @Override
192         public MyValue2 test4(OtherVal other1, OtherVal other2, int y) {
193             return new MyValue2(x + other1.x + other2.x + y);
194         }
195 
196         @Override
197         public MyValue2 test5(OtherVal other1, OtherVal other2, int y) {
198             return new MyValue2(x + other1.x + other2.x + y);
199         }
200 
201         @Override
202         public MyValue2 test6() {
203             return this;
204         }
205 
206         @Override
207         public MyValue2 test7(int i1, int i2, int i3, int i4, int i5, int i6) {
208             return new MyValue2(x + i1 + i2 + i3 + i4 + i5 + i6);
209         }
210 
211         @Override
212         public MyValue2 test8(int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
213             return new MyValue2(x + i1 + i2 + i3 + i4 + i5 + i6 + i7);
214         }
215 
216         public MyValue2 test9(MyValue3 other, int i1, int i2, int i3, int i4, int i5, int i6) {
217             return new MyValue2(x + (int)(other.d1 + other.d2 + other.d3 + other.d4) + i1 + i2 + i3 + i4 + i5 + i6);
218         }
219 
220         public MyValue2 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) {
221             return new MyValue2(x + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6);
222         }
223     }
224 
225     static value class MyValue3 implements MyInterface1 {
226         public double d1;
227         public double d2;
228         public double d3;
229         public double d4;
230 
231         private MyValue3(double d) {
232             this.d1 = d;
233             this.d2 = d;
234             this.d3 = d;
235             this.d4 = d;
236         }
237 
238         @Override
239         public int getValue() {
240             return (int)d4;
241         }
242 
243         @Override
244         public MyValue3 test1(OtherVal other, int y) { return new MyValue3(0); }
245         @Override
246         public MyValue3 test2(OtherVal other1, OtherVal other2, int y)  { return new MyValue3(0); }
247         @Override
248         public MyValue3 test3(OtherVal other1, OtherVal other2, int y, boolean deopt)  { return new MyValue3(0); }
249         @Override
250         public MyValue3 test4(OtherVal other1, OtherVal other2, int y)  { return new MyValue3(0); }
251         @Override
252         public MyValue3 test5(OtherVal other1, OtherVal other2, int y)  { return new MyValue3(0); }
253         @Override
254         public MyValue3 test6()  { return new MyValue3(0); }
255 
256         @Override
257         public MyValue3 test7(int i1, int i2, int i3, int i4, int i5, int i6)  {
258             return new MyValue3(d1 + d2 + d3 + d4 + i1 + i2 + i3 + i4 + i5 + i6);
259         }
260 
261         @Override
262         public MyValue3 test8(int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
263             return new MyValue3(d1 + d2 + d3 + d4 + i1 + i2 + i3 + i4 + i5 + i6 + i7);
264         }
265 
266         public MyValue3 test9(MyValue3 other, int i1, int i2, int i3, int i4, int i5, int i6) {
267             return new MyValue3(d1 + d2 + d3 + d4 + other.d1 + other.d2 + other.d3 + other.d4 + i1 + i2 + i3 + i4 + i5 + i6);
268         }
269 
270         public MyValue3 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) {
271             return new MyValue3(d1 + d2 + d3 + d4 + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6);
272         }
273     }
274 
275     static value class MyValue4 implements MyInterface1 {
276         public int x1;
277         public int x2;
278         public int x3;
279         public int x4;
280 
281         private MyValue4(int i) {
282             this.x1 = i;
283             this.x2 = i;
284             this.x3 = i;
285             this.x4 = i;
286         }
287 
288         @Override
289         public int getValue() {
290             return x4;
291         }
292 
293         @Override
294         public MyValue4 test1(OtherVal other, int y) { return new MyValue4(0); }
295         @Override
296         public MyValue4 test2(OtherVal other1, OtherVal other2, int y)  { return new MyValue4(0); }
297         @Override
298         public MyValue4 test3(OtherVal other1, OtherVal other2, int y, boolean deopt)  { return new MyValue4(0); }
299         @Override
300         public MyValue4 test4(OtherVal other1, OtherVal other2, int y)  { return new MyValue4(0); }
301         @Override
302         public MyValue4 test5(OtherVal other1, OtherVal other2, int y)  { return new MyValue4(0); }
303         @Override
304         public MyValue4 test6()  { return new MyValue4(0); }
305 
306         @Override
307         public MyValue4 test7(int i1, int i2, int i3, int i4, int i5, int i6)  {
308             return new MyValue4(x1 + x2 + x3 + x4 + i1 + i2 + i3 + i4 + i5 + i6);
309         }
310 
311         @Override
312         public MyValue4 test8(int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
313             return new MyValue4(x1 + x2 + x3 + x4 + i1 + i2 + i3 + i4 + i5 + i6 + i7);
314         }
315 
316         public MyValue4 test9(MyValue3 other, int i1, int i2, int i3, int i4, int i5, int i6) {
317             return new MyValue4(x1 + x2 + x3 + x4 + (int)(other.d1 + other.d2 + other.d3 + other.d4) + i1 + i2 + i3 + i4 + i5 + i6);
318         }
319 
320         public MyValue4 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) {
321             return new MyValue4(x1 + x2 + x3 + x4 + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6);
322         }
323     }
324 
325     static class MyObject implements MyInterface1 {
326         private final int x;
327 
328         private MyObject(int x) {
329             this.x = x;
330         }
331 
332         @Override
333         public int getValue() {
334             return x;
335         }
336 
337         @Override
338         public MyObject test1(OtherVal other, int y) {
339             return new MyObject(x + other.x + y);
340         }
341 
342         @Override
343         public MyObject test2(OtherVal other1, OtherVal other2, int y) {
344             return new MyObject(x + other1.x + other2.x + y);
345         }
346 
347         @Override
348         public MyObject test3(OtherVal other1, OtherVal other2, int y, boolean deopt) {
349             if (!deopt) {
350               return new MyObject(x + other1.x + other2.x + y);
351             } else {
352               // Uncommon trap
353               return test1(other1, y);
354             }
355         }
356 
357         @Override
358         public MyObject test4(OtherVal other1, OtherVal other2, int y) {
359             return new MyObject(x + other1.x + other2.x + y);
360         }
361 
362         @Override
363         public MyObject test5(OtherVal other1, OtherVal other2, int y) {
364             return new MyObject(x + other1.x + other2.x + y);
365         }
366 
367         @Override
368         public MyObject test6() {
369             return this;
370         }
371 
372         @Override
373         public MyObject test7(int i1, int i2, int i3, int i4, int i5, int i6) {
374             return new MyObject(x + i1 + i2 + i3 + i4 + i5 + i6);
375         }
376 
377         @Override
378         public MyObject test8(int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
379             return new MyObject(x + i1 + i2 + i3 + i4 + i5 + i6 + i7);
380         }
381 
382         public MyObject test9(MyValue3 other, int i1, int i2, int i3, int i4, int i5, int i6) {
383             return new MyObject(x + (int)(other.d1 + other.d2 + other.d3 + other.d4) + i1 + i2 + i3 + i4 + i5 + i6);
384         }
385 
386         public MyObject test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) {
387             return new MyObject(x + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6);
388         }
389     }
390 
391     // Test calling methods with value class arguments through an interface
392     public static int test1(MyInterface1 intf, OtherVal other, int y) {
393         return intf.test1(other, y).getValue();
394     }
395 
396     public static int test2(MyInterface1 intf, OtherVal other, int y) {
397         return intf.test2(other, other, y).getValue();
398     }
399 
400     // Test mixing null-tolerant and null-free value class arguments
401     public static int test3(MyValue1 vt, OtherVal other, int y) {
402         return vt.test2(other, other, y).getValue();
403     }
404 
405     public static int test4(MyObject obj, OtherVal other, int y) {
406         return obj.test2(other, other, y).getValue();
407     }
408 
409     // Optimized interface call with value class receiver
410     public static int test5(MyInterface1 intf, OtherVal other, int y) {
411         return intf.test1(other, y).getValue();
412     }
413 
414     public static int test6(MyInterface1 intf, OtherVal other, int y) {
415         return intf.test2(other, other, y).getValue();
416     }
417 
418     // Optimized interface call with object receiver
419     public static int test7(MyInterface1 intf, OtherVal other, int y) {
420         return intf.test1(other, y).getValue();
421     }
422 
423     public static int test8(MyInterface1 intf, OtherVal other, int y) {
424         return intf.test2(other, other, y).getValue();
425     }
426 
427     // Interface calls with deoptimized callee
428     public static int test9(MyInterface1 intf, OtherVal other, int y, boolean deopt) {
429         return intf.test3(other, other, y, deopt).getValue();
430     }
431 
432     public static int test10(MyInterface1 intf, OtherVal other, int y, boolean deopt) {
433         return intf.test3(other, other, y, deopt).getValue();
434     }
435 
436     // Optimized interface calls with deoptimized callee
437     public static int test11(MyInterface1 intf, OtherVal other, int y, boolean deopt) {
438         return intf.test3(other, other, y, deopt).getValue();
439     }
440 
441     public static int test12(MyInterface1 intf, OtherVal other, int y, boolean deopt) {
442         return intf.test3(other, other, y, deopt).getValue();
443     }
444 
445     public static int test13(MyInterface1 intf, OtherVal other, int y, boolean deopt) {
446         return intf.test3(other, other, y, deopt).getValue();
447     }
448 
449     public static int test14(MyInterface1 intf, OtherVal other, int y, boolean deopt) {
450         return intf.test3(other, other, y, deopt).getValue();
451     }
452 
453     // Interface calls without warmed up / compiled callees
454     public static int test15(MyInterface1 intf, OtherVal other, int y) {
455         return intf.test4(other, other, y).getValue();
456     }
457 
458     public static int test16(MyInterface1 intf, OtherVal other, int y) {
459         return intf.test5(other, other, y).getValue();
460     }
461 
462     // Interface call with no arguments
463     public static int test17(MyInterface1 intf) {
464         return intf.test6().getValue();
465     }
466 
467     // Calls that require stack extension
468     public static int test18(MyInterface1 intf, int y) {
469         return intf.test7(y, y, y, y, y, y).getValue();
470     }
471 
472     public static int test19(MyInterface1 intf, int y) {
473         return intf.test8(y, y, y, y, y, y, y).getValue();
474     }
475 
476     public static int test20(MyInterface1 intf, MyValue3 v, int y) {
477         return intf.test9(v, y, y, y, y, y, y).getValue();
478     }
479 
480     public static int test21(MyInterface1 intf, MyValue4 v, int y) {
481         return intf.test10(v, y, y, y, y, y, y).getValue();
482     }
483 
484     public static void main(String[] args) {
485         // Sometimes, exclude some methods from compilation with C2 to stress test the calling convention
486         if (Utils.getRandomInstance().nextBoolean()) {
487             ArrayList<Method> methods = new ArrayList<Method>();
488             Collections.addAll(methods, MyValue1.class.getDeclaredMethods());
489             Collections.addAll(methods, MyValue2.class.getDeclaredMethods());
490             Collections.addAll(methods, MyValue3.class.getDeclaredMethods());
491             Collections.addAll(methods, MyValue4.class.getDeclaredMethods());
492             Collections.addAll(methods, MyObject.class.getDeclaredMethods());
493             Collections.addAll(methods, TestC2CCalls.class.getDeclaredMethods());
494             System.out.println("Excluding methods from C2 compilation:");
495             for (Method m : methods) {
496                 if (Utils.getRandomInstance().nextBoolean()) {
497                     System.out.println(m);
498                     WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_FULL_OPTIMIZATION, false);
499                 }
500             }
501         }
502 
503         MyValue1 val1 = new MyValue1(rI);
504         MyValue2 val2 = new MyValue2(rI+1);
505         MyValue3 val3 = new MyValue3(rI+2);
506         MyValue4 val4 = new MyValue4(rI+3);
507         OtherVal other = new OtherVal(rI+4);
508         MyObject obj = new MyObject(rI+5);
509 
510         // Make sure callee methods are compiled
511         for (int i = 0; i < 10_000; ++i) {
512             Asserts.assertEQ(val1.test1(other, rI).getValue(), val1.x + other.x + rI);
513             Asserts.assertEQ(val2.test1(other, rI).getValue(), val2.x + other.x + rI);
514             Asserts.assertEQ(obj.test1(other, rI).getValue(), obj.x + other.x + rI);
515             Asserts.assertEQ(val1.test2(other, other, rI).getValue(), val1.x + 2*other.x + rI);
516             Asserts.assertEQ(val2.test2(other, other, rI).getValue(), val2.x + 2*other.x + rI);
517             Asserts.assertEQ(obj.test2(other, other, rI).getValue(), obj.x + 2*other.x + rI);
518             Asserts.assertEQ(val1.test3(other, other, rI, false).getValue(), val1.x + 2*other.x + rI);
519             Asserts.assertEQ(val2.test3(other, other, rI, false).getValue(), val2.x + 2*other.x + rI);
520             Asserts.assertEQ(obj.test3(other, other, rI, false).getValue(), obj.x + 2*other.x + rI);
521             Asserts.assertEQ(val1.test7(rI, rI, rI, rI, rI, rI).getValue(), val1.x + 6*rI);
522             Asserts.assertEQ(val2.test7(rI, rI, rI, rI, rI, rI).getValue(), val2.x + 6*rI);
523             Asserts.assertEQ(val3.test7(rI, rI, rI, rI, rI, rI).getValue(), (int)(4*val3.d1 + 6*rI));
524             Asserts.assertEQ(val4.test7(rI, rI, rI, rI, rI, rI).getValue(), (int)(4*val4.x1 + 6*rI));
525             Asserts.assertEQ(obj.test7(rI, rI, rI, rI, rI, rI).getValue(), obj.x + 6*rI);
526             Asserts.assertEQ(val1.test8(rI, rI, rI, rI, rI, rI, rI).getValue(), val1.x + 7*rI);
527             Asserts.assertEQ(val2.test8(rI, rI, rI, rI, rI, rI, rI).getValue(), val2.x + 7*rI);
528             Asserts.assertEQ(val3.test8(rI, rI, rI, rI, rI, rI, rI).getValue(), (int)(4*val3.d1 + 7*rI));
529             Asserts.assertEQ(val4.test8(rI, rI, rI, rI, rI, rI, rI).getValue(), (int)(4*val4.x1 + 7*rI));
530             Asserts.assertEQ(obj.test8(rI, rI, rI, rI, rI, rI, rI).getValue(), obj.x + 7*rI);
531             Asserts.assertEQ(val1.test9(val3, rI, rI, rI, rI, rI, rI).getValue(), (int)(val1.x + 4*val3.d1 + 6*rI));
532             Asserts.assertEQ(val2.test9(val3, rI, rI, rI, rI, rI, rI).getValue(), (int)(val2.x + 4*val3.d1 + 6*rI));
533             Asserts.assertEQ(val3.test9(val3, rI, rI, rI, rI, rI, rI).getValue(), (int)(4*val3.d1 + 4*val3.d1 + 6*rI));
534             Asserts.assertEQ(val4.test9(val3, rI, rI, rI, rI, rI, rI).getValue(), (int)(4*val4.x1 + 4*val3.d1 + 6*rI));
535             Asserts.assertEQ(obj.test9(val3, rI, rI, rI, rI, rI, rI).getValue(), (int)(obj.x + 4*val3.d1 + 6*rI));
536             Asserts.assertEQ(val1.test10(val4, rI, rI, rI, rI, rI, rI).getValue(), (int)(val1.x + 4*val4.x1 + 6*rI));
537             Asserts.assertEQ(val2.test10(val4, rI, rI, rI, rI, rI, rI).getValue(), (int)(val2.x + 4*val4.x1 + 6*rI));
538             Asserts.assertEQ(val3.test10(val4, rI, rI, rI, rI, rI, rI).getValue(), (int)(4*val3.d1 + 4*val4.x1 + 6*rI));
539             Asserts.assertEQ(val4.test10(val4, rI, rI, rI, rI, rI, rI).getValue(), (int)(4*val4.x1 + 4*val4.x1 + 6*rI));
540             Asserts.assertEQ(obj.test10(val4, rI, rI, rI, rI, rI, rI).getValue(), (int)(obj.x + 4*val4.x1 + 6*rI));
541         }
542 
543         // Polute call profile
544         for (int i = 0; i < 100; ++i) {
545             Asserts.assertEQ(test15(val1, other, rI), val1.x + 2*other.x + rI);
546             Asserts.assertEQ(test16(obj, other, rI), obj.x + 2*other.x + rI);
547             Asserts.assertEQ(test17(obj), obj.x);
548         }
549 
550         // Trigger compilation of caller methods
551         for (int i = 0; i < 100_000; ++i) {
552             val1 = new MyValue1(rI+i);
553             val2 = new MyValue2(rI+i+1);
554             val3 = new MyValue3(rI+i+2);
555             val4 = new MyValue4(rI+i+3);
556             other = new OtherVal(rI+i+4);
557             obj = new MyObject(rI+i+5);
558 
559             Asserts.assertEQ(test1(val1, other, rI), val1.x + other.x + rI);
560             Asserts.assertEQ(test1(obj, other, rI), obj.x + other.x + rI);
561             Asserts.assertEQ(test2(obj, other, rI), obj.x + 2*other.x + rI);
562             Asserts.assertEQ(test2(val1, other, rI), val1.x + 2*other.x + rI);
563             Asserts.assertEQ(test3(val1, other, rI), val1.x + 2*other.x + rI);
564             Asserts.assertEQ(test4(obj, other, rI), obj.x + 2*other.x + rI);
565             Asserts.assertEQ(test5(val1, other, rI), val1.x + other.x + rI);
566             Asserts.assertEQ(test6(val1, other, rI), val1.x + 2*other.x + rI);
567             Asserts.assertEQ(test7(obj, other, rI), obj.x + other.x + rI);
568             Asserts.assertEQ(test8(obj, other, rI), obj.x + 2*other.x + rI);
569             Asserts.assertEQ(test9(val1, other, rI, false), val1.x + 2*other.x + rI);
570             Asserts.assertEQ(test9(obj, other, rI, false), obj.x + 2*other.x + rI);
571             Asserts.assertEQ(test10(val1, other, rI, false), val1.x + 2*other.x + rI);
572             Asserts.assertEQ(test10(obj, other, rI, false), obj.x + 2*other.x + rI);
573             Asserts.assertEQ(test11(val1, other, rI, false), val1.x + 2*other.x + rI);
574             Asserts.assertEQ(test12(val1, other, rI, false), val1.x + 2*other.x + rI);
575             Asserts.assertEQ(test13(obj, other, rI, false), obj.x + 2*other.x + rI);
576             Asserts.assertEQ(test14(obj, other, rI, false), obj.x + 2*other.x + rI);
577             Asserts.assertEQ(test15(obj, other, rI), obj.x + 2*other.x + rI);
578             Asserts.assertEQ(test16(val1, other, rI), val1.x + 2*other.x + rI);
579             Asserts.assertEQ(test17(val1), val1.x);
580             Asserts.assertEQ(test18(val1, rI), val1.x + 6*rI);
581             Asserts.assertEQ(test18(val2, rI), val2.x + 6*rI);
582             Asserts.assertEQ(test18(val3, rI), (int)(4*val3.d1 + 6*rI));
583             Asserts.assertEQ(test18(val4, rI), 4*val4.x1 + 6*rI);
584             Asserts.assertEQ(test18(obj, rI), obj.x + 6*rI);
585             Asserts.assertEQ(test19(val1, rI), val1.x + 7*rI);
586             Asserts.assertEQ(test19(val2, rI), val2.x + 7*rI);
587             Asserts.assertEQ(test19(val3, rI), (int)(4*val3.d1 + 7*rI));
588             Asserts.assertEQ(test19(val4, rI), 4*val4.x1 + 7*rI);
589             Asserts.assertEQ(test19(obj, rI), obj.x + 7*rI);
590             Asserts.assertEQ(test20(val1, val3, rI), (int)(val1.x + 4*val3.d1 + 6*rI));
591             Asserts.assertEQ(test20(val2, val3, rI), (int)(val2.x + 4*val3.d1 + 6*rI));
592             Asserts.assertEQ(test20(val3, val3, rI), (int)(4*val3.d1 + 4*val3.d1 + 6*rI));
593             Asserts.assertEQ(test20(val4, val3, rI), (int)(4*val4.x1 + 4*val3.d1 + 6*rI));
594             Asserts.assertEQ(test20(obj, val3, rI), (int)(obj.x + 4*val3.d1 + 6*rI));
595             Asserts.assertEQ(test21(val1, val4, rI), val1.x + 4*val4.x1 + 6*rI);
596             Asserts.assertEQ(test21(val2, val4, rI), val2.x + 4*val4.x1 + 6*rI);
597             Asserts.assertEQ(test21(val3, val4, rI), (int)(4*val3.d1 + 4*val4.x1 + 6*rI));
598             Asserts.assertEQ(test21(val4, val4, rI), 4*val4.x1 + 4*val4.x1 + 6*rI);
599             Asserts.assertEQ(test21(obj, val4, rI), obj.x + 4*val4.x1 + 6*rI);
600         }
601 
602         // Trigger deoptimization
603         Asserts.assertEQ(val1.test3(other, other, rI, true).getValue(), val1.x + other.x + rI);
604         Asserts.assertEQ(obj.test3(other, other, rI, true).getValue(), obj.x + other.x + rI);
605 
606         // Check results of methods still calling the deoptimized methods
607         Asserts.assertEQ(test9(val1, other, rI, false), val1.x + 2*other.x + rI);
608         Asserts.assertEQ(test9(obj, other, rI, false), obj.x + 2*other.x + rI);
609         Asserts.assertEQ(test10(obj, other, rI, false), obj.x + 2*other.x + rI);
610         Asserts.assertEQ(test10(val1, other, rI, false), val1.x + 2*other.x + rI);
611         Asserts.assertEQ(test11(val1, other, rI, false), val1.x + 2*other.x + rI);
612         Asserts.assertEQ(test11(obj, other, rI, false), obj.x + 2*other.x + rI);
613         Asserts.assertEQ(test12(obj, other, rI, false), obj.x + 2*other.x + rI);
614         Asserts.assertEQ(test12(val1, other, rI, false), val1.x + 2*other.x + rI);
615         Asserts.assertEQ(test13(val1, other, rI, false), val1.x + 2*other.x + rI);
616         Asserts.assertEQ(test13(obj, other, rI, false), obj.x + 2*other.x + rI);
617         Asserts.assertEQ(test14(obj, other, rI, false), obj.x + 2*other.x + rI);
618         Asserts.assertEQ(test14(val1, other, rI, false), val1.x + 2*other.x + rI);
619 
620         // Check with unexpected arguments
621         Asserts.assertEQ(test1(val2, other, rI), val2.x + other.x + rI);
622         Asserts.assertEQ(test2(val2, other, rI), val2.x + 2*other.x + rI);
623         Asserts.assertEQ(test5(val2, other, rI), val2.x + other.x + rI);
624         Asserts.assertEQ(test6(val2, other, rI), val2.x + 2*other.x + rI);
625         Asserts.assertEQ(test7(val1, other, rI), val1.x + other.x + rI);
626         Asserts.assertEQ(test8(val1, other, rI), val1.x + 2*other.x + rI);
627         Asserts.assertEQ(test15(val1, other, rI), val1.x + 2*other.x + rI);
628         Asserts.assertEQ(test16(obj, other, rI), obj.x + 2*other.x + rI);
629         Asserts.assertEQ(test17(obj), obj.x);
630     }
631 }