36 * |
34 * |
37 * @author igor.ignatyev@oracle.com |
35 * @author igor.ignatyev@oracle.com |
38 */ |
36 */ |
39 public abstract class CompilerWhiteBoxTest { |
37 public abstract class CompilerWhiteBoxTest { |
40 /** {@code CompLevel::CompLevel_none} -- Interpreter */ |
38 /** {@code CompLevel::CompLevel_none} -- Interpreter */ |
41 protected static final int COMP_LEVEL_NONE = 0; |
39 public static final int COMP_LEVEL_NONE = 0; |
42 /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */ |
40 /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */ |
43 protected static final int COMP_LEVEL_ANY = -1; |
41 public static final int COMP_LEVEL_ANY = -1; |
44 /** {@code CompLevel::CompLevel_simple} -- C1 */ |
42 /** {@code CompLevel::CompLevel_simple} -- C1 */ |
45 protected static final int COMP_LEVEL_SIMPLE = 1; |
43 public static final int COMP_LEVEL_SIMPLE = 1; |
46 /** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation & backedge counters */ |
44 /** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation & backedge counters */ |
47 protected static final int COMP_LEVEL_LIMITED_PROFILE = 2; |
45 public static final int COMP_LEVEL_LIMITED_PROFILE = 2; |
48 /** {@code CompLevel::CompLevel_full_profile} -- C1, invocation & backedge counters + mdo */ |
46 /** {@code CompLevel::CompLevel_full_profile} -- C1, invocation & backedge counters + mdo */ |
49 protected static final int COMP_LEVEL_FULL_PROFILE = 3; |
47 public static final int COMP_LEVEL_FULL_PROFILE = 3; |
50 /** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */ |
48 /** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */ |
51 protected static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; |
49 public static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; |
52 /** Maximal value for CompLevel */ |
50 /** Maximal value for CompLevel */ |
53 protected static final int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION; |
51 public static final int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION; |
54 |
52 |
55 /** Instance of WhiteBox */ |
53 /** Instance of WhiteBox */ |
56 protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); |
54 protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); |
57 /** Value of {@code -XX:CompileThreshold} */ |
55 /** Value of {@code -XX:CompileThreshold} */ |
58 protected static final int COMPILE_THRESHOLD |
56 protected static final int COMPILE_THRESHOLD |
439 * Skip the test for the specified value of Tiered Compilation |
437 * Skip the test for the specified value of Tiered Compilation |
440 * @param value of TieredCompilation the test should not run with |
438 * @param value of TieredCompilation the test should not run with |
441 * @return {@code true} if the test should be skipped, |
439 * @return {@code true} if the test should be skipped, |
442 * {@code false} otherwise |
440 * {@code false} otherwise |
443 */ |
441 */ |
444 protected static boolean skipOnTieredCompilation(boolean value) { |
442 public static boolean skipOnTieredCompilation(boolean value) { |
445 if (value == CompilerWhiteBoxTest.TIERED_COMPILATION) { |
443 if (value == CompilerWhiteBoxTest.TIERED_COMPILATION) { |
446 System.err.println("Test isn't applicable w/ " |
444 System.err.println("Test isn't applicable w/ " |
447 + (value ? "enabled" : "disabled") |
445 + (value ? "enabled" : "disabled") |
448 + "TieredCompilation. Skip test."); |
446 + "TieredCompilation. Skip test."); |
449 return true; |
447 return true; |
450 } |
448 } |
451 return false; |
449 return false; |
452 } |
450 } |
453 } |
451 } |
454 |
452 |
455 enum SimpleTestCase implements CompilerWhiteBoxTest.TestCase { |
|
456 /** constructor test case */ |
|
457 CONSTRUCTOR_TEST(Helper.CONSTRUCTOR, Helper.CONSTRUCTOR_CALLABLE, false), |
|
458 /** method test case */ |
|
459 METHOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE, false), |
|
460 /** static method test case */ |
|
461 STATIC_TEST(Helper.STATIC, Helper.STATIC_CALLABLE, false), |
|
462 /** OSR constructor test case */ |
|
463 OSR_CONSTRUCTOR_TEST(Helper.OSR_CONSTRUCTOR, |
|
464 Helper.OSR_CONSTRUCTOR_CALLABLE, true), |
|
465 /** OSR method test case */ |
|
466 OSR_METHOD_TEST(Helper.OSR_METHOD, Helper.OSR_METHOD_CALLABLE, true), |
|
467 /** OSR static method test case */ |
|
468 OSR_STATIC_TEST(Helper.OSR_STATIC, Helper.OSR_STATIC_CALLABLE, true); |
|
469 |
|
470 private final Executable executable; |
|
471 private final Callable<Integer> callable; |
|
472 private final boolean isOsr; |
|
473 |
|
474 private SimpleTestCase(Executable executable, Callable<Integer> callable, |
|
475 boolean isOsr) { |
|
476 this.executable = executable; |
|
477 this.callable = callable; |
|
478 this.isOsr = isOsr; |
|
479 } |
|
480 |
|
481 @Override |
|
482 public Executable getExecutable() { |
|
483 return executable; |
|
484 } |
|
485 |
|
486 @Override |
|
487 public Callable<Integer> getCallable() { |
|
488 return callable; |
|
489 } |
|
490 |
|
491 @Override |
|
492 public boolean isOsr() { |
|
493 return isOsr; |
|
494 } |
|
495 |
|
496 private static class Helper { |
|
497 |
|
498 private static final Callable<Integer> CONSTRUCTOR_CALLABLE |
|
499 = new Callable<Integer>() { |
|
500 @Override |
|
501 public Integer call() throws Exception { |
|
502 return new Helper(1337).hashCode(); |
|
503 } |
|
504 }; |
|
505 |
|
506 private static final Callable<Integer> METHOD_CALLABLE |
|
507 = new Callable<Integer>() { |
|
508 private final Helper helper = new Helper(); |
|
509 |
|
510 @Override |
|
511 public Integer call() throws Exception { |
|
512 return helper.method(); |
|
513 } |
|
514 }; |
|
515 |
|
516 private static final Callable<Integer> STATIC_CALLABLE |
|
517 = new Callable<Integer>() { |
|
518 @Override |
|
519 public Integer call() throws Exception { |
|
520 return staticMethod(); |
|
521 } |
|
522 }; |
|
523 |
|
524 private static final Callable<Integer> OSR_CONSTRUCTOR_CALLABLE |
|
525 = new Callable<Integer>() { |
|
526 @Override |
|
527 public Integer call() throws Exception { |
|
528 return new Helper(null, CompilerWhiteBoxTest.BACKEDGE_THRESHOLD).hashCode(); |
|
529 } |
|
530 }; |
|
531 |
|
532 private static final Callable<Integer> OSR_METHOD_CALLABLE |
|
533 = new Callable<Integer>() { |
|
534 private final Helper helper = new Helper(); |
|
535 |
|
536 @Override |
|
537 public Integer call() throws Exception { |
|
538 return helper.osrMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD); |
|
539 } |
|
540 }; |
|
541 |
|
542 private static final Callable<Integer> OSR_STATIC_CALLABLE |
|
543 = new Callable<Integer>() { |
|
544 @Override |
|
545 public Integer call() throws Exception { |
|
546 return osrStaticMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD); |
|
547 } |
|
548 }; |
|
549 |
|
550 private static final Constructor CONSTRUCTOR; |
|
551 private static final Constructor OSR_CONSTRUCTOR; |
|
552 private static final Method METHOD; |
|
553 private static final Method STATIC; |
|
554 private static final Method OSR_METHOD; |
|
555 private static final Method OSR_STATIC; |
|
556 |
|
557 static { |
|
558 try { |
|
559 CONSTRUCTOR = Helper.class.getDeclaredConstructor(int.class); |
|
560 } catch (NoSuchMethodException | SecurityException e) { |
|
561 throw new RuntimeException( |
|
562 "exception on getting method Helper.<init>(int)", e); |
|
563 } |
|
564 try { |
|
565 OSR_CONSTRUCTOR = Helper.class.getDeclaredConstructor( |
|
566 Object.class, long.class); |
|
567 } catch (NoSuchMethodException | SecurityException e) { |
|
568 throw new RuntimeException( |
|
569 "exception on getting method Helper.<init>(Object, long)", e); |
|
570 } |
|
571 METHOD = getMethod("method"); |
|
572 STATIC = getMethod("staticMethod"); |
|
573 OSR_METHOD = getMethod("osrMethod", long.class); |
|
574 OSR_STATIC = getMethod("osrStaticMethod", long.class); |
|
575 } |
|
576 |
|
577 private static Method getMethod(String name, Class<?>... parameterTypes) { |
|
578 try { |
|
579 return Helper.class.getDeclaredMethod(name, parameterTypes); |
|
580 } catch (NoSuchMethodException | SecurityException e) { |
|
581 throw new RuntimeException( |
|
582 "exception on getting method Helper." + name, e); |
|
583 } |
|
584 } |
|
585 |
|
586 private static int staticMethod() { |
|
587 return 1138; |
|
588 } |
|
589 |
|
590 private int method() { |
|
591 return 42; |
|
592 } |
|
593 |
|
594 /** |
|
595 * Deoptimizes all non-osr versions of the given executable after |
|
596 * compilation finished. |
|
597 * |
|
598 * @param e Executable |
|
599 * @throws Exception |
|
600 */ |
|
601 private static void waitAndDeoptimize(Executable e) { |
|
602 CompilerWhiteBoxTest.waitBackgroundCompilation(e); |
|
603 if (WhiteBox.getWhiteBox().isMethodQueuedForCompilation(e)) { |
|
604 throw new RuntimeException(e + " must not be in queue"); |
|
605 } |
|
606 // Deoptimize non-osr versions of executable |
|
607 WhiteBox.getWhiteBox().deoptimizeMethod(e, false); |
|
608 } |
|
609 |
|
610 /** |
|
611 * Executes the method multiple times to make sure we have |
|
612 * enough profiling information before triggering an OSR |
|
613 * compilation. Otherwise the C2 compiler may add uncommon traps. |
|
614 * |
|
615 * @param m Method to be executed |
|
616 * @return Number of times the method was executed |
|
617 * @throws Exception |
|
618 */ |
|
619 private static int warmup(Method m) throws Exception { |
|
620 waitAndDeoptimize(m); |
|
621 Helper helper = new Helper(); |
|
622 int result = 0; |
|
623 for (long i = 0; i < CompilerWhiteBoxTest.THRESHOLD; ++i) { |
|
624 result += (int)m.invoke(helper, 1); |
|
625 } |
|
626 // Wait to make sure OSR compilation is not blocked by |
|
627 // non-OSR compilation in the compile queue |
|
628 CompilerWhiteBoxTest.waitBackgroundCompilation(m); |
|
629 return result; |
|
630 } |
|
631 |
|
632 /** |
|
633 * Executes the constructor multiple times to make sure we |
|
634 * have enough profiling information before triggering an OSR |
|
635 * compilation. Otherwise the C2 compiler may add uncommon traps. |
|
636 * |
|
637 * @param c Constructor to be executed |
|
638 * @return Number of times the constructor was executed |
|
639 * @throws Exception |
|
640 */ |
|
641 private static int warmup(Constructor c) throws Exception { |
|
642 waitAndDeoptimize(c); |
|
643 int result = 0; |
|
644 for (long i = 0; i < CompilerWhiteBoxTest.THRESHOLD; ++i) { |
|
645 result += c.newInstance(null, 1).hashCode(); |
|
646 } |
|
647 // Wait to make sure OSR compilation is not blocked by |
|
648 // non-OSR compilation in the compile queue |
|
649 CompilerWhiteBoxTest.waitBackgroundCompilation(c); |
|
650 return result; |
|
651 } |
|
652 |
|
653 private static int osrStaticMethod(long limit) throws Exception { |
|
654 int result = 0; |
|
655 if (limit != 1) { |
|
656 result = warmup(OSR_STATIC); |
|
657 } |
|
658 // Trigger osr compilation |
|
659 for (long i = 0; i < limit; ++i) { |
|
660 result += staticMethod(); |
|
661 } |
|
662 return result; |
|
663 } |
|
664 |
|
665 private int osrMethod(long limit) throws Exception { |
|
666 int result = 0; |
|
667 if (limit != 1) { |
|
668 result = warmup(OSR_METHOD); |
|
669 } |
|
670 // Trigger osr compilation |
|
671 for (long i = 0; i < limit; ++i) { |
|
672 result += method(); |
|
673 } |
|
674 return result; |
|
675 } |
|
676 |
|
677 private final int x; |
|
678 |
|
679 // for method and OSR method test case |
|
680 public Helper() { |
|
681 x = 0; |
|
682 } |
|
683 |
|
684 // for OSR constructor test case |
|
685 private Helper(Object o, long limit) throws Exception { |
|
686 int result = 0; |
|
687 if (limit != 1) { |
|
688 result = warmup(OSR_CONSTRUCTOR); |
|
689 } |
|
690 // Trigger osr compilation |
|
691 for (long i = 0; i < limit; ++i) { |
|
692 result += method(); |
|
693 } |
|
694 x = result; |
|
695 } |
|
696 |
|
697 // for constructor test case |
|
698 private Helper(int x) { |
|
699 this.x = x; |
|
700 } |
|
701 |
|
702 @Override |
|
703 public int hashCode() { |
|
704 return x; |
|
705 } |
|
706 } |
|
707 } |
|