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

📄 codeattr.java

📁 这是一个Linux下的集成开发环境
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
// Copyright (c) 1997  Per M.A. Bothner.// This is free software;  for terms and warranty disclaimer see ./COPYING.package gnu.bytecode;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;  LocalVarsAttr locals;  private Type[] stack_types;  int SP;  // Current stack size (in "words")  private int max_stack;  private int max_locals;  int PC;  // readPC (which is <= PC) is a bound on locations that have been  // saved into labels or otherwise externally seen.  // Hence, we cannot re-arrange code upto readPC, but we can  // rearrange code between readPC and PC.  int readPC;  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 quadrules are defined. */  short[] exception_table;  /* The number of (defined) exception handlers (i.e. quadruples)     in exception_table. */  int exception_table_length;  /* A chain of labels.  Unsorted, except that the Label with     the lowest element in fixups must be the first one. */  Label labels;  /** 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 ConstantPool getConstants ()  {    return getMethod().classfile.constants;  }  /* True if we cannot fall through to bytes[PC] -     the previous instruction was an uncondition control transfer.  */  boolean unreachable_here;  /** True if control could reach here. */  public boolean reachableHere () { return !unreachable_here; }  /** 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; readPC = PC; }  /** 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; readPC = len;}  /** Set the current lengthof the code (instruction bytes) of this method. */  public int getCodeLength() { readPC = PC;  return PC; }  public CodeAttr (Method meth)  {    super ("Code");    setContainer(meth);    setNext(meth.getAttributes());    meth.setAttributes(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;      }    while (labels != null && labels.fixups != null) {      int oldest_fixup = labels.fixups[0];      int threshold = unreachable_here ? 30000 : 32000;      if (PC + bytes - oldest_fixup > threshold)	labels.emit_spring (this);      else	break;    }  }  /**   * 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 (int linenumber)  {    if (lines == null)      lines = new LineNumbersAttr(this);    readPC = PC;    lines.put(linenumber, PC);  }  public final void pushType(Type type)  {    if (type == Type.void_type)      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");    Type type = stack_types[--SP];    if (type.size == 8)      if (popType () != Type.void_type)	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      }  }  public void emitSwap ()  {    reserve(1);    Type type1 = popType();    Type type2 = popType();    if (type1.size > 4 || type2.size > 4)      throw new Error ("emitSwap:  not allowed for long or double");    pushType(type1);    put1(95);  // swap    pushType(type2);  }  /** 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)  {    emitDup(size, 0);  }  public void emitDup (Type type)  {    emitDup(type.size > 4 ? 2 : 1, 0);  }  public void enterScope (Scope scope)  {    locals.enterScope(scope);  }  public Scope pushScope () {    Scope scope = new Scope ();    scope.start_pc = PC;    readPC = PC;    if (locals == null)      locals = new LocalVarsAttr(this);    locals.enterScope(scope);    if (locals.parameter_scope == null)       locals.parameter_scope= scope;    return scope;  }  public Scope popScope () {    Scope scope = locals.current_scope;    locals.current_scope = scope.parent;    scope.end_pc = PC;  readPC = PC;    for (Variable var = scope.vars; var != null; var = var.next) {      if (var.isSimple () && ! var.dead ())	var.freeLocal(this);    }    return scope;  }  /** Get the index'th parameter. */  public Variable getArg (int index)  {    return locals.parameter_scope.find_var (index);  }  /**   * Search by name for a Variable   * @param name name to search for   * @return the Variable, or null if not found (in any scope of this Method).   */  Variable lookup (String name)  {    Scope scope = locals.current_scope;    for (; scope != null;  scope = scope.parent)      {	Variable var = scope.lookup (name);	if (var != null)	  return var;      }    return null;  }  /** Add a new local variable (in the current scope).   * @param type type of the new Variable.   * @return the new Variable. */  public Variable addLocal (Type type)  {    return locals.current_scope.addVariable(this, type, null);  }  /** Add a new local variable (in the current scope).   * @param type type of the new Variable.   * @param name name of the new Variable.   * @return the new Variable. */  Variable addLocal (Type type, String name)  {    return locals.current_scope.addVariable (this, type, name);  }  public final void emitPushConstant(int val, Type type)  {    switch (type.getSignature().charAt(0))      {      case 'B':  case 'C':  case 'I':  case 'Z':  case 'S':	emitPushInt(val);  break;      case 'J':	emitPushLong((long)val);  break;      case 'F':	emitPushFloat((float)val);  break;      case 'D':	emitPushDouble((double)val);  break;      default:	throw new Error("bad type to emitPushConstant");      }  }  public final void emitPushConstant (CpoolEntry cnst)  {    reserve(3);    int index = cnst.index;    if (cnst instanceof CpoolValue2)      {      	put1 (20); // ldc2w	put2 (index);      }    else if (index < 256)      {	put1(18); // ldc1	put1(index);      }    else      {	put1(19); // ldc2	put2(index);      }  }  public final void emitPushInt(int i)  {    reserve(3);    if (i >= -1 && i <= 5)      put1(i + 3);  // iconst_m1 .. iconst_5    else if (i >= -128 && i < 128)      {	put1(16); // bipush	put1(i);      }    else if (i >= -32768 && i < 32768)      {	put1(17); // sipush	put2(i);      }    else      {	emitPushConstant(getConstants().addInt(i));      }    pushType(Type.int_type);  }  public void emitPushLong (long i)  {    if (i == 0 || i == 1)      {	reserve(1);	put1 (9 + (int) i);  // lconst_0 .. lconst_1      }    else if ((long) (int) i == i)      {	emitPushInt ((int) i);	reserve(1);	popType();	put1 (133); // i2l      }    else      {	emitPushConstant(getConstants().addLong(i));      }    pushType(Type.long_type);  }  public void emitPushFloat (float x)  {    int xi = (int) x;    if ((float) xi == x && xi >= -128 && xi < 128)      {	if (xi >= 0 && xi <= 2)	  {	    reserve(1);	    put1(11 + xi);  // fconst_0 .. fconst_2	  }	else	  {	    // Saves space in the constant pool	    // Probably faster, at least on modern CPUs.	    emitPushInt (xi);	    reserve(1);	    popType();	    put1 (134); // i2f	  }      }    else      {	emitPushConstant(getConstants().addFloat(x));      }    pushType(Type.float_type);  }  public void emitPushDouble (double x)  {    int xi = (int) x;    if ((double) xi == x && xi >= -128 && xi < 128)      {	if (xi == 0 || xi == 1)	  {	    reserve(1);	    put1(14+xi);  // dconst_0 or dconst_1	  }	else	  {	    // Saves space in the constant pool	    // Probably faster, at least on modern CPUs.	    emitPushInt (xi);	    reserve(1);	    popType();	    put1 (135); // i2d	  }      }    else      {	emitPushConstant(getConstants().addDouble(x));      }    pushType(Type.double_type);  }  public final void emitPushString (String str)  {    emitPushConstant(getConstants().addString(str));    pushType(Type.string_type);  }  public void emitPushNull ()  {    reserve(1);    put1(1);  // aconst_null    pushType(Type.pointer_type);  }  public final void emitPushThis()  {    reserve(1);    put1(42);  // aload_0    pushType(getMethod().getDeclaringClass());  }  void emitNewArray (int type_code)  {    reserve(2);    put1(188);  // newarray    put1(type_code);  }  public final void emitArrayLength ()  {    reserve(1);    put1(190);  // arraylength    pushType(Type.int_type);  }  private int adjustTypedOp  (Type type)  {    switch (type.getSignature().charAt(0))      {      case 'I':  return 0;  // int      case 'J':  return 1;  // long      case 'F':  return 2;  // float      case 'D':  return 3;  // double      default:   return 4;  // object      case 'B':      case 'Z':  return 5;  // byte or boolean      case 'C':  return 6;  // char      case 'S':  return 7;  // short      }  }  private void emitTypedOp (int op, Type type)  {    reserve(1);    put1(op + adjustTypedOp(type));  }  /** Store into an element of an array.   * Must already have pushed the array reference, the index,   * and the new value (in that order).   * Stack:  ..., array, index, value => ...   */

⌨️ 快捷键说明

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