WALA/com.ibm.wala.shrike/src/com/ibm/wala/shrikeBT/Instruction.java

133 lines
4.6 KiB
Java

/*******************************************************************************
* Copyright (c) 2002,2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.shrikeBT;
/**
* Instructions are immutable objects. It is always legal to take a reference to an instruction and use it in any other context. You
* never need to copy instructions. It is often a good idea to keep references to frequently used instructions cached in static
* fields.
*
* To generate an Instruction, locate the class for the instruction you want to generate, and invoke the appropriate "make" static
* method on that class. The Util class has convenience methods for creating some of the more complex instructions using reflection
* to fill in some of the needed information (e.g., makeGet, makePut, makeInvoke).
*
* We simplify the bytecode instruction set a bit using some preprocessing and postprocessing:
*
* There is no 'iinc' instruction. 'iinc' instructions are expanded to 'iload; bipush; iadd; istore' during decoding and reassembled
* during compilation.
*
* There are no 'jsr' or 'ret' instructions. Bytecode subroutines are expanded inline during decoding.
*
* There are no 'ifeq', 'ifne', 'ifgt', 'ifge', 'iflt', 'ifle' instructions. These instructions are expanded to 'bipush 0; if_icmp'
* during decoding and reassembled during compilation.
*
* There are no 'ifnull' or 'ifnonnull' instructions. These instructions are expanded to 'aconst_null; if_acmp' during decoding and
* reassembled during compilation.
*
* All Java values, including longs and doubles, occupy just one word on the stack. Places where the JVM assumes differently are
* fixed up during compilation. However, longs and double still take up two local variable slots (this usually doesn't matter to
* instrumentation).
*
* Control transfer instructions refer to target instructions using integers. These integers are usually indices into an array of
* instructions.
*/
public abstract class Instruction implements Constants, Cloneable, IInstruction {
public final static int[] noInstructions = new int[0];
/**
* Ensure that only this package can subclass Instruction.
*/
Instruction(short opcode) {
this.opcode = opcode;
}
final short opcode;
/**
* @return true if the instruction can "fall through" to the following instruction
*/
@Override
public boolean isFallThrough() {
return true;
}
/**
* @return an array containing the labels this instruction can branch to (not including the following instruction if this
* instruction 'falls through')
*/
@Override
public int[] getBranchTargets() {
return noInstructions;
}
/**
* @return an Instruction equivalent to this one but with any branch labels updated by looking them up in the targetMap array
*/
@Override
public IInstruction redirectTargets(int[] targetMap) {
return this;
}
/**
* @return the number of values this instruction pops off the working stack
*/
@Override
public int getPoppedCount() {
return 0;
}
/**
* @return the opcode selected for this instruction, or -1 if we don't know it yet
*/
public final short getOpcode() {
return opcode;
}
/**
* Computes the type of data pushed onto the stack, or null if none is pushed.
*
* @param poppedTypesToCheck the types of the data popped off the stack by this instruction; if poppedTypes is null, then we don't
* know the incoming stack types and the result of this method may be less accurate
*/
@Override
public String getPushedType(String[] poppedTypesToCheck) {
return null;
}
/**
* @return the JVM word size of the value this instruction pushes onto the stack, or 0 if this instruction doesn't push anything
* onto the stack.
*/
@Override
public byte getPushedWordSize() {
return 0;
}
/**
* Apply a Visitor to this instruction. We invoke the appropriate Visitor method according to the type of this instruction.
*/
@Override
public abstract void visit(IInstruction.Visitor v);
/**
* Subclasses must implement toString.
*/
@Override
public abstract String toString();
/**
* We're immutable so there's no need to clone any Instruction object.
*/
@Override
final public Object clone() {
return this;
}
}