⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codeattr.java

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
// Copyright (c) 1997, 1998, 1999, 2001, 2003, 2004  Per M.A. Bothner.// This is free software;  for terms and warranty disclaimer see ./COPYING.package gnu.bytecodecvssnap;import java.io.*;/**  * Represents the contents of a standard "Code" attribute.  * <p>  * Most of the actual methods that generate bytecode operation  * are in this class (typically with names starting with <code>emit</code>),  * though there are also some in <code>Method</code>.  * <p>  * Note that a <code>CodeAttr</code> is an <code>Attribute</code>  * of a <code>Method</code>, and can in turn contain other  * <code>Attribute</code>s, such as a <code>LineNumbersAttr</code>.  *  * @author      Per Bothner  */public class CodeAttr extends Attribute implements AttrContainer{  Attribute attributes;  public final Attribute getAttributes () { return attributes; }  public final void setAttributes (Attribute attributes)  { this.attributes = attributes; }  LineNumbersAttr lines;  public LocalVarsAttr locals;  SourceDebugExtAttr sourceDbgExt;  // In hindsight, maintaining stack_types is more hassle than it is worth.  // Instead, better to just keep track of SP, which should catch most  // stack errors, while being more general and less hassle.  FIXME.  Type[] stack_types;  int SP;  // Current stack size (in "words")  private int max_stack;  private int max_locals;  /** Current active length of code array.   * Note that processFixups may expand/contract the code array.  */  int PC;  byte[] code;  /* The exception handler table, as a vector of quadruples     (start_pc, end_pc, handler_pc, catch_type).     Only the first exception_table_length quadruples are defined. */  short[] exception_table;  /* The number of (defined) exception handlers (i.e. quadruples)     in exception_table. */  int exception_table_length;  /** Not a fixup - a no-op. */  static final int FIXUP_NONE = 0;  /** The definition of a label. */  static final int FIXUP_DEFINE = 1;  /** The offset points to a tableswitch/lookupswitch - handle padding. */  static final int FIXUP_SWITCH = 2;  /** The offset contains a label relative to the previous FIXUP_SWITCH. */  static final int FIXUP_CASE = 3;  /** The offset points to a goto instruction.   * This case up to FIXUP_TRANSFER2 must be contiguous   * - see the jump-to-jump optimization in processFixups. */  static final int FIXUP_GOTO = 4;  /** The offset points to a jsr instruction. */  static final int FIXUP_JSR = 5;  /** The offset points to a conditional transfer (if_xxx) instruction. */  static final int FIXUP_TRANSFER = 6;  /** A FIXUP_GOTO_, FIXUP_JSR, or FIXUP_TRANSFER that uses a 2-byte offset. */  static final int FIXUP_TRANSFER2 = 7;  /** The offsets points to 3 bytes that should be deleted. */  static final int FIXUP_DELETE3 = 8;  /** The following instructions are moved to later in the code stream.   * Instead the instructions starting at the fixup label are patched here.   * (If the fixup label is null, we're done.)   * This allows re-arranging code to avoid unneeded gotos.   * The following instruction is the target of a later FIXUP_MOVE,   * and we'll insert then when we get to it. */  static final int FIXUP_MOVE = 9;  /** The following instructions are moved to the end of the code stream.   * Same as FIXUP_MOVE, but there is no explicit later FIXUP_MOVE that   * refers to the following instructions.  Created by beginFragment.   * The fixup_offset points to the end of the fragment.   * (The first processFixups patches these to FIXUP_MOVE.) */  static final int FIXUP_MOVE_TO_END = 10;  /** FIXUP_TRY with the following FIXUP_CATCH marks an exception handler.   * The label is the start of the try clause;   * the current offset marks the exception handler. */  static final int FIXUP_TRY = 11;  /** Second half of a FIXUP_TRY/FIXUP_CATCH pair.   * The label is the ed of the try clause;   * the current offset is the exception type as a constant pool index. */  static final int FIXUP_CATCH = 12;  /** With following FIXUP_LINE_NUMBER associates an offset with a line number.   * The fixup_offset is the code location; the fixup_label is null. */  static final int FIXUP_LINE_PC = 13;  /** With preceding FIXUP_LINE_PC associates an offset with a line number.   * The fixup_offset is the line number; the fixup_label is null. */  static final int FIXUP_LINE_NUMBER = 14;  int[] fixup_offsets;  Label[] fixup_labels;  int fixup_count;  /** This causes a later processFixup to rearrange the code.   * The codet a target comes here, nstead of the following instructions. */  public final void fixupChain (Label here, Label target)  {    fixupAdd(CodeAttr.FIXUP_MOVE, 0, target);    here.define(this);  }  /** Add a fixup at this location.   * @param kind one of the FIXUP_xxx codes.   * @param label varies - typically the target of jump. */  public final void fixupAdd (int kind, Label label)  {    fixupAdd(kind, PC, label);  }  final void fixupAdd (int kind, int offset, Label label)  {    int count = fixup_count;    if (count == 0)      {	fixup_offsets = new int[30];	fixup_labels = new Label[30];      }    else if (fixup_count == fixup_offsets.length)      {	int new_length = 2 * count;	Label[] new_labels = new Label[new_length];	System.arraycopy (fixup_labels, 0, new_labels, 0, count);	fixup_labels = new_labels;	int[] new_offsets = new int[new_length];	System.arraycopy (fixup_offsets, 0, new_offsets, 0, count);	fixup_offsets = new_offsets;      }    fixup_offsets[count] = (offset << 4) | kind;    fixup_labels[count] = label;    fixup_count = count + 1;  }  private final int fixupOffset(int index)  {    return fixup_offsets[index] >> 4;  }  private final int fixupKind(int index)  {    return fixup_offsets[index] & 15;  }  /** The stack of currently active conditionals. */  IfState if_stack;  /** The stack of currently active try statements. */  TryState try_stack;  public final Method getMethod() { return (Method) getContainer(); }  public final int getPC() { return PC; }  public final int getSP() { return SP; }  public final ConstantPool getConstants ()  {    return getMethod().classfile.constants;  }  /* True if we cannot fall through to bytes[PC] -     the previous instruction was an uncondition control transfer.  */  private boolean unreachable_here;  /** True if control could reach here. */  public final boolean reachableHere () { return !unreachable_here; }  public final void setReachable(boolean val) { unreachable_here = !val; }  public final void setUnreachable() { unreachable_here = true; }  /** Get the maximum number of words on the operand stack in this method. */  public int getMaxStack() { return max_stack; }  /** Get the maximum number of local variable words in this method. */  public int getMaxLocals() { return max_locals; }  /** Set the maximum number of words on the operand stack in this method. */  public void setMaxStack(int n) { max_stack = n; }  /** Set the maximum number of local variable words in this method. */  public void setMaxLocals(int n) { max_locals = n; }  /** Get the code (instruction bytes) of this method.    * Does not make a copy. */  public byte[] getCode() { return code; }  /** Set the code (instruction bytes) of this method.    * @param code the code bytes (which are not copied).    * Implicitly calls setCodeLength(code.length). */  public void setCode(byte[] code) {    this.code = code; this.PC = code.length; }  /** Set the length the the code (instruction bytes) of this method.    * That is the number of current used bytes in getCode().    * (Any remaing bytes provide for future growth.) */  public void setCodeLength(int len) { PC = len;}  /** Set the current lengthof the code (instruction bytes) of this method. */  public int getCodeLength() { return PC; }  public CodeAttr (Method meth)  {    super ("Code");    addToFrontOf(meth);    meth.code = this;  }  public final void reserve (int bytes)  {    if (code == null)      code = new byte[100+bytes];    else if (PC + bytes > code.length)      {	byte[] new_code = new byte[2 * code.length + bytes];	System.arraycopy (code, 0, new_code, 0, PC);	code = new_code;      }  }  /** Get opcode that implements NOT (x OPCODE y). */  byte invert_opcode (byte opcode)  {    if ((opcode >= 153 && opcode <= 166)	|| (opcode >= 198 && opcode <= 199))      return (byte) (opcode ^ 1);    throw new Error("unknown opcode to invert_opcode");  }  /**   * Write an 8-bit byte to the current code-stream.   * @param i the byte to write   */  public final void put1(int i)  {    code[PC++] = (byte) i;    unreachable_here = false;  }  /**   * Write a 16-bit short to the current code-stream   * @param i the value to write   */  public final void put2(int i)  {    code[PC++] = (byte) (i >> 8);    code[PC++] = (byte) (i);    unreachable_here = false;  }  /**   * Write a 32-bit int to the current code-stream   * @param i the value to write   */  public final void put4(int i)  {    code[PC++] = (byte) (i >> 24);    code[PC++] = (byte) (i >> 16);    code[PC++] = (byte) (i >> 8);    code[PC++] = (byte) (i);    unreachable_here = false;  }  public final void putIndex2 (CpoolEntry cnst)  {    put2(cnst.index);  }  public final void putLineNumber (String filename, int linenumber)  {    getMethod().classfile.setSourceFile(filename);    putLineNumber(linenumber);  }  public final void putLineNumber (int linenumber)  {    if (sourceDbgExt != null)      linenumber = sourceDbgExt.fixLine(linenumber);    fixupAdd(FIXUP_LINE_PC, null);    fixupAdd(FIXUP_LINE_NUMBER, linenumber, null);  }  public final void pushType(Type type)  {    if (type.size == 0)      throw new Error ("pushing void type onto stack");    if (stack_types == null)      stack_types = new Type[20];    else if (SP + 1 >= stack_types.length) {      Type[] new_array = new Type[2 * stack_types.length];      System.arraycopy (stack_types, 0, new_array, 0, SP);      stack_types = new_array;    }    if (type.size == 8)      stack_types[SP++] = Type.void_type;    stack_types[SP++] = type;    if (SP > max_stack)      max_stack = SP;  }  public final Type popType ()  {    if (SP <= 0)      throw new Error("popType called with empty stack "+getMethod());    Type type = stack_types[--SP];    if (type.size == 8)      if (! popType().isVoid())	throw new Error("missing void type on stack");    return type;  }  public final Type topType ()  {    return stack_types[SP - 1];  }  /** Compile code to pop values off the stack (and ignore them).   * @param nvalues the number of values (not words) to pop   */  public void emitPop (int nvalues)  {    for ( ; nvalues > 0;  --nvalues)      {        reserve(1);	Type type = popType();	if (type.size > 4)	  put1(88);  // pop2	else if (nvalues > 1)	  { // optimization:  can we pop 2 4-byte words using a pop2	    Type type2 = popType();	    if (type2.size > 4)	      {		put1(87);  // pop		reserve(1);	      }	    put1(88);  // pop2	    --nvalues;	  }	else	  put1(87); // pop      }  }  /** Get a new Label for the current location.   * Unlike Label.define, Does not change reachableHere().   */  public Label getLabel ()  {    boolean  unreachable = unreachable_here;    Label label = new Label();    label.define(this);    unreachable_here = unreachable;    return label;  }  public void emitSwap ()  {    reserve(1);    Type type1 = popType();    Type type2 = popType();    if (type1.size > 4 || type2.size > 4)      {	// There is no swap instruction in the JVM for this case.	// Fall back to a more convoluted way.	pushType(type2);	pushType(type1);	emitDupX();	emitPop(1);      }    else      {	pushType(type1);	put1(95);  // swap	pushType(type2);      }  }  /** Emit code to duplicate the top element of the stack. */  public void emitDup ()  {    reserve(1);    Type type = topType();    put1 (type.size <= 4 ? 89 : 92); // dup or dup2    pushType (type);  }  /** Emit code to duplicate the top element of the stack      and place the copy before the previous element. */  public void emitDupX ()  {    reserve(1);    Type type = popType();    Type skipedType = popType();    if (skipedType.size <= 4)      put1 (type.size <= 4 ? 90 : 93); // dup_x1 or dup2_x1    else      put1 (type.size <= 4 ? 91 : 94); // dup_x2 or dup2_x2    pushType (type);    pushType (skipedType);    pushType (type);  }  /** Compile code to duplicate with offset.   * @param size the size of the stack item to duplicate (1 or 2)   * @param offset where to insert the result (must be 0, 1, or 2)   * The new words get inserted at stack[SP-size-offset]   */  public void emitDup (int size, int offset)  {    if (size == 0)      return;    reserve(1);    // copied1 and (optionally copied2) are the types of the duplicated words    Type copied1 = popType ();    Type copied2 = null;    if (size == 1)      {	if (copied1.size > 4)	  throw new Error ("using dup for 2-word type");      }    else if (size != 2)      throw new Error ("invalid size to emitDup");    else if (copied1.size <= 4)      {	copied2 = popType();	if (copied2.size > 4)	  throw new Error ("dup will cause invalid types on stack");      }    int kind;    // These are the types of the words (in any) that are "skipped":    Type skipped1 = null;    Type skipped2 = null;    if (offset == 0)      {	kind = size == 1 ? 89 : 92;  // dup or dup2      }    else if (offset == 1)      {	kind = size == 1 ? 90 : 93; // dup_x1 or dup2_x1	skipped1 = popType ();	if (skipped1.size > 4)	  throw new Error ("dup will cause invalid types on stack");      }    else if (offset == 2)      {	kind = size == 1 ? 91 : 94; // dup_x2 or dup2_x2	skipped1 = popType();	if (skipped1.size <= 4)	  {	    skipped2 = popType();	    if (skipped2.size > 4)	      throw new Error ("dup will cause invalid types on stack");	  }      }    else      throw new Error ("emitDup:  invalid offset");    put1(kind);    if (copied2 != null)      pushType(copied2);    pushType(copied1);    if (skipped2 != null)      pushType(skipped2);    if (skipped1 != null)      pushType(skipped1);    if (copied2 != null)      pushType(copied2);    pushType(copied1);  }  /**   * Compile code to duplicate the top 1 or 2 words.   * @param size number of words to duplicate   */  public void emitDup (int size)  {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -