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
 * <http://www.apache.org/>.
 */
import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;

Abstract super class for instructions dealing with local variables.
Author:M. Dahm
Version:$Id: InstructionLV.java,v 1.5 2009/10/05 17:35:36 aclement Exp $
/** * 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> */
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' ">"
/** * 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; }
Returns:local variable index referred by this instruction.
/** * @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; } }