
com.sun.jdo.api.persistence.enhancer.classfile.Insn Maven / Gradle / Ivy
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.jdo.api.persistence.enhancer.classfile;
import java.io.PrintStream;
/**
* Insn is an abstract class which represents a java VM instruction in a
* sequence of instructions.
*/
abstract public class Insn implements VMConstants {
/* An instruction with no pc defined yet */
final static int NO_OFFSET = -1;
/* A special magic opcode for branch target pseudo instructions */
final public static int opc_target = -1;
/* The opcode of this instruction */
private int insnOpcode;
/* The pc of this instruction within the containing code sequence */
private int insnOffset = NO_OFFSET;
/* The next instruction in the code sequence */
private Insn nextInsn = null;
/* The previous instruction in the code sequence */
private Insn prevInsn = null;
/* public accessors */
/**
* Returns the next instruction in the code sequence
*/
public Insn next() {
return nextInsn;
}
/**
* Returns the previous instruction in the code sequence
*/
public Insn prev() {
return prevInsn;
}
/**
* Removes the current instruction from it's embedding sequence.
*/
//@olsen: added method
public void remove() {
if (nextInsn != null)
nextInsn.prevInsn = prevInsn;
if (prevInsn != null)
prevInsn.nextInsn = nextInsn;
prevInsn = null;
nextInsn = null;
}
/**
* Insert the single instruction in the code sequence after this
* instruction.
* Returns the inserted instruction.
*/
public Insn setNext(Insn i) {
if (nextInsn != null)
nextInsn.prevInsn = i;
if (i != null) {
i.nextInsn = nextInsn;
i.prevInsn = this;
}
nextInsn = i;
return i;
}
/**
* Insert an instruction sequence in the code sequence after this
* instruction.
* Returns the final instruction.
*/
public Insn insert(Insn i) {
if (i == null)
return this;
Insn theNextInsn = nextInsn;
nextInsn = i;
i.prevInsn = this;
while (i.nextInsn != null)
i = i.nextInsn;
i.nextInsn = theNextInsn;
if (theNextInsn != null)
theNextInsn.prevInsn = i;
return i;
}
/**
* Append an instruction sequence at the end of this instruction
* sequence.
* Returns the final instruction.
*/
public Insn append(Insn i) {
Insn thisInsn = this;
while (thisInsn.nextInsn != null)
thisInsn = thisInsn.nextInsn;
return thisInsn.insert(i);
}
/**
* Return the opcode for this instruction
*/
public int opcode() {
return insnOpcode;
}
/**
* Return the offset of this instruction in the containing code sequence
*/
public int offset() {
return insnOffset;
}
/**
* How many words of stack operands does this instruction take?
*/
abstract public int nStackArgs();
/**
* How many words of stack results does this instruction deposit?
*/
abstract public int nStackResults();
/**
* What are the types of the stack operands ?
*/
abstract public String argTypes();
/**
* What are the types of the stack results?
*/
abstract public String resultTypes();
/**
* Does this instruction branch?
*/
abstract public boolean branches();
/**
* Mark possible branch targets
*/
public void markTargets() {
}
/**
* Return the name of the operation for a given opcode
*/
public static String opName(int opcode) {
if (opcode == opc_target)
return "target:";//NOI18N
if (opcode >=0 && opcode <= VMOp.ops.length)
return VMOp.ops[opcode].name();
else
throw new InsnError("invalid opcode for opName: " + opcode);//NOI18N
}
/* Instruction creation interfaces - these should be used for all
* instructions except opc_iinc, opc_tableswitch, opc_lookupswitch,
* opc_multidimarraynew, and opc_invokeinterface.
*/
/**
* Create an instruction which requires no immediate operands
*/
public static Insn create(int theOpCode) {
return new InsnSingle(theOpCode);
}
/**
* Create an instruction which requires a single constant from the
* constant pool as an immediate operand.
*/
public static Insn create(int theOpCode, ConstBasic constValue) {
return new InsnConstOp(theOpCode, constValue);
}
/**
* Create an instruction which requires a single integral constant
* as an immediate operand.
*/
public static Insn create(int theOpCode, int intValue) {
return new InsnIntOp(theOpCode, intValue);
}
/**
* Create an instruction which requires a single branch offset
* as an immediate operand.
*/
public static Insn create(int theOpCode, InsnTarget target) {
return new InsnTargetOp(theOpCode, target);
}
/**
* Print the sequence of instructions to the output stream
*/
public void printList(PrintStream out) {
Insn insn = this;
while (insn != null) {
insn.print(out, 0);
insn = insn.next();
}
}
/**
* Print this instruction to the output stream
*/
public void printInsn(PrintStream out) {
print(out, 0);
}
/* package local methods */
abstract void print (PrintStream out, int indent);
abstract int store(byte[] buf, int index);
/* return the size of the instruction in bytes
* Note: some instructions are unable to answer correctly until their
* start offset is known
*/
abstract int size();
/* Set the offset of the instruction and return the offset of the
following instruction */
final int resolveOffset(int pc) {
insnOffset = pc;
return pc + size();
}
Insn(int theOpcode, int theOffset) {
insnOpcode = theOpcode;
insnOffset = theOffset;
}
static int storeInt(byte buf[], int index, int v) {
buf[index++] = (byte) (v >> 24);
buf[index++] = (byte) ((v >> 16) & 0xff);
buf[index++] = (byte) ((v >> 8) & 0xff);
buf[index++] = (byte) (v & 0xff);
return index;
}
static int storeShort(byte buf[], int index, short v) {
buf[index++] = (byte) ((v >> 8) & 0xff);
buf[index++] = (byte) (v & 0xff);
return index;
}
static Insn read(InsnReadEnv insnEnv) {
boolean widen = false;
int pc = insnEnv.currentPC();
int op = insnEnv.getUByte();
if (op == opc_wide) {
widen = true;
op = insnEnv.getUByte();
}
switch (op) {
case opc_nop:
case opc_aconst_null:
case opc_iconst_m1:
case opc_iconst_0:
case opc_iconst_1:
case opc_iconst_2:
case opc_iconst_3:
case opc_iconst_4:
case opc_iconst_5:
case opc_lconst_0:
case opc_lconst_1:
case opc_fconst_0:
case opc_fconst_1:
case opc_fconst_2:
case opc_dconst_0:
case opc_dconst_1:
case opc_iload_0:
case opc_iload_1:
case opc_iload_2:
case opc_iload_3:
case opc_lload_0:
case opc_lload_1:
case opc_lload_2:
case opc_lload_3:
case opc_fload_0:
case opc_fload_1:
case opc_fload_2:
case opc_fload_3:
case opc_dload_0:
case opc_dload_1:
case opc_dload_2:
case opc_dload_3:
case opc_aload_0:
case opc_aload_1:
case opc_aload_2:
case opc_aload_3:
case opc_iaload:
case opc_laload:
case opc_faload:
case opc_daload:
case opc_aaload:
case opc_baload:
case opc_caload:
case opc_saload:
case opc_istore_0:
case opc_istore_1:
case opc_istore_2:
case opc_istore_3:
case opc_lstore_0:
case opc_lstore_1:
case opc_lstore_2:
case opc_lstore_3:
case opc_fstore_0:
case opc_fstore_1:
case opc_fstore_2:
case opc_fstore_3:
case opc_dstore_0:
case opc_dstore_1:
case opc_dstore_2:
case opc_dstore_3:
case opc_astore_0:
case opc_astore_1:
case opc_astore_2:
case opc_astore_3:
case opc_iastore:
case opc_lastore:
case opc_fastore:
case opc_dastore:
case opc_aastore:
case opc_bastore:
case opc_castore:
case opc_sastore:
case opc_pop:
case opc_pop2:
case opc_dup:
case opc_dup_x1:
case opc_dup_x2:
case opc_dup2:
case opc_dup2_x1:
case opc_dup2_x2:
case opc_swap:
case opc_iadd:
case opc_ladd:
case opc_fadd:
case opc_dadd:
case opc_isub:
case opc_lsub:
case opc_fsub:
case opc_dsub:
case opc_imul:
case opc_lmul:
case opc_fmul:
case opc_dmul:
case opc_idiv:
case opc_ldiv:
case opc_fdiv:
case opc_ddiv:
case opc_irem:
case opc_lrem:
case opc_frem:
case opc_drem:
case opc_ineg:
case opc_lneg:
case opc_fneg:
case opc_dneg:
case opc_ishl:
case opc_lshl:
case opc_ishr:
case opc_lshr:
case opc_iushr:
case opc_lushr:
case opc_iand:
case opc_land:
case opc_ior:
case opc_lor:
case opc_ixor:
case opc_lxor:
case opc_i2l:
case opc_i2f:
case opc_i2d:
case opc_l2i:
case opc_l2f:
case opc_l2d:
case opc_f2i:
case opc_f2l:
case opc_f2d:
case opc_d2i:
case opc_d2l:
case opc_d2f:
case opc_i2b:
case opc_i2c:
case opc_i2s:
case opc_lcmp:
case opc_fcmpl:
case opc_fcmpg:
case opc_dcmpl:
case opc_dcmpg:
case opc_ireturn:
case opc_lreturn:
case opc_freturn:
case opc_dreturn:
case opc_areturn:
case opc_return:
case opc_xxxunusedxxx:
case opc_arraylength:
case opc_athrow:
case opc_monitorenter:
case opc_monitorexit:
return new InsnSingle(op, pc);
case opc_ldc:
return new InsnConstOp(op, insnEnv.pool().constantAt(insnEnv.getUByte()),
pc);
case opc_ldc_w:
case opc_ldc2_w:
case opc_getstatic:
case opc_putstatic:
case opc_getfield:
case opc_putfield:
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic:
case opc_new:
case opc_anewarray:
case opc_checkcast:
case opc_instanceof:
return new InsnConstOp(op,
insnEnv.pool().constantAt(insnEnv.getUShort()),
pc);
case opc_iload:
case opc_lload:
case opc_fload:
case opc_dload:
case opc_aload:
case opc_istore:
case opc_lstore:
case opc_fstore:
case opc_dstore:
case opc_astore:
case opc_ret:
if (widen)
return new InsnIntOp(op, insnEnv.getShort(), pc);
else
return new InsnIntOp(op, insnEnv.getByte(), pc);
case opc_bipush: /* a byte constant */
case opc_newarray:
return new InsnIntOp(op, insnEnv.getByte(), pc);
case opc_sipush: /* a short constant */
return new InsnIntOp(op, insnEnv.getShort(), pc);
case opc_iinc:
if (widen)
return new InsnIInc(insnEnv.getUShort(), insnEnv.getShort(), pc);
else
return new InsnIInc(insnEnv.getUByte(), insnEnv.getByte(), pc);
case opc_ifeq:
case opc_ifne:
case opc_iflt:
case opc_ifge:
case opc_ifgt:
case opc_ifle:
case opc_if_icmpeq:
case opc_if_icmpne:
case opc_if_icmplt:
case opc_if_icmpge:
case opc_if_icmpgt:
case opc_if_icmple:
case opc_if_acmpeq:
case opc_if_acmpne:
case opc_goto:
case opc_jsr:
case opc_ifnull:
case opc_ifnonnull:
return new InsnTargetOp(op, insnEnv.getTarget(insnEnv.getShort()+pc), pc);
case opc_goto_w:
case opc_jsr_w:
return new InsnTargetOp(op, insnEnv.getTarget(insnEnv.getInt()+pc), pc);
case opc_tableswitch:
return InsnTableSwitch.read(insnEnv, pc);
case opc_lookupswitch:
return InsnLookupSwitch.read(insnEnv, pc);
case opc_invokeinterface:
return InsnInterfaceInvoke.read(insnEnv, pc);
case opc_multianewarray:
return InsnMultiDimArrayNew.read(insnEnv, pc);
}
throw new InsnError("Invalid byte code (" + op + ")");//NOI18N
}
/**
* Return the type of value manipulated by the load/store instruction
*/
public static final int loadStoreDataType(int opcode) {
switch(opcode) {
case opc_iload:
case opc_iload_0:
case opc_iload_1:
case opc_iload_2:
case opc_iload_3:
case opc_istore:
case opc_istore_0:
case opc_istore_1:
case opc_istore_2:
case opc_istore_3:
case opc_iaload:
case opc_baload:
case opc_caload:
case opc_saload:
case opc_iastore:
case opc_bastore:
case opc_castore:
case opc_sastore:
return T_INT;
case opc_lload:
case opc_lload_0:
case opc_lload_1:
case opc_lload_2:
case opc_lload_3:
case opc_lstore:
case opc_lstore_0:
case opc_lstore_1:
case opc_lstore_2:
case opc_lstore_3:
case opc_laload:
case opc_lastore:
return T_LONG;
case opc_fload:
case opc_fload_0:
case opc_fload_1:
case opc_fload_2:
case opc_fload_3:
case opc_fstore:
case opc_fstore_0:
case opc_fstore_1:
case opc_fstore_2:
case opc_fstore_3:
case opc_faload:
case opc_fastore:
return T_FLOAT;
case opc_dload:
case opc_dload_0:
case opc_dload_1:
case opc_dload_2:
case opc_dload_3:
case opc_dstore:
case opc_dstore_0:
case opc_dstore_1:
case opc_dstore_2:
case opc_dstore_3:
case opc_daload:
case opc_dastore:
return T_DOUBLE;
case opc_aload:
case opc_aload_0:
case opc_aload_1:
case opc_aload_2:
case opc_aload_3:
case opc_astore:
case opc_astore_0:
case opc_astore_1:
case opc_astore_2:
case opc_astore_3:
case opc_aaload:
case opc_aastore:
return TC_OBJECT;
default:
throw new InsnError("not a load/store");//NOI18N
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy