@ -180,11 +180,7 @@ public class TransformExceptionHandlers {
* @param ret the ReturnBlock .
* /
private void removeReturnLocal ( ReturnBlock ret ) {
if ( ret . outer = = null
| | ! ( ret . outer instanceof SequentialBlock ) )
return ;
StructuredBlock pred = ret . outer . getSubBlocks ( ) [ 0 ] ;
StructuredBlock pred = getPredecessor ( ret ) ;
if ( ! ( pred instanceof InstructionBlock ) )
return ;
Expression instr = ( ( InstructionBlock ) pred ) . getInstruction ( ) ;
@ -203,15 +199,13 @@ public class TransformExceptionHandlers {
}
/ * *
* Remove the JSR ' s jumping to the specified subRoutine . It
* is checked if the next block is a leaving instruction , and
* otherwise the JsrBlock is not removed ( to give the user a
* hint that something went wrong ) . This will also remove the
* local javac generates for returns .
* Remove the wrongly placed JSRs jumping to the specified
* subRoutine . The right JSRs are already removed , but we have to
* replace the wrong ones with a warning .
* @param tryFlow the FlowBLock of the try block .
* @param subRoutine the FlowBlock of the sub routine .
* /
private void removeJSR ( FlowBlock tryFlow , StructuredBlock catchBlock ,
private void removeBad JSR ( FlowBlock tryFlow , StructuredBlock catchBlock ,
FlowBlock subRoutine ) {
Jump nextJump ;
for ( Jump jumps = tryFlow . getJumps ( subRoutine ) ;
@ -225,64 +219,96 @@ public class TransformExceptionHandlers {
/* This is the mandatory jsr in the catch block */
continue ;
}
if ( prev . outer . getNextFlowBlock ( ) ! = null ) {
/* The jsr is directly before a jump, okay. */
/ * We have a JSR to the subroutine , which is badly placed .
* We complain here .
* /
DescriptionBlock msg
= new DescriptionBlock ( "ERROR: JSR FINALLY BLOCK!" ) ;
tryFlow . removeSuccessor ( jumps ) ;
prev . removeJump ( ) ;
prev . outer . removeBlock ( ) ;
continue ;
}
if ( prev . outer . outer instanceof SequentialBlock
& & prev . outer . outer . getSubBlocks ( ) [ 0 ] = = prev . outer ) {
SequentialBlock seq = ( SequentialBlock ) prev . outer . outer ;
if ( seq . subBlocks [ 1 ] instanceof JsrBlock
| | ( seq . subBlocks [ 1 ] instanceof SequentialBlock
& & seq . subBlocks [ 1 ] . getSubBlocks ( ) [ 0 ]
instanceof JsrBlock ) ) {
/* The jsr is followed by a jsr, okay. */
msg . replace ( prev . outer ) ;
} else {
/ * We have a jump to the subroutine , that is wrong .
* We complain here .
* /
DescriptionBlock msg
= new DescriptionBlock ( "ERROR: GOTO FINALLY BLOCK!" ) ;
tryFlow . removeSuccessor ( jumps ) ;
prev . removeJump ( ) ;
prev . outer . removeBlock ( ) ;
continue ;
prev . appendBlock ( msg ) ;
}
}
}
if ( seq . subBlocks [ 1 ] instanceof ReturnBlock
& & ! ( seq . subBlocks [ 1 ] instanceof ThrowBlock ) ) {
/* The jsr is followed by a return, okay. */
tryFlow . removeSuccessor ( jumps ) ;
prev . removeJump ( ) ;
ReturnBlock ret = ( ReturnBlock ) seq . subBlocks [ 1 ] ;
prev . outer . removeBlock ( ) ;
private static StructuredBlock getPredecessor ( StructuredBlock stmt )
{
if ( stmt . outer instanceof SequentialBlock ) {
SequentialBlock seq = ( SequentialBlock ) stmt . outer ;
if ( seq . subBlocks [ 1 ] = = stmt )
return seq . subBlocks [ 0 ] ;
else if ( seq . outer instanceof SequentialBlock )
return seq . outer . getSubBlocks ( ) [ 0 ] ;
}
return null ;
}
removeReturnLocal ( ret ) ;
continue ;
/ * *
* Gets the slot of the monitorexit instruction instr in the
* stmt , or - 1 if stmt isn ' t a InstructionBlock with a
* monitorexit instruction .
* @param stmt the stmt , may be null .
* /
private static int getMonitorExitSlot ( StructuredBlock stmt ) {
if ( stmt instanceof InstructionBlock ) {
Expression instr = ( ( InstructionBlock ) stmt ) . getInstruction ( ) ;
if ( instr instanceof MonitorExitOperator ) {
MonitorExitOperator monExit = ( MonitorExitOperator ) instr ;
if ( monExit . getFreeOperandCount ( ) = = 0
& & ( monExit . getSubExpressions ( ) [ 0 ]
instanceof LocalLoadOperator ) )
return ( ( LocalLoadOperator ) monExit . getSubExpressions ( ) [ 0 ] )
. getLocalInfo ( ) . getSlot ( ) ;
}
}
return - 1 ;
}
/ * Now we have a jump to the subroutine , that is wrong .
* We complain here .
* /
DescriptionBlock msg
= new DescriptionBlock ( "ERROR: GOTO FINALLY BLOCK!" ) ;
tryFlow . removeSuccessor ( jumps ) ;
prev . removeJump ( ) ;
prev . appendBlock ( msg ) ;
private boolean isMonitorExitSubRoutine ( FlowBlock subRoutine ,
LocalInfo local ) {
if ( transformSubRoutine ( subRoutine . block )
& & getMonitorExitSlot ( subRoutine . block ) = = local . getSlot ( ) )
return true ;
return false ;
}
private static StructuredBlock skipFinExitChain ( StructuredBlock block )
{
StructuredBlock pred , result ;
if ( block instanceof ReturnBlock )
pred = getPredecessor ( block ) ;
else
pred = block ;
result = null ;
while ( pred instanceof JsrBlock
| | getMonitorExitSlot ( pred ) > = 0 ) {
result = pred ;
pred = getPredecessor ( pred ) ;
}
return result ;
}
public void checkAndRemoveJSR ( FlowBlock tryFlow ,
private void checkAndRemoveJSR ( FlowBlock tryFlow ,
StructuredBlock catchBlock ,
FlowBlock subRoutine ,
int startOutExit , int endOutExit ) {
boolean foundSub = false ;
Iterator iter = tryFlow . getSuccessors ( ) . iterator ( ) ;
dest_loop :
while ( iter . hasNext ( ) ) {
FlowBlock dest = ( FlowBlock ) iter . next ( ) ;
if ( dest = = subRoutine ) {
foundSub = true ;
if ( dest = = subRoutine )
continue dest_loop ;
}
boolean isFirstJump = true ;
for ( Jump jumps = tryFlow . getJumps ( dest ) ;
@ -295,41 +321,34 @@ public class TransformExceptionHandlers {
* /
continue ;
}
if ( prev instanceof JsrBlock ) {
/ * The jump is directly preceeded by a jsr .
* Everything okay .
* /
continue ;
}
if ( prev instanceof EmptyBlock
& & prev . outer instanceof JsrBlock ) {
/ * If jump is a jsr check the outer
* block instead .
* /
prev = prev . outer ;
}
if ( ( prev instanceof ReturnBlock
| | prev instanceof JsrBlock )
& & prev . outer instanceof SequentialBlock ) {
SequentialBlock seq = ( SequentialBlock ) prev . outer ;
if ( seq . subBlocks [ 1 ] = = prev
& & ( seq . subBlocks [ 0 ] instanceof JsrBlock ) ) {
/ * The jump is preceeded by another jsr , okay .
/ * This jump is really a jsr , since it doesn ' t
* leave the block forever , we can ignore it .
* /
continue ;
}
if ( seq . subBlocks [ 0 ] = = prev
& & seq . outer instanceof SequentialBlock
& & ( seq . outer . getSubBlocks ( ) [ 0 ] instanceof JsrBlock ) ) {
/ * Again the jump is preceeded by another jsr , okay .
StructuredBlock pred = skipFinExitChain ( prev ) ;
if ( pred instanceof JsrBlock ) {
StructuredBlock jsrInner = ( ( JsrBlock ) pred ) . innerBlock ;
if ( jsrInner instanceof EmptyBlock
& & jsrInner . jump ! = null
& & jsrInner . jump . destination = = subRoutine ) {
/ * The jump is preceeded by the right jsr . Remove
* the jsr .
* /
tryFlow . removeSuccessor ( jsrInner . jump ) ;
jsrInner . removeJump ( ) ;
pred . removeBlock ( ) ;
if ( prev instanceof ReturnBlock )
removeReturnLocal ( ( ReturnBlock ) prev ) ;
continue ;
}
}
if ( isFirstJump ) {
/ * Now we have a jump that is not preceded by the
if ( pred = = null & & isFirstJump ) {
/ * Now we have a jump that is not preceded by any
* jsr . There ' s a last chance : the jump jumps
* directly to a correct jsr instruction , which
* lies outside the try / catch block .
@ -360,42 +379,18 @@ public class TransformExceptionHandlers {
* /
DescriptionBlock msg
= new DescriptionBlock ( "ERROR: NO JSR TO FINALLY" ) ;
if ( pred ! = null )
pred . prependBlock ( msg ) ;
else {
prev . appendBlock ( msg ) ;
msg . moveJump ( jumps ) ;
msg . moveJump ( prev . jump ) ;
}
}
if ( foundSub )
removeJSR ( tryFlow , catchBlock , subRoutine ) ;
}
static boolean isMonitorExit ( Expression instr , LocalInfo local ) {
if ( instr instanceof MonitorExitOperator ) {
MonitorExitOperator monExit = ( MonitorExitOperator ) instr ;
if ( monExit . getFreeOperandCount ( ) = = 0
& & monExit . getSubExpressions ( ) [ 0 ] instanceof LocalLoadOperator
& & ( ( ( LocalLoadOperator ) monExit . getSubExpressions ( ) [ 0 ] )
. getLocalInfo ( ) . getSlot ( ) = = local . getSlot ( ) ) ) {
return true ;
}
}
return false ;
}
boolean isMonitorExitSubRoutine ( FlowBlock subRoutine , LocalInfo local ) {
if ( transformSubRoutine ( subRoutine . block ) ) {
if ( subRoutine . block instanceof InstructionBlock ) {
Expression instr =
( ( InstructionBlock ) subRoutine . block )
. getInstruction ( ) ;
if ( isMonitorExit ( instr , local ) ) {
return true ;
}
}
}
return false ;
removeBadJSR ( tryFlow , catchBlock , subRoutine ) ;
}
public void checkAndRemoveMonitorExit ( FlowBlock tryFlow ,
private void checkAndRemoveMonitorExit ( FlowBlock tryFlow ,
StructuredBlock catchBlock ,
LocalInfo local ,
int start , int end ) {
@ -409,91 +404,57 @@ public class TransformExceptionHandlers {
jumps ! = null ; jumps = jumps . next , isFirstJump = false ) {
StructuredBlock prev = jumps . prev ;
if ( prev instanceof ThrowBlock ) {
/ * The jump is a throw . We have a catch all block
* that will do the monitorexit .
* /
continue ;
}
if ( prev instanceof JsrBlock ) {
/ * The jump is directly preceeded by a jsr .
/ * The jump is a throw . We have a catch - all block
* that will do the finally .
* /
continue ;
}
if ( prev instanceof EmptyBlock
& & prev . outer instanceof JsrBlock ) {
/ * If jump is a jsr ch eck the out er
* block instead .
/ * This jump is really a jsr , sin ce i t d oesn ' t
* leave the block forever , we can ignore it .
* /
prev = prev . outer ;
continue ;
}
StructuredBlock pred = skipFinExitChain ( prev ) ;
if ( pred instanceof JsrBlock ) {
StructuredBlock jsrInner = ( ( JsrBlock ) pred ) . innerBlock ;
if ( jsrInner instanceof EmptyBlock
& & jsrInner . jump ! = null ) {
FlowBlock dest = jsrInner . jump . destination ;
/ * If the block is a jsr or a return block , check if
* it is preceeded by another jsr .
* /
if ( ( prev instanceof JsrBlock
| | prev instanceof ReturnBlock )
& & prev . outer instanceof SequentialBlock ) {
SequentialBlock seq = ( SequentialBlock ) prev . outer ;
StructuredBlock pred = null ;
if ( seq . subBlocks [ 1 ] = = prev )
pred = seq . subBlocks [ 0 ] ;
else if ( seq . outer instanceof SequentialBlock )
pred = seq . outer . getSubBlocks ( ) [ 0 ] ;
if ( subRoutine = = null
& & dest . getAddr ( ) > = start
& & dest . getNextAddr ( ) < = end ) {
dest . analyze ( start , end ) ;
if ( isMonitorExitSubRoutine ( dest , local ) )
subRoutine = dest ;
}
if ( pred ! = null ) {
if ( pred instanceof JsrBlock )
/ * The jump is preceeded by another jsr , okay .
if ( dest = = subRoutine ) {
/ * The jump is preceeded by the right jsr . Remove
* the jsr .
* /
continue ;
if ( pred instanceof InstructionBlock ) {
Expression instr =
( ( InstructionBlock ) pred ) . getInstruction ( ) ;
if ( isMonitorExit ( instr , local ) ) {
tryFlow . removeSuccessor ( jsrInner . jump ) ;
jsrInner . removeJump ( ) ;
pred . removeBlock ( ) ;
if ( prev instanceof ReturnBlock )
removeReturnLocal ( ( ReturnBlock ) prev ) ;
continue ;
}
}
}
}
if ( prev instanceof InstructionBlock
& & isMonitorExit ( ( ( InstructionBlock ) prev ) . instr , local ) ) {
/ * This is probably the last expression in the
* synchronized block , and has the right monitor exit
* attached . Remove this block .
} else if ( getMonitorExitSlot ( pred ) = = local . getSlot ( ) ) {
/ * The jump is preceeded by the right monitor
* exit instruction .
* /
prev . removeBlock ( ) ;
pred . removeBlock ( ) ;
if ( prev instanceof ReturnBlock )
removeReturnLocal ( ( ReturnBlock ) prev ) ;
continue ;
}
if ( isFirstJump ) {
/ * This is the first jump to that destination .
* Check if the destination does the monitorExit
* /
/ * The block is a jsr that is not preceeded by
* another jsr . This must be the monitorexit
* subroutine .
* /
if ( prev instanceof JsrBlock ) {
if ( subRoutine = = null
& & successor . getAddr ( ) > = start
& & successor . getNextAddr ( ) < = end ) {
successor . analyze ( start , end ) ;
if ( isMonitorExitSubRoutine ( successor , local ) )
subRoutine = successor ;
}
if ( subRoutine = = successor )
continue dest_loop ;
}
if ( pred = = null & & isFirstJump ) {
/ * Now we have a jump that is not preceded by a
* monitorexit . There ' s a last chance : the jump
* jumps directly to the correct monitorexit
@ -521,20 +482,18 @@ public class TransformExceptionHandlers {
}
if ( subRoutine = = dest ) {
successor . removeSuccessor ( jsrInner . jump ) ;
jsrInner . removeJump ( ) ;
sb . removeBlock ( ) ;
continue dest_loop ;
}
}
if ( sb instanceof InstructionBlock ) {
Expression instr = ( ( InstructionBlock ) sb )
. getInstruction ( ) ;
if ( isMonitorExit ( instr , local ) ) {
if ( getMonitorExitSlot ( sb ) = = local . getSlot ( ) ) {
sb . removeBlock ( ) ;
continue dest_loop ;
}
}
}
}
/ * Complain !
* /
@ -546,7 +505,7 @@ public class TransformExceptionHandlers {
}
if ( subRoutine ! = null ) {
removeJSR ( tryFlow , catchBlock , subRoutine ) ;
removeBad JSR ( tryFlow , catchBlock , subRoutine ) ;
tryFlow . mergeAddr ( subRoutine ) ;
}
}