@@ -45,7 +45,7 @@ static IDATA matchStack (J9BytecodeVerificationData * verifyData, J9BranchTarget
4545static IDATA findAndMatchStack (J9BytecodeVerificationData * verifyData , IDATA targetPC , IDATA currentPC );
4646static IDATA verifyExceptions (J9BytecodeVerificationData * verifyData );
4747static J9BranchTargetStack * nextStack (J9BytecodeVerificationData * verifyData , UDATA * nextMapIndex , IDATA * nextStackPC );
48- static IDATA nextExceptionStart (J9BytecodeVerificationData * verifyData , J9ROMMethod * romMethod , IDATA lastPC );
48+ static void nextExceptionPC (J9BytecodeVerificationData * verifyData , J9ROMMethod * romMethod , IDATA * exceptionStartPC , IDATA * exceptionEndPC );
4949static void storeArgumentErrorData (J9BytecodeVerificationData * verifyData , U_32 errorCurrentFramePosition , U_16 errorArgumentIndex );
5050static void storeMethodInfo (J9BytecodeVerificationData * verifyData , J9UTF8 * errorClassString , J9UTF8 * errorMethodString , J9UTF8 * errorSignatureString , IDATA currentPC );
5151
@@ -447,16 +447,16 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
447447 UDATA classIndex , maxStack ;
448448 UDATA wideIndex = FALSE;
449449 IDATA nextStackPC ;
450- IDATA nextExceptionStartPC ;
450+ IDATA exceptionStartPC = -1 ;
451+ IDATA exceptionEndPC = -1 ;
451452 IDATA rc = 0 ;
452453 U_8 returnBytecode ;
453454 UDATA errorModule = J9NLS_BCV_ERR_BYTECODES_INVALID__MODULE ; /* defaults to BCV NLS catalog */
454455 U_16 errorType ;
455456 I_16 offset16 ;
456457 I_32 offset32 ;
457458 UDATA argCount ;
458- UDATA checkIfInsideException = romMethod -> modifiers & J9AccMethodHasExceptionInfo ;
459- UDATA tempStoreChange ;
459+ BOOLEAN tempStoreChange = FALSE;
460460 J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD (romMethod );
461461 J9ExceptionHandler * handler ;
462462 J9UTF8 * catchName ;
@@ -523,7 +523,7 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
523523 currentMapData = nextStack (verifyData , & nextMapIndex , & nextStackPC );
524524
525525 /* Determine where the first region of bytecodes covered by an exception handler is */
526- nextExceptionStartPC = nextExceptionStart (verifyData , romMethod , -1 );
526+ nextExceptionPC (verifyData , romMethod , & exceptionStartPC , & exceptionEndPC );
527527
528528 /* walk the bytecodes linearly */
529529 while (pc < length ) {
@@ -570,8 +570,19 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
570570 currentMapData = nextStack (verifyData , & nextMapIndex , & nextStackPC );
571571 }
572572
573- /* Check the stack against the exception handler stack */
574- if (pc == (UDATA ) nextExceptionStartPC ) {
573+ /* Check the current state against the exception handlers if:
574+ * - This is the first bytecode of the try/catch block
575+ * - The temps (locals) type state has changed due to a store
576+ * instruction. If it is within the same exception range ensure
577+ * that the types are still compatible.
578+ */
579+ if ((pc == (UDATA )exceptionStartPC )
580+ || (tempStoreChange && ((exceptionStartPC < pc ) && (pc < exceptionEndPC )))
581+ ) {
582+ /* If this is the first pc of an exception tempStoreChange does not apply. */
583+ if ((pc == (UDATA )exceptionStartPC ) && tempStoreChange ) {
584+ tempStoreChange = FALSE;
585+ }
575586 handler = J9EXCEPTIONINFO_HANDLERS (exceptionInfo );
576587 SAVE_STACKTOP (liveStack , stackTop );
577588
@@ -582,7 +593,9 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
582593
583594 /* Find all exception handlers from here */
584595 for (i = exceptionInfo -> catchCount ; i ; i -- , handler ++ ) {
585- if (handler -> startPC == pc ) {
596+ if ((handler -> startPC == pc )
597+ || (tempStoreChange && ((UDATA )pc >= handler -> startPC ) && ((UDATA )pc < handler -> endPC ))
598+ ) {
586599 /* Check the maps at the handler PC */
587600 /* Modify the liveStack temporarily to contain the handler exception */
588601 if (handler -> exceptionClassIndex ) {
@@ -612,8 +625,13 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
612625 liveStack -> stackElements [liveStack -> stackBaseIndex ] = originalStackZeroEntry ;
613626 stackTop = originalStackTop ;
614627
615- /* Get next exception start PC of interest */
616- nextExceptionStartPC = nextExceptionStart (verifyData , romMethod , nextExceptionStartPC );
628+ if (!tempStoreChange ) {
629+ /* Get next exception start PC of interest */
630+ nextExceptionPC (verifyData , romMethod , & exceptionStartPC , & exceptionEndPC );
631+ }
632+ }
633+ if (tempStoreChange ) {
634+ tempStoreChange = FALSE;
617635 }
618636
619637 bcIndex = code + pc ;
@@ -809,8 +827,6 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
809827 goto _inconsistentStack ;
810828 }
811829
812- tempStoreChange = FALSE;
813-
814830 if (type != type1 ) {
815831 if ((type1 != BCV_GENERIC_OBJECT ) || (type & BCV_TAG_BASE_TYPE_OR_TOP )) {
816832 inconsistentStack = TRUE;
@@ -830,56 +846,6 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
830846 }
831847 tempStoreChange |= (type != temps [index ]);
832848 STORE_TEMP (index , type );
833-
834- if (checkIfInsideException && tempStoreChange ) {
835- /* If we've stored a value into an arg/local, and it's of a different type than was
836- * originally there, we need to ensure that we are still compatible with all our
837- * exception handlers.
838- *
839- * For all exception handlers covering this instruction
840- */
841- handler = J9EXCEPTIONINFO_HANDLERS (exceptionInfo );
842- SAVE_STACKTOP (liveStack , stackTop );
843-
844- /* Save the current liveStack element zero */
845- /* Reset the stack pointer to push the exception on the empty stack */
846- originalStackTop = stackTop ;
847- originalStackZeroEntry = liveStack -> stackElements [liveStack -> stackBaseIndex ];
848-
849- /* Find all exception handlers from here */
850- for (i = exceptionInfo -> catchCount ; i ; i -- , handler ++ ) {
851- if (((UDATA ) start >= handler -> startPC ) && ((UDATA ) start < handler -> endPC )) {
852- #ifdef DEBUG_BCV
853- printf ("exception map change check at startPC: %d\n" , handler -> startPC );
854- #endif
855- /* Check the maps at the handler PC */
856- /* Modify the liveStack temporarily to contain the handler exception */
857- if (handler -> exceptionClassIndex ) {
858- catchName = J9ROMSTRINGREF_UTF8DATA ((J9ROMStringRef * )(& constantPool [handler -> exceptionClassIndex ]));
859- catchClass = convertClassNameToStackMapType (verifyData , J9UTF8_DATA (catchName ), J9UTF8_LENGTH (catchName ), 0 , 0 );
860- } else {
861- catchClass = BCV_JAVA_LANG_THROWABLE_INDEX ;
862- catchClass <<= BCV_CLASS_INDEX_SHIFT ;
863- }
864-
865- stackTop = & (liveStack -> stackElements [liveStack -> stackBaseIndex ]);
866- PUSH (catchClass );
867- SAVE_STACKTOP (liveStack , stackTop );
868-
869- rc = findAndMatchStack (verifyData , handler -> handlerPC , start );
870- if (BCV_SUCCESS != rc ) {
871- if (BCV_ERR_INSUFFICIENT_MEMORY == rc ) {
872- goto _outOfMemoryError ;
873- }
874- goto _mapError ;
875- }
876- }
877- }
878-
879- /* Restore liveStack */
880- liveStack -> stackElements [liveStack -> stackBaseIndex ] = originalStackZeroEntry ;
881- stackTop = originalStackTop ;
882- }
883849 break ;
884850
885851 case RTV_ARRAY_STORE :
@@ -2862,23 +2828,34 @@ nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *n
28622828 return returnStack ;
28632829}
28642830
2865- /* Return the next pc in the method that is an exception handler start address */
2866-
2867- static IDATA
2868- nextExceptionStart (J9BytecodeVerificationData * verifyData , J9ROMMethod * romMethod , IDATA lastPC )
2831+ /**
2832+ * Return the pc range for the next exception handler in romMethod.
2833+ * @param verifyData pointer to J9BytecodeVerificationData
2834+ * @param romMethod the method whose exception handling information is searched
2835+ * @param exceptionStartPC contains the starting pc of the last exception. It will
2836+ * be set to the next exception start pc if one exists otherwise will be set to
2837+ * the last possible pc for the method.
2838+ * @param exceptionEndPC will be set to the next exception end pc if one exists
2839+ * otherwise will be set to the last possible pc for the method.
2840+ */
2841+ static void
2842+ nextExceptionPC (J9BytecodeVerificationData * verifyData , J9ROMMethod * romMethod , IDATA * exceptionStartPC , IDATA * exceptionEndPC )
28692843{
28702844 /* Method size */
2871- IDATA nextPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD (romMethod );
2845+ IDATA nextStartPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD (romMethod );
2846+ IDATA nextEndPC = nextStartPC ;
28722847
28732848 if (romMethod -> modifiers & CFR_ACC_HAS_EXCEPTION_INFO ) {
28742849 J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD (romMethod );
28752850 J9ExceptionHandler * handler = J9EXCEPTIONINFO_HANDLERS (exceptionInfo );
28762851 UDATA i ;
28772852
28782853 for (i = exceptionInfo -> catchCount ; i ; i -- , handler ++ ) {
2879- if (((IDATA ) handler -> startPC ) > lastPC ) {
2880- if (handler -> startPC < (UDATA ) nextPC ) {
2881- nextPC = handler -> startPC ;
2854+ /* exceptionStartPC has the last exception start. */
2855+ if (((IDATA )handler -> startPC ) > * exceptionStartPC ) {
2856+ if (handler -> startPC < (UDATA ) nextStartPC ) {
2857+ nextStartPC = handler -> startPC ;
2858+ nextEndPC = handler -> endPC ;
28822859 }
28832860 }
28842861 }
@@ -2889,10 +2866,12 @@ nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMeth
28892866 J9UTF8_DATA (J9ROMMETHOD_NAME (verifyData -> romMethod )),
28902867 (UDATA ) J9UTF8_LENGTH (J9ROMMETHOD_SIGNATURE (verifyData -> romMethod )),
28912868 J9UTF8_DATA (J9ROMMETHOD_SIGNATURE (verifyData -> romMethod )),
2892- exceptionInfo -> catchCount , lastPC , nextPC ,
2869+ exceptionInfo -> catchCount , * exceptionStartPC , nextStartPC ,
28932870 J9_BYTECODE_SIZE_FROM_ROM_METHOD (romMethod ));
28942871 }
2895- return nextPC ;
2872+
2873+ * exceptionStartPC = nextStartPC ;
2874+ * exceptionEndPC = nextEndPC ;
28962875}
28972876
28982877
0 commit comments