133 lines
4.6 KiB
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;
|
|
}
|
|
} |