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 }