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.Position; 023import lucee.transformer.bytecode.util.ExpressionUtil; 024import lucee.transformer.bytecode.util.Types; 025 026import org.objectweb.asm.Label; 027import org.objectweb.asm.Opcodes; 028import org.objectweb.asm.commons.GeneratorAdapter; 029 030public final class ForIntVisitor implements Opcodes, LoopVisitor { 031 032 private Label beforeInit=new Label(); 033 private Label beforeExpr=new Label(),afterExpr=new Label(); 034 private Label beforeBody=new Label(),afterBody=new Label(); 035 private Label beforeUpdate=new Label(),afterUpdate=new Label(); 036 private int i; 037 038 public int visitBeforeExpression(GeneratorAdapter adapter, int start, int step, boolean isLocal) { 039 // init 040 adapter.visitLabel(beforeInit); 041 forInit(adapter, start, isLocal); 042 adapter.goTo(beforeExpr); 043 044 // update 045 adapter.visitLabel(beforeUpdate); 046 forUpdate(adapter, step, isLocal); 047 048 // expression 049 adapter.visitLabel(beforeExpr); 050 return i; 051 } 052 053 public void visitAfterExpressionBeginBody(GeneratorAdapter adapter) { 054 adapter.ifZCmp(Opcodes.IFEQ, afterBody); 055 } 056 057 public void visitEndBody(BytecodeContext bc,Position line) { 058 bc.getAdapter().goTo(beforeUpdate); 059 ExpressionUtil.visitLine(bc, line); 060 bc.getAdapter().visitLabel(afterBody); 061 //adapter.visitLocalVariable("i", "I", null, beforeInit, afterBody, i); 062 } 063 064 065 private void forInit(GeneratorAdapter adapter, int start, boolean isLocal) { 066 i=adapter.newLocal(Types.INT_VALUE); 067 if(isLocal)adapter.loadLocal(start,Types.INT_VALUE); 068 else adapter.push(start); 069 adapter.visitVarInsn(ISTORE, i); 070 } 071 072 private void forUpdate(GeneratorAdapter adapter, int step, boolean isLocal) { 073 if(isLocal) { 074 adapter.visitVarInsn(ILOAD, i); 075 adapter.loadLocal(step); 076 adapter.visitInsn(IADD); 077 adapter.visitVarInsn(ISTORE, i); 078 } 079 else adapter.visitIincInsn(i, step); 080 } 081 082 /** 083 * 084 * @see lucee.transformer.bytecode.visitor.LoopVisitor#visitContinue(org.objectweb.asm.commons.GeneratorAdapter) 085 */ 086 public void visitContinue(BytecodeContext bc) { 087 bc.getAdapter().visitJumpInsn(Opcodes.GOTO, beforeUpdate); 088 } 089 090 /** 091 * 092 * @see lucee.transformer.bytecode.visitor.LoopVisitor#visitBreak(org.objectweb.asm.commons.GeneratorAdapter) 093 */ 094 public void visitBreak(BytecodeContext bc) { 095 bc.getAdapter().visitJumpInsn(Opcodes.GOTO, afterBody); 096 } 097 098 /** 099 * 100 * @see lucee.transformer.bytecode.visitor.LoopVisitor#getContinueLabel() 101 */ 102 public Label getContinueLabel() { 103 return beforeUpdate; 104 } 105 106 /** 107 * 108 * @see lucee.transformer.bytecode.visitor.LoopVisitor#getBreakLabel() 109 */ 110 public Label getBreakLabel() { 111 return afterBody; 112 } 113 114}