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.Type;
030import org.objectweb.asm.commons.GeneratorAdapter;
031
032public class TryCatchFinallyVisitor implements Opcodes {
033        private OnFinally onFinally;
034        private Label beginTry;
035        private Label endTry;
036        private Label endTry2;
037        private Label l3;
038        private Label l4;
039        private Label l5;
040        private Label l6;
041        private Type type=Types.THROWABLE;
042        private FlowControlFinal fcf;
043
044
045        public TryCatchFinallyVisitor(OnFinally onFinally, FlowControlFinal fcf){
046                this.onFinally=onFinally;
047                this.fcf=fcf;
048        }
049
050        public void visitTryBegin(BytecodeContext bc) {
051                GeneratorAdapter ga = bc.getAdapter();
052                beginTry = new Label();
053                endTry = new Label();
054                endTry2 = new Label();
055                l3 = new Label();
056                l4 = new Label();
057                bc.pushOnFinally(onFinally);
058                ga.visitLabel(beginTry);
059        }
060
061        public int visitTryEndCatchBeging(BytecodeContext bc) {
062                GeneratorAdapter ga = bc.getAdapter();
063                
064                ga.visitTryCatchBlock(beginTry, endTry, endTry2, type.getInternalName());
065                ga.visitLabel(endTry);
066                l5 = new Label();
067                ga.visitJumpInsn(GOTO, l5);
068                ga.visitLabel(endTry2);
069                int lThrow = ga.newLocal(type);
070                ga.storeLocal(lThrow);
071                //mv.visitVarInsn(ASTORE, 1);
072                l6 = new Label();
073                ga.visitLabel(l6);
074                return lThrow;
075        }
076        
077        public void visitCatchEnd(BytecodeContext bc) throws BytecodeException {
078                Label end = new Label();
079                GeneratorAdapter ga = bc.getAdapter();
080                bc.popOnFinally();
081                ga.visitLabel(l3);
082                ga.visitJumpInsn(GOTO, l5);
083                ga.visitLabel(l4);
084                int lThrow = ga.newLocal(Types.THROWABLE);
085                ga.storeLocal(lThrow);
086                //mv.visitVarInsn(ASTORE, 2);
087                Label l8 = new Label();
088                ga.visitLabel(l8);
089
090                onFinally.writeOut(bc);
091                
092                ga.loadLocal(lThrow);
093                ga.visitInsn(ATHROW);
094                ga.visitLabel(l5);
095
096                onFinally.writeOut(bc);
097                if(fcf!=null && fcf.getAfterFinalGOTOLabel()!=null) {
098                        Label _end=new Label();
099                        ga.visitJumpInsn(Opcodes.GOTO, _end); // ignore when coming not from break/continue
100                                ASMUtil.visitLabel(ga,fcf.getFinalEntryLabel());
101                                onFinally.writeOut(bc);
102                                ga.visitJumpInsn(Opcodes.GOTO, fcf.getAfterFinalGOTOLabel());
103                        ga.visitLabel(_end);
104                }
105                
106                                
107                
108                
109
110                ga.visitLabel(end);
111                ga.visitTryCatchBlock(beginTry, l3, l4, null);
112                        
113        }
114}