package org.aspectj.apache.bcel.generic; /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Apache BCEL" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * "Apache BCEL", nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ import java.io.DataOutputStream; import java.io.IOException; import org.aspectj.apache.bcel.Constants; /** * Abstract super class for instructions dealing with local variables. * * @version $Id: InstructionLV.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm */ public class InstructionLV extends Instruction { protected int lvar = -1; public InstructionLV(short opcode, int lvar) { super(opcode); this.lvar = lvar; } public InstructionLV(short opcode) { super(opcode); } public void dump(DataOutputStream out) throws IOException { if (lvar == -1) { out.writeByte(opcode); } else { if (lvar < 4) { if (opcode == ALOAD) { out.writeByte(ALOAD_0 + lvar); } else if (opcode == ASTORE) { out.writeByte(ASTORE_0 + lvar); } else if (opcode == ILOAD) { out.writeByte(ILOAD_0 + lvar); } else if (opcode == ISTORE) { out.writeByte(ISTORE_0 + lvar); } else if (opcode == DLOAD) { out.writeByte(DLOAD_0 + lvar); } else if (opcode == DSTORE) { out.writeByte(DSTORE_0 + lvar); } else if (opcode == FLOAD) { out.writeByte(FLOAD_0 + lvar); } else if (opcode == FSTORE) { out.writeByte(FSTORE_0 + lvar); } else if (opcode == LLOAD) { out.writeByte(LLOAD_0 + lvar); } else if (opcode == LSTORE) { out.writeByte(LSTORE_0 + lvar); } else { if (wide()) { out.writeByte(Constants.WIDE); } out.writeByte(opcode); if (wide()) { out.writeShort(lvar); } else { out.writeByte(lvar); } } } else { if (wide()) { out.writeByte(Constants.WIDE); } out.writeByte(opcode); if (wide()) { out.writeShort(lvar); } else { out.writeByte(lvar); } } } } /** * Long output format: * * 'name of opcode' "[" 'opcode number' "]" "(" 'length of instruction' ")" "<" 'local variable index' ">" */ public String toString(boolean verbose) { if (opcode >= Constants.ILOAD_0 && opcode <= Constants.ALOAD_3 || opcode >= Constants.ISTORE_0 && opcode <= Constants.ASTORE_3) { return super.toString(verbose); } else { return super.toString(verbose) + (lvar != -1 && lvar < 4 ? "_" : " ") + lvar; } } public boolean isALOAD() { return opcode == ALOAD || opcode >= ALOAD_0 && opcode <= ALOAD_3; } public boolean isASTORE() { return opcode == ASTORE || opcode >= ASTORE_0 && opcode <= ASTORE_3; } public int getBaseOpcode() { if (opcode >= ILOAD && opcode <= ALOAD || opcode >= ISTORE && opcode <= ASTORE) { // not an optimized instruction return opcode; } if (opcode >= Constants.ILOAD_0 && opcode <= Constants.ALOAD_3) { int ret = opcode - ILOAD_0; ret = ret - ret % 4; ret = ret / 4; return ret + ILOAD; } int ret = opcode - ISTORE_0; ret = ret - ret % 4; ret = ret / 4; return ret + ISTORE; } /** * @return local variable index referred by this instruction. */ // optimize! public final int getIndex() { if (lvar != -1) { return lvar; } if (opcode >= Constants.ILOAD_0 && opcode <= Constants.ALOAD_3) { return (opcode - Constants.ILOAD_0) % 4; } else if (opcode >= Constants.ISTORE_0 && opcode <= Constants.ASTORE_3) { return (opcode - Constants.ISTORE_0) % 4; } return -1; } public void setIndex(int i) { // Switching the index for a load/store without a current index specified (ie. an aload_1 or istore_2) // means we need to should adjust to a normal aload/istore opcode if (getIndex() != i) { if (opcode >= Constants.ILOAD_0 && opcode <= Constants.ALOAD_3) { opcode = (short) (ILOAD + (opcode - ILOAD_0) / 4); } else if (opcode >= Constants.ISTORE_0 && opcode <= Constants.ASTORE_3) { opcode = (short) (ISTORE + (opcode - ISTORE_0) / 4); } this.lvar = i; } } public boolean canSetIndex() { return true; } public InstructionLV setIndexAndCopyIfNecessary(int newIndex) { if (canSetIndex()) { setIndex(newIndex); return this; } else { if (getIndex() == newIndex) { return this; } InstructionLV newInstruction = null; int baseOpCode = getBaseOpcode(); if (newIndex < 4) { if (isStoreInstruction()) { newInstruction = (InstructionLV) InstructionConstants.INSTRUCTIONS[(baseOpCode - Constants.ISTORE) * 4 + Constants.ISTORE_0 + newIndex]; } else { newInstruction = (InstructionLV) InstructionConstants.INSTRUCTIONS[(baseOpCode - Constants.ILOAD) * 4 + Constants.ILOAD_0 + newIndex]; } } else { newInstruction = new InstructionLV((short) baseOpCode, newIndex); } // if (getBaseOpcode()!=newInstruction.getBaseOpcode() || newInstruction.getIndex()!=newIndex) { // throw new // RuntimeException("New Instruction created does not appear to be valid: originalBaseOpcode="+getBaseOpcode()+ // " newBaseOpcode="+newInstruction.getBaseOpcode()); // } return newInstruction; } } public int getLength() { int size = Constants.iLen[opcode]; if (lvar == -1) { return size; } else { if (lvar < 4) { if (opcode == ALOAD || opcode == ASTORE) { return 1; } else if (opcode == ILOAD || opcode == ISTORE) { return 1; } else if (opcode == DLOAD || opcode == DSTORE) { return 1; } else if (opcode == FLOAD || opcode == FSTORE) { return 1; } else if (opcode == LLOAD || opcode == LSTORE) { return 1; } else { if (wide()) { return size + 2; } return size; } } else { if (wide()) { return size + 2; } return size; } } } private final boolean wide() { return lvar > Constants.MAX_BYTE; } public boolean equals(Object other) { if (!(other instanceof InstructionLV)) { return false; } InstructionLV o = (InstructionLV) other; return o.opcode == opcode && o.lvar == lvar; } public int hashCode() { return opcode * 37 + lvar; } }