001    package railo.transformer.bytecode.visitor;
002    
003    import org.objectweb.asm.Label;
004    import org.objectweb.asm.Opcodes;
005    import org.objectweb.asm.commons.GeneratorAdapter;
006    
007    import railo.transformer.bytecode.BytecodeContext;
008    import railo.transformer.bytecode.BytecodeException;
009    import railo.transformer.bytecode.statement.FlowControlFinal;
010    import railo.transformer.bytecode.util.ASMUtil;
011    import railo.transformer.bytecode.util.Types;
012    
013    public class TryFinallyVisitor implements Opcodes {
014    
015            private Label beforeTry;
016            private Label afterTry;
017            private Label beforeFinally;
018            private Label afterFinally;
019            private int lThrow;
020            private OnFinally onFinally;
021            private FlowControlFinal fcf;
022    
023    
024    
025            public TryFinallyVisitor(OnFinally onFinally, FlowControlFinal fcf) {
026                    this.onFinally=onFinally;
027                    this.fcf=fcf;
028            }
029    
030            public void visitTryBegin(BytecodeContext bc) {
031                    GeneratorAdapter ga = bc.getAdapter();
032                    bc.pushOnFinally(onFinally);
033                    beforeTry = new Label();
034                    afterTry = new Label();
035                    beforeFinally = new Label();
036                    afterFinally = new Label();
037                    
038                    ga.visitLabel(beforeTry);
039            }
040    
041            public void visitTryEnd(BytecodeContext bc) throws BytecodeException {
042                    GeneratorAdapter ga = bc.getAdapter();
043                    bc.popOnFinally();
044                    ga.visitJumpInsn(GOTO, beforeFinally);
045                    
046                    ga.visitLabel(afterTry);
047                    lThrow = ga.newLocal(Types.THROWABLE);
048                    ga.storeLocal(lThrow);
049                    
050                    onFinally.writeOut(bc);
051                    
052                    ga.loadLocal(lThrow);
053                    ga.visitInsn(ATHROW);
054                    
055                    ga.visitLabel(beforeFinally);
056                    
057                    onFinally.writeOut(bc);
058                    if(fcf!=null && fcf.getAfterFinalGOTOLabel()!=null) {
059                            Label _end=new Label();
060                            ga.visitJumpInsn(Opcodes.GOTO, _end); // ignore when coming not from break/continue
061                                    ASMUtil.visitLabel(ga,fcf.getFinalEntryLabel());
062                                    onFinally.writeOut(bc);
063                                    ga.visitJumpInsn(Opcodes.GOTO, fcf.getAfterFinalGOTOLabel());
064                            ga.visitLabel(_end);
065                    }
066                    
067                    
068                    
069                    ga.visitLabel(afterFinally);
070                    
071                    ga.visitTryCatchBlock(beforeTry, afterTry, afterTry, null);
072            }
073    }