3131import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .FALL_THROUGH ;
3232import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .FIELD_READ ;
3333import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .FIELD_WRITE ;
34+ import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .IF_BRANCH_PROFILED ;
3435import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .INVOKE ;
3536import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .LOAD ;
3637import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .STOP ;
3738import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .STORE ;
3839import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .TRAP ;
40+ import static com .oracle .svm .interpreter .metadata .Bytecodes .Flags .TYPE_PROFILED ;
3941
4042import java .lang .reflect .Field ;
4143import java .lang .reflect .Modifier ;
@@ -325,6 +327,14 @@ static class Flags {
325327 * Denotes the 4 INVOKE* instructions.
326328 */
327329 static final int INVOKE = 0x00001000 ;
330+ /**
331+ * Denotes all binary branches that are subject to branch profiling.
332+ */
333+ static final int IF_BRANCH_PROFILED = 0x00002000 ;
334+ /**
335+ * Denotes all instructions that are subject to type profiling.
336+ */
337+ static final int TYPE_PROFILED = 0x00004000 ;
328338 }
329339
330340 // Performs a sanity check that none of the flags overlap.
@@ -423,7 +433,7 @@ static class Flags {
423433 def (LALOAD , "laload" , "b" , 0 , TRAP );
424434 def (FALOAD , "faload" , "b" , -1 , TRAP );
425435 def (DALOAD , "daload" , "b" , 0 , TRAP );
426- def (AALOAD , "aaload" , "b" , -1 , TRAP );
436+ def (AALOAD , "aaload" , "b" , -1 , TRAP | TYPE_PROFILED );
427437 def (BALOAD , "baload" , "b" , -1 , TRAP );
428438 def (CALOAD , "caload" , "b" , -1 , TRAP );
429439 def (SALOAD , "saload" , "b" , -1 , TRAP );
@@ -456,7 +466,7 @@ static class Flags {
456466 def (LASTORE , "lastore" , "b" , -4 , TRAP );
457467 def (FASTORE , "fastore" , "b" , -3 , TRAP );
458468 def (DASTORE , "dastore" , "b" , -4 , TRAP );
459- def (AASTORE , "aastore" , "b" , -3 , TRAP );
469+ def (AASTORE , "aastore" , "b" , -3 , TRAP | TYPE_PROFILED );
460470 def (BASTORE , "bastore" , "b" , -3 , TRAP );
461471 def (CASTORE , "castore" , "b" , -3 , TRAP );
462472 def (SASTORE , "sastore" , "b" , -3 , TRAP );
@@ -526,20 +536,20 @@ static class Flags {
526536 def (FCMPG , "fcmpg" , "b" , -1 );
527537 def (DCMPL , "dcmpl" , "b" , -3 );
528538 def (DCMPG , "dcmpg" , "b" , -3 );
529- def (IFEQ , "ifeq" , "boo" , -1 , FALL_THROUGH | BRANCH );
530- def (IFNE , "ifne" , "boo" , -1 , FALL_THROUGH | BRANCH );
531- def (IFLT , "iflt" , "boo" , -1 , FALL_THROUGH | BRANCH );
532- def (IFGE , "ifge" , "boo" , -1 , FALL_THROUGH | BRANCH );
533- def (IFGT , "ifgt" , "boo" , -1 , FALL_THROUGH | BRANCH );
534- def (IFLE , "ifle" , "boo" , -1 , FALL_THROUGH | BRANCH );
535- def (IF_ICMPEQ , "if_icmpeq" , "boo" , -2 , COMMUTATIVE | FALL_THROUGH | BRANCH );
536- def (IF_ICMPNE , "if_icmpne" , "boo" , -2 , COMMUTATIVE | FALL_THROUGH | BRANCH );
537- def (IF_ICMPLT , "if_icmplt" , "boo" , -2 , FALL_THROUGH | BRANCH );
538- def (IF_ICMPGE , "if_icmpge" , "boo" , -2 , FALL_THROUGH | BRANCH );
539- def (IF_ICMPGT , "if_icmpgt" , "boo" , -2 , FALL_THROUGH | BRANCH );
540- def (IF_ICMPLE , "if_icmple" , "boo" , -2 , FALL_THROUGH | BRANCH );
541- def (IF_ACMPEQ , "if_acmpeq" , "boo" , -2 , COMMUTATIVE | FALL_THROUGH | BRANCH );
542- def (IF_ACMPNE , "if_acmpne" , "boo" , -2 , COMMUTATIVE | FALL_THROUGH | BRANCH );
539+ def (IFEQ , "ifeq" , "boo" , -1 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
540+ def (IFNE , "ifne" , "boo" , -1 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
541+ def (IFLT , "iflt" , "boo" , -1 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
542+ def (IFGE , "ifge" , "boo" , -1 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
543+ def (IFGT , "ifgt" , "boo" , -1 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
544+ def (IFLE , "ifle" , "boo" , -1 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
545+ def (IF_ICMPEQ , "if_icmpeq" , "boo" , -2 , COMMUTATIVE | FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
546+ def (IF_ICMPNE , "if_icmpne" , "boo" , -2 , COMMUTATIVE | FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
547+ def (IF_ICMPLT , "if_icmplt" , "boo" , -2 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
548+ def (IF_ICMPGE , "if_icmpge" , "boo" , -2 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
549+ def (IF_ICMPGT , "if_icmpgt" , "boo" , -2 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
550+ def (IF_ICMPLE , "if_icmple" , "boo" , -2 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
551+ def (IF_ACMPEQ , "if_acmpeq" , "boo" , -2 , COMMUTATIVE | FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
552+ def (IF_ACMPNE , "if_acmpne" , "boo" , -2 , COMMUTATIVE | FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
543553 def (GOTO , "goto" , "boo" , 0 , STOP | BRANCH );
544554 def (JSR , "jsr" , "boo" , 0 , STOP | BRANCH );
545555 def (RET , "ret" , "bi" , 0 , STOP );
@@ -555,24 +565,24 @@ static class Flags {
555565 def (PUTSTATIC , "putstatic" , "bjj" , -1 , TRAP | FIELD_WRITE );
556566 def (GETFIELD , "getfield" , "bjj" , 0 , TRAP | FIELD_READ );
557567 def (PUTFIELD , "putfield" , "bjj" , -2 , TRAP | FIELD_WRITE );
558- def (INVOKEVIRTUAL , "invokevirtual" , "bjj" , -1 , TRAP | INVOKE );
559- def (INVOKESPECIAL , "invokespecial" , "bjj" , -1 , TRAP | INVOKE );
560- def (INVOKESTATIC , "invokestatic" , "bjj" , 0 , TRAP | INVOKE );
561- def (INVOKEINTERFACE , "invokeinterface" , "bjja_" , -1 , TRAP | INVOKE );
562- def (INVOKEDYNAMIC , "invokedynamic" , "bjjjj" , 0 , TRAP | INVOKE );
568+ def (INVOKEVIRTUAL , "invokevirtual" , "bjj" , -1 , TRAP | INVOKE | TYPE_PROFILED );
569+ def (INVOKESPECIAL , "invokespecial" , "bjj" , -1 , TRAP | INVOKE | TYPE_PROFILED );
570+ def (INVOKESTATIC , "invokestatic" , "bjj" , 0 , TRAP | INVOKE | TYPE_PROFILED );
571+ def (INVOKEINTERFACE , "invokeinterface" , "bjja_" , -1 , TRAP | INVOKE | TYPE_PROFILED );
572+ def (INVOKEDYNAMIC , "invokedynamic" , "bjjjj" , 0 , TRAP | INVOKE | TYPE_PROFILED );
563573 def (NEW , "new" , "bii" , 1 , TRAP );
564574 def (NEWARRAY , "newarray" , "bc" , 0 , TRAP );
565575 def (ANEWARRAY , "anewarray" , "bii" , 0 , TRAP );
566576 def (ARRAYLENGTH , "arraylength" , "b" , 0 , TRAP );
567577 def (ATHROW , "athrow" , "b" , -1 , TRAP | STOP );
568- def (CHECKCAST , "checkcast" , "bii" , 0 , TRAP );
569- def (INSTANCEOF , "instanceof" , "bii" , 0 , TRAP );
578+ def (CHECKCAST , "checkcast" , "bii" , 0 , TRAP | TYPE_PROFILED );
579+ def (INSTANCEOF , "instanceof" , "bii" , 0 , TRAP | TYPE_PROFILED );
570580 def (MONITORENTER , "monitorenter" , "b" , -1 , TRAP );
571581 def (MONITOREXIT , "monitorexit" , "b" , -1 , TRAP );
572582 def (WIDE , "wide" , "" , 0 );
573583 def (MULTIANEWARRAY , "multianewarray" , "biic" , 1 , TRAP );
574- def (IFNULL , "ifnull" , "boo" , -1 , FALL_THROUGH | BRANCH );
575- def (IFNONNULL , "ifnonnull" , "boo" , -1 , FALL_THROUGH | BRANCH );
584+ def (IFNULL , "ifnull" , "boo" , -1 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
585+ def (IFNONNULL , "ifnonnull" , "boo" , -1 , FALL_THROUGH | BRANCH | IF_BRANCH_PROFILED );
576586 def (GOTO_W , "goto_w" , "boooo" , 0 , STOP | BRANCH );
577587 def (JSR_W , "jsr_w" , "boooo" , 0 , STOP | BRANCH );
578588 def (BREAKPOINT , "breakpoint" , "b" , 0 , TRAP );
@@ -648,6 +658,31 @@ public static boolean isBranch(int opcode) {
648658 return (flagsArray [opcode & 0xff ] & BRANCH ) != 0 ;
649659 }
650660
661+ /**
662+ * Determines if a given opcode is an instruction that is subject to binary branch profiling in
663+ * the interpreter. Binary branches are instructions that have 2 successors - the taken and not
664+ * taken successor.
665+ *
666+ * Note that {@link #GOTO} and {@link #JSR} are not considered a profiled if branch
667+ *
668+ * @param opcode an opcode to test
669+ * @return {@code true} iff {@code opcode} is a binary branch instruction that is profiled
670+ */
671+ public static boolean isProfiledIfBranch (int opcode ) {
672+ return (flagsArray [opcode & 0xff ] & IF_BRANCH_PROFILED ) != 0 ;
673+ }
674+
675+ /**
676+ * Determines if a given opcode is an instruction that is subject to type profiling. This covers
677+ * all instructions that deal with objects of a dynamic type.
678+ *
679+ * @param opcode an opcode to test
680+ * @return {@code true} iff {@code opcode} is a type profiled branch instruction
681+ */
682+ public static boolean isTypeProfiled (int opcode ) {
683+ return (flagsArray [opcode & 0xff ] & TYPE_PROFILED ) != 0 ;
684+ }
685+
651686 /**
652687 * Determines if a given opcode denotes a conditional branch.
653688 *
0 commit comments