Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java
41149 views
1
/*
2
* Copyright (c) 2019, 2021, 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
* @requires !vm.graal.enabled & vm.opt.final.UseVtableBasedCHA == true
27
* @modules java.base/jdk.internal.org.objectweb.asm
28
* java.base/jdk.internal.misc
29
* java.base/jdk.internal.vm.annotation
30
* @library /test/lib /
31
* @compile Utils.java
32
* @build sun.hotspot.WhiteBox
33
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
34
*
35
* @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
36
* -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet
37
* -XX:CompileCommand=compileonly,*::m
38
* -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=dontinline,*::test
39
* -XX:CompileCommand=compileonly,*::testHelper -XX:CompileCommand=inline,*::testHelper
40
* -Xbatch -Xmixed -XX:+WhiteBoxAPI
41
* -XX:-TieredCompilation
42
* compiler.cha.StrengthReduceInterfaceCall
43
*
44
* @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
45
* -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet
46
* -XX:CompileCommand=compileonly,*::m
47
* -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=dontinline,*::test
48
* -XX:CompileCommand=compileonly,*::testHelper -XX:CompileCommand=inline,*::testHelper
49
* -Xbatch -Xmixed -XX:+WhiteBoxAPI
50
* -XX:+TieredCompilation -XX:TieredStopAtLevel=1
51
* compiler.cha.StrengthReduceInterfaceCall
52
*/
53
package compiler.cha;
54
55
import jdk.internal.vm.annotation.DontInline;
56
57
import static compiler.cha.Utils.*;
58
59
public class StrengthReduceInterfaceCall {
60
public static void main(String[] args) {
61
run(ObjectToString.class);
62
run(ObjectHashCode.class);
63
run(TwoLevelHierarchyLinear.class);
64
run(ThreeLevelHierarchyLinear.class);
65
run(ThreeLevelHierarchyAbstractVsDefault.class);
66
run(ThreeLevelDefaultHierarchy.class);
67
run(ThreeLevelDefaultHierarchy1.class);
68
System.out.println("TEST PASSED");
69
}
70
71
public static class ObjectToString extends ATest<ObjectToString.I> {
72
public ObjectToString() { super(I.class, C.class); }
73
74
interface J { String toString(); }
75
interface I extends J {}
76
77
static class C implements I {}
78
79
interface K1 extends I {}
80
interface K2 extends I { String toString(); } // K2.tS() ABSTRACT
81
// interface K3 extends I { default String toString() { return "K3"; } // K2.tS() DEFAULT
82
83
static class D implements I { public String toString() { return "D"; }}
84
85
static class DJ1 implements J {}
86
static class DJ2 implements J { public String toString() { return "DJ2"; }}
87
88
@Override
89
public Object test(I i) { return ObjectToStringHelper.testHelper(i); /* invokeinterface I.toString() */ }
90
91
@TestCase
92
public void testMono() {
93
// 0. Trigger compilation of a monomorphic call site
94
compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.toString()
95
assertCompiled();
96
97
// Dependency: none
98
99
call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
100
assertCompiled();
101
}
102
103
@TestCase
104
public void testBi() {
105
// 0. Trigger compilation of a bimorphic call site
106
compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString()
107
assertCompiled();
108
109
// Dependency: none
110
111
call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
112
assertCompiled();
113
}
114
115
@TestCase
116
public void testMega() {
117
// 0. Trigger compilation of a megamorphic call site
118
compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.toString()
119
assertCompiled();
120
121
// Dependency: none
122
// compiler.cha.StrengthReduceInterfaceCall$ObjectToString::test (5 bytes)
123
// @ 1 compiler.cha.StrengthReduceInterfaceCall$ObjectToStringHelper::test (7 bytes) inline (hot)
124
// @ 1 java.lang.Object::toString (36 bytes) virtual call
125
126
// No dependency - no invalidation
127
repeat(100, () -> call(new C(){})); // Cn <: C <: intf I
128
assertCompiled();
129
130
initialize(K1.class, // intf K1 <: intf I <: intf J
131
K2.class, // intf K2.tS ABSTRACT <: intf I <: intf J
132
DJ1.class, // DJ1 <: intf J
133
DJ2.class); // DJ2.tS <: intf J
134
assertCompiled();
135
136
initialize(D.class); // D.tS <: intf I <: intf J
137
assertCompiled();
138
139
call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
140
assertCompiled();
141
}
142
143
@Override
144
public void checkInvalidReceiver() {
145
shouldThrow(IncompatibleClassChangeError.class, () -> {
146
I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
147
test(o);
148
});
149
assertCompiled();
150
151
shouldThrow(IncompatibleClassChangeError.class, () -> {
152
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
153
test(j);
154
});
155
assertCompiled();
156
}
157
}
158
159
public static class ObjectHashCode extends ATest<ObjectHashCode.I> {
160
public ObjectHashCode() { super(I.class, C.class); }
161
162
interface J {}
163
interface I extends J {}
164
165
static class C implements I {}
166
167
interface K1 extends I {}
168
interface K2 extends I { int hashCode(); } // K2.hC() ABSTRACT
169
// interface K3 extends I { default int hashCode() { return CORRECT; } // K2.hC() DEFAULT
170
171
static class D implements I { public int hashCode() { return super.hashCode(); }}
172
173
static class DJ1 implements J {}
174
static class DJ2 implements J { public int hashCode() { return super.hashCode(); }}
175
176
@Override
177
public Object test(I i) {
178
return ObjectHashCodeHelper.testHelper(i); /* invokeinterface I.hashCode() */
179
}
180
181
@TestCase
182
public void testMono() {
183
// 0. Trigger compilation of a monomorphic call site
184
compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.hashCode()
185
assertCompiled();
186
187
// Dependency: none
188
189
call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
190
assertCompiled();
191
}
192
193
@TestCase
194
public void testBi() {
195
// 0. Trigger compilation of a bimorphic call site
196
compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString()
197
assertCompiled();
198
199
// Dependency: none
200
201
call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
202
assertCompiled();
203
}
204
205
@TestCase
206
public void testMega() {
207
// 0. Trigger compilation of a megamorphic call site
208
compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.hashCode()
209
assertCompiled();
210
211
// Dependency: none
212
213
// No dependency - no invalidation
214
repeat(100, () -> call(new C(){})); // Cn <: C <: intf I
215
assertCompiled();
216
217
initialize(K1.class, // intf K1 <: intf I <: intf J
218
K2.class, // intf K2.hC ABSTRACT <: intf I <: intf J
219
DJ1.class, // DJ1 <: intf J
220
DJ2.class); // DJ2.hC <: intf J
221
assertCompiled();
222
223
initialize(D.class); // D.hC <: intf I <: intf J
224
assertCompiled();
225
226
call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
227
assertCompiled();
228
}
229
230
@Override
231
public void checkInvalidReceiver() {
232
shouldThrow(IncompatibleClassChangeError.class, () -> {
233
I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
234
test(o);
235
});
236
assertCompiled();
237
238
shouldThrow(IncompatibleClassChangeError.class, () -> {
239
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
240
test(j);
241
});
242
assertCompiled();
243
}
244
}
245
246
public static class TwoLevelHierarchyLinear extends ATest<TwoLevelHierarchyLinear.I> {
247
public TwoLevelHierarchyLinear() { super(I.class, C.class); }
248
249
interface J { default Object m() { return WRONG; } }
250
251
interface I extends J { Object m(); }
252
static class C implements I { public Object m() { return CORRECT; }}
253
254
interface K1 extends I {}
255
interface K2 extends I { Object m(); }
256
interface K3 extends I { default Object m() { return WRONG; }}
257
interface K4 extends I { default Object m() { return CORRECT; }}
258
259
static class D implements I { public Object m() { return WRONG; }}
260
261
static class DJ1 implements J {}
262
static class DJ2 implements J { public Object m() { return WRONG; }}
263
264
@DontInline
265
public Object test(I i) {
266
return i.m();
267
}
268
269
@TestCase
270
public void testMega1() {
271
// 0. Trigger compilation of a megamorphic call site
272
compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m ABSTRACT
273
assertCompiled();
274
275
// Dependency: type = unique_concrete_method, context = I, method = C.m
276
277
checkInvalidReceiver(); // ensure proper type check is preserved
278
279
// 1. No deoptimization/invalidation on not-yet-seen receiver
280
repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
281
assertCompiled();
282
283
// 2. No dependency invalidation on class loading of unrelated classes: different context
284
initialize(K1.class, // intf K1 <: intf I.m ABSTRACT <: intf J.m DEFAULT
285
K2.class, // intf K2.m ABSTRACT <: intf I.m ABSTRACT <: intf J.m DEFAULT
286
DJ1.class, // DJ1 <: intf J.m DEFAULT
287
DJ2.class); // DJ2.m <: intf J.m DEFAULT
288
assertCompiled();
289
290
// 3. Dependency invalidation on D <: I
291
initialize(D.class); // D.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
292
assertNotCompiled();
293
294
// 4. Recompilation: no inlining, no dependencies
295
compile(megamorphic());
296
call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
297
assertCompiled();
298
299
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
300
}
301
302
@TestCase
303
public void testMega2() {
304
// 0. Trigger compilation of a megamorphic call site
305
compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
306
assertCompiled();
307
308
// Dependency: type = unique_concrete_method, context = I, method = C.m
309
310
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
311
312
// 1. No invalidation: interfaces don't participate in CHA.
313
initialize(K3.class); // intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT
314
assertCompiled();
315
316
// 2. Dependency invalidation on K3n <: I with concrete method.
317
call(new K3() { public Object m() { return CORRECT; }}); // K3n.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT
318
assertNotCompiled();
319
320
// 3. Recompilation: no inlining, no dependencies
321
compile(megamorphic());
322
call(new K3() { public Object m() { return CORRECT; }}); // K3n.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT
323
assertCompiled();
324
325
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
326
}
327
328
@TestCase
329
public void testMega3() {
330
// 0. Trigger compilation of a megamorphic call site
331
compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
332
assertCompiled();
333
334
// Dependency: type = unique_concrete_method, context = I, method = C.m
335
336
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
337
338
// 1. No invalidation: interfaces don't participate in CHA.
339
initialize(K4.class); // intf K4.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT
340
assertCompiled();
341
342
// 2. Dependency invalidation on K4n <: I with default method.
343
call(new K4() { /* default method K4.m */ }); // K4n <: intf K4.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT
344
assertNotCompiled();
345
346
// 3. Recompilation: no inlining, no dependencies
347
compile(megamorphic());
348
call(new K4() { /* default method K4.m */ }); // K4n <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT
349
assertCompiled();
350
351
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
352
}
353
354
@Override
355
public void checkInvalidReceiver() {
356
shouldThrow(IncompatibleClassChangeError.class, () -> {
357
I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
358
test(o);
359
});
360
assertCompiled();
361
362
shouldThrow(IncompatibleClassChangeError.class, () -> {
363
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
364
test(j);
365
});
366
assertCompiled();
367
}
368
}
369
370
public static class ThreeLevelHierarchyLinear extends ATest<ThreeLevelHierarchyLinear.I> {
371
public ThreeLevelHierarchyLinear() { super(I.class, C.class); }
372
373
interface J { Object m(); }
374
interface I extends J {}
375
376
interface K1 extends I {}
377
interface K2 extends I { Object m(); }
378
interface K3 extends I { default Object m() { return WRONG; }}
379
interface K4 extends I { default Object m() { return CORRECT; }}
380
381
static class C implements I { public Object m() { return CORRECT; }}
382
383
static class DI implements I { public Object m() { return WRONG; }}
384
static class DJ implements J { public Object m() { return WRONG; }}
385
386
@DontInline
387
public Object test(I i) {
388
return i.m(); // I <: J.m ABSTRACT
389
}
390
391
@TestCase
392
public void testMega1() {
393
// 0. Trigger compilation of a megamorphic call site
394
compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
395
assertCompiled();
396
397
// Dependency: type = unique_concrete_method, context = I, method = C.m
398
399
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
400
401
// 1. No deoptimization/invalidation on not-yet-seen receiver
402
repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I
403
assertCompiled(); // No deopt on not-yet-seen receiver
404
405
// 2. No dependency invalidation: different context
406
initialize(DJ.class, // DJ.m <: intf J.m ABSTRACT
407
K1.class, // intf K1 <: intf I <: intf J.m ABSTRACT
408
K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT
409
assertCompiled();
410
411
// 3. Dependency invalidation: DI.m <: I
412
initialize(DI.class); // DI.m <: intf I <: intf J.m ABSTRACT
413
assertNotCompiled();
414
415
// 4. Recompilation w/o a dependency
416
compile(megamorphic());
417
call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT
418
assertCompiled(); // no dependency
419
420
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
421
}
422
423
@TestCase
424
public void testMega2() {
425
compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
426
assertCompiled();
427
428
// Dependency: type = unique_concrete_method, context = I, method = C.m
429
430
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
431
432
// No invalidation: interfaces don't participate in CHA.
433
initialize(K3.class); // intf K3.m DEFAULT <: intf I;
434
assertCompiled();
435
436
// Dependency: type = unique_concrete_method, context = I, method = C.m
437
438
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
439
440
call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: K3.m DEFAULT <: intf I <: intf J.m ABSTRACT
441
assertNotCompiled();
442
443
// Recompilation w/o a dependency
444
compile(megamorphic());
445
// Dependency: none
446
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
447
call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT
448
assertCompiled();
449
}
450
451
@TestCase
452
public void testMega3() {
453
compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
454
assertCompiled();
455
456
// Dependency: type = unique_concrete_method, context = I, method = C.m
457
458
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
459
460
// No invalidation: interfaces don't participate in CHA.
461
initialize(K4.class); // intf K3.m DEFAULT <: intf I;
462
assertCompiled();
463
464
// Dependency: type = unique_concrete_method, context = I, method = C.m
465
466
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
467
468
call(new K4() { /* default method K4.m */ }); // K4n <: K4.m DEFAULT <: intf I <: intf J.m ABSTRACT
469
assertNotCompiled();
470
471
// Recompilation w/o a dependency
472
compile(megamorphic());
473
// Dependency: none
474
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
475
call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT
476
assertCompiled();
477
}
478
479
@Override
480
public void checkInvalidReceiver() {
481
shouldThrow(IncompatibleClassChangeError.class, () -> {
482
I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
483
test(o);
484
});
485
assertCompiled();
486
487
shouldThrow(IncompatibleClassChangeError.class, () -> {
488
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() { public Object m() { return WRONG; }}); // super interface
489
test(j);
490
});
491
assertCompiled();
492
}
493
}
494
495
public static class ThreeLevelHierarchyAbstractVsDefault extends ATest<ThreeLevelHierarchyAbstractVsDefault.I> {
496
public ThreeLevelHierarchyAbstractVsDefault() { super(I.class, C.class); }
497
498
interface J1 { default Object m() { return WRONG; } } // intf J1.m DEFAULT
499
interface J2 extends J1 { Object m(); } // intf J2.m ABSTRACT <: intf J1
500
interface I extends J1, J2 {} // intf I.m OVERPASS <: intf J1,J2
501
502
static class C implements I { public Object m() { return CORRECT; }}
503
504
@DontInline
505
public Object test(I i) {
506
return i.m(); // intf I.m OVERPASS
507
}
508
509
static class DI implements I { public Object m() { return WRONG; }}
510
511
static class DJ11 implements J1 {}
512
static class DJ12 implements J1 { public Object m() { return WRONG; }}
513
514
static class DJ2 implements J2 { public Object m() { return WRONG; }}
515
516
interface K11 extends J1 {}
517
interface K12 extends J1 { Object m(); }
518
interface K13 extends J1 { default Object m() { return WRONG; }}
519
interface K21 extends J2 {}
520
interface K22 extends J2 { Object m(); }
521
interface K23 extends J2 { default Object m() { return WRONG; }}
522
523
524
public void testMega1() {
525
// 0. Trigger compilation of megamorphic call site
526
compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT
527
assertCompiled();
528
529
// Dependency: type = unique_concrete_method, context = I, method = C.m
530
531
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
532
533
// 1. No deopt/invalidation on not-yet-seen receiver
534
repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT
535
assertCompiled();
536
537
// 2. No dependency invalidation: different context
538
initialize(K11.class, K12.class, K13.class,
539
K21.class, K22.class, K23.class);
540
541
// 3. Dependency invalidation: Cn.m <: C <: I
542
call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT
543
assertNotCompiled();
544
545
// 4. Recompilation w/o a dependency
546
compile(megamorphic());
547
call(new C() { public Object m() { return CORRECT; }});
548
assertCompiled(); // no inlining
549
550
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
551
}
552
553
public void testMega2() {
554
// 0. Trigger compilation of a megamorphic call site
555
compile(megamorphic());
556
assertCompiled();
557
558
// Dependency: type = unique_concrete_method, context = I, method = C.m
559
560
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
561
562
// 1. No dependency invalidation: different context
563
initialize(DJ11.class,
564
DJ12.class,
565
DJ2.class);
566
assertCompiled();
567
568
// 2. Dependency invalidation: DI.m <: I
569
initialize(DI.class);
570
assertNotCompiled();
571
572
// 3. Recompilation w/o a dependency
573
compile(megamorphic());
574
call(new C() { public Object m() { return CORRECT; }});
575
assertCompiled(); // no inlining
576
577
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
578
}
579
580
@Override
581
public void checkInvalidReceiver() {
582
shouldThrow(IncompatibleClassChangeError.class, () -> {
583
I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
584
test(o);
585
});
586
assertCompiled();
587
588
shouldThrow(IncompatibleClassChangeError.class, () -> {
589
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() {}); // super interface
590
test(j);
591
});
592
assertCompiled();
593
594
shouldThrow(IncompatibleClassChangeError.class, () -> {
595
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() { public Object m() { return WRONG; }}); // super interface
596
test(j);
597
});
598
assertCompiled();
599
}
600
}
601
602
public static class ThreeLevelDefaultHierarchy extends ATest<ThreeLevelDefaultHierarchy.I> {
603
public ThreeLevelDefaultHierarchy() { super(I.class, C.class); }
604
605
interface J { default Object m() { return WRONG; }}
606
interface I extends J {}
607
608
static class C implements I { public Object m() { return CORRECT; }}
609
610
interface K1 extends I {}
611
interface K2 extends I { Object m(); }
612
interface K3 extends J { default Object m() { return WRONG; }}
613
614
static class DI implements I { public Object m() { return WRONG; }}
615
static class DJ implements J { public Object m() { return WRONG; }}
616
static class DK3 implements K3 {}
617
618
@DontInline
619
public Object test(I i) {
620
return i.m();
621
}
622
623
@TestCase
624
public void testMega() {
625
// 0. Trigger compilation of a megamorphic call site
626
compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
627
assertCompiled();
628
629
// Dependency: type = unique_concrete_method, context = I, method = C.m
630
631
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
632
633
// 1. No deoptimization/invalidation on not-yet-seen receiver
634
repeat(100, () -> call(new C() {}));
635
assertCompiled();
636
637
// 2. No dependency invalidation
638
initialize(DJ.class, // DJ.m <: intf J.m ABSTRACT
639
K1.class, // intf K1 <: intf I <: intf J.m ABSTRACT
640
K2.class, // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT
641
DK3.class); // DK3.m <: intf K3.m DEFAULT <: intf J.m ABSTRACT
642
assertCompiled();
643
644
// 3. Dependency invalidation
645
initialize(DI.class); // DI.m <: intf I <: intf J.m ABSTRACT
646
assertNotCompiled();
647
648
// 4. Recompilation w/o a dependency
649
compile(megamorphic());
650
call(new C() { public Object m() { return CORRECT; }});
651
assertCompiled(); // no inlining
652
}
653
654
@Override
655
public void checkInvalidReceiver() {
656
shouldThrow(IncompatibleClassChangeError.class, () -> {
657
I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
658
test(o);
659
});
660
assertCompiled();
661
662
shouldThrow(IncompatibleClassChangeError.class, () -> {
663
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
664
test(j);
665
});
666
assertCompiled();
667
}
668
}
669
670
public static class ThreeLevelDefaultHierarchy1 extends ATest<ThreeLevelDefaultHierarchy1.I> {
671
public ThreeLevelDefaultHierarchy1() { super(I.class, C.class); }
672
673
interface J1 { Object m();}
674
interface J2 extends J1 { default Object m() { return WRONG; } }
675
interface I extends J1, J2 {}
676
677
static class C implements I { public Object m() { return CORRECT; }}
678
679
interface K1 extends I {}
680
interface K2 extends I { Object m(); }
681
interface K3 extends I { default Object m() { return WRONG; }}
682
683
static class DI implements I { public Object m() { return WRONG; }}
684
static class DJ1 implements J1 { public Object m() { return WRONG; }}
685
static class DJ2 implements J2 { public Object m() { return WRONG; }}
686
687
@DontInline
688
public Object test(I i) {
689
return i.m();
690
}
691
692
@TestCase
693
public void testMega() {
694
// 0. Trigger compilation of a megamorphic call site
695
compile(megamorphic());
696
assertCompiled();
697
698
// Dependency: type = unique_concrete_method, context = I, method = C.m
699
700
checkInvalidReceiver(); // ensure proper type check on receiver is preserved
701
702
// 1. No deoptimization/invalidation on not-yet-seen receiver
703
repeat(100, () -> call(new C() {}));
704
assertCompiled();
705
706
// 2. No dependency invalidation
707
initialize(DJ1.class,
708
DJ2.class,
709
K1.class,
710
K2.class,
711
K3.class);
712
assertCompiled();
713
714
// 3. Dependency invalidation
715
initialize(DI.class); // DI.m <: intf I <: intf J.m ABSTRACT
716
assertNotCompiled();
717
718
// 4. Recompilation w/o a dependency
719
compile(megamorphic());
720
call(new C() { public Object m() { return CORRECT; }});
721
assertCompiled(); // no inlining
722
}
723
724
@Override
725
public void checkInvalidReceiver() {
726
shouldThrow(IncompatibleClassChangeError.class, () -> {
727
I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
728
test(o);
729
});
730
assertCompiled();
731
732
shouldThrow(IncompatibleClassChangeError.class, () -> {
733
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() { public Object m() { return WRONG; } }); // super interface
734
test(j);
735
});
736
assertCompiled();
737
738
shouldThrow(IncompatibleClassChangeError.class, () -> {
739
I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() {}); // super interface
740
test(j);
741
});
742
assertCompiled();
743
}
744
}
745
}
746
747