001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.bytecode.visitor; 020 021import lucee.transformer.bytecode.BytecodeContext; 022import lucee.transformer.bytecode.BytecodeException; 023import lucee.transformer.bytecode.statement.FlowControlFinal; 024import lucee.transformer.bytecode.util.ASMUtil; 025import lucee.transformer.bytecode.util.Types; 026 027import org.objectweb.asm.Label; 028import org.objectweb.asm.Opcodes; 029import org.objectweb.asm.commons.GeneratorAdapter; 030 031public class TryFinallyVisitor implements Opcodes { 032 033 private Label beforeTry; 034 private Label afterTry; 035 private Label beforeFinally; 036 private Label afterFinally; 037 private int lThrow; 038 private OnFinally onFinally; 039 private FlowControlFinal fcf; 040 041 042 043 public TryFinallyVisitor(OnFinally onFinally, FlowControlFinal fcf) { 044 this.onFinally=onFinally; 045 this.fcf=fcf; 046 } 047 048 public void visitTryBegin(BytecodeContext bc) { 049 GeneratorAdapter ga = bc.getAdapter(); 050 bc.pushOnFinally(onFinally); 051 beforeTry = new Label(); 052 afterTry = new Label(); 053 beforeFinally = new Label(); 054 afterFinally = new Label(); 055 056 ga.visitLabel(beforeTry); 057 } 058 059 public void visitTryEnd(BytecodeContext bc) throws BytecodeException { 060 GeneratorAdapter ga = bc.getAdapter(); 061 bc.popOnFinally(); 062 ga.visitJumpInsn(GOTO, beforeFinally); 063 064 ga.visitLabel(afterTry); 065 lThrow = ga.newLocal(Types.THROWABLE); 066 ga.storeLocal(lThrow); 067 068 onFinally.writeOut(bc); 069 070 ga.loadLocal(lThrow); 071 ga.visitInsn(ATHROW); 072 073 ga.visitLabel(beforeFinally); 074 075 onFinally.writeOut(bc); 076 if(fcf!=null && fcf.getAfterFinalGOTOLabel()!=null) { 077 Label _end=new Label(); 078 ga.visitJumpInsn(Opcodes.GOTO, _end); // ignore when coming not from break/continue 079 ASMUtil.visitLabel(ga,fcf.getFinalEntryLabel()); 080 onFinally.writeOut(bc); 081 ga.visitJumpInsn(Opcodes.GOTO, fcf.getAfterFinalGOTOLabel()); 082 ga.visitLabel(_end); 083 } 084 085 086 087 ga.visitLabel(afterFinally); 088 089 ga.visitTryCatchBlock(beforeTry, afterTry, afterTry, null); 090 } 091}