private Node tryOptimizeSwitch ( Node n ) { checkState ( n . isSwitch ( ) , n ) ; Node defaultCase = tryOptimizeDefaultCase ( n ) ; // Generally, it is unsafe to remove other cases when the default case is not the last one. if ( defaultCase == null || n . getLastChild ( ) . isDefaultCase ( ) ) { Node cond = n . getFirstChild ( ) ; Node prev = null ; Node next = null ; Node cur ; for ( cur = cond . getNext ( ) ; cur != null ; cur = next ) { next = cur . getNext ( ) ; if ( ! mayHaveSideEffects ( cur . getFirstChild ( ) ) && isUselessCase ( cur , prev , defaultCase ) ) { removeCase ( n , cur ) ; } else { prev = cur ; } } // Optimize switches with constant condition if ( NodeUtil . isLiteralValue ( cond , false ) ) { Node caseLabel ; TernaryValue caseMatches = TernaryValue . TRUE ; // Remove cases until you find one that may match for ( cur = cond . getNext ( ) ; cur != null ; cur = next ) { next = cur . getNext ( ) ; caseLabel = cur . getFirstChild ( ) ; caseMatches = PeepholeFoldConstants . evaluateComparison ( this , Token . SHEQ , cond , caseLabel ) ; if ( caseMatches == TernaryValue . TRUE ) { break ; } else if ( caseMatches == TernaryValue . UNKNOWN ) { break ; } else { removeCase ( n , cur ) ; } } if ( cur != null && caseMatches == TernaryValue . TRUE ) { // Skip cases until you find one whose last stm is a removable break Node matchingCase = cur ; Node matchingCaseBlock = matchingCase . getLastChild ( ) ; while ( cur != null ) { Node block = cur . getLastChild ( ) ; Node lastStm = block . getLastChild ( ) ; boolean isLastStmRemovableBreak = false ; if ( lastStm != null && isExit ( lastStm ) ) { removeIfUnnamedBreak ( lastStm ) ; isLastStmRemovableBreak = true ; } next = cur . getNext ( ) ; // Remove the fallthrough case labels if ( cur != matchingCase ) { while ( block . hasChildren ( ) ) { matchingCaseBlock . addChildToBack ( block . getFirstChild ( ) . detach ( ) ) ; } reportChangeToEnclosingScope ( cur ) ; cur . detach ( ) ; } cur = next ; if ( isLastStmRemovableBreak ) { break ; } } // Remove any remaining cases for ( ; cur != null ; cur = next ) { next = cur . getNext ( ) ; removeCase ( n , cur ) ; } // If there is one case left, we may be able to fold it cur = cond . getNext ( ) ; if ( cur != null && cur . getNext ( ) == null ) { return tryRemoveSwitchWithSingleCase ( n , false ) ; } } } } return tryRemoveSwitch ( n ) ; }
Remove useless switches and cases .