/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2006-2008, Martin Schoeberl (martin@jopdesign.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jopdesign.build; import com.jopdesign.common.ClassInfo; import com.jopdesign.common.MethodCode; import com.jopdesign.common.MethodInfo; import com.jopdesign.common.graphutils.ClassVisitor; import org.apache.bcel.generic.BIPUSH; import org.apache.bcel.generic.IADD; import org.apache.bcel.generic.ICONST; import org.apache.bcel.generic.IINC; import org.apache.bcel.generic.ILOAD; import org.apache.bcel.generic.ISTORE; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.SIPUSH; import org.apache.bcel.util.InstructionFinder; import java.util.Iterator; /** * @author Martin * <p/> * replaces IINC by ILOAD, push the constant, IADD, and ISTORE * <p/> * avoids issues with the Java 1.5 compiler (produces WIDE IINC) and * generates faster code on JOP. */ public class ReplaceIinc implements ClassVisitor { public ReplaceIinc() { } @Override public boolean visitClass(ClassInfo classInfo) { for (MethodInfo method : classInfo.getMethods()) { if (!(method.isAbstract() || method.isNative())) { replace(method); } } return true; } @Override public void finishClass(ClassInfo classInfo) { } private void replace(MethodInfo method) { MethodCode mc = method.getCode(); InstructionList il = mc.getInstructionList(); InstructionFinder f = new InstructionFinder(il); for (Iterator i = f.search("IINC"); i.hasNext();) { InstructionHandle[] match = (InstructionHandle[]) i.next(); InstructionHandle ih = match[0]; IINC ii = (IINC) ih.getInstruction(); int idx = ii.getIndex(); int inc = ii.getIncrement(); // IINC rep = new IINC(idx, inc); ih.setInstruction(new ILOAD(idx)); if (inc >= -1 && inc <= 5) { ih = il.append(ih, new ICONST(inc)); } else if (inc >= -128 && inc < 127) { ih = il.append(ih, new BIPUSH((byte) inc)); } else if (inc >= -32768 && inc < 32767) { ih = il.append(ih, new SIPUSH((short) inc)); } else { System.out.println("IINC constant too big"); System.exit(-1); } ih = il.append(ih, new IADD()); ih = il.append(ih, new ISTORE(idx)); } method.compile(); } }