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

📄 codewriter.java

📁 开源的java 编辑器源代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
      -2, //DRETURN,         // -      -1, //ARETURN,         // -      0,  //RETURN,          // -      NA, //GETSTATIC,       // visitFieldInsn      NA, //PUTSTATIC,       // -      NA, //GETFIELD,        // -      NA, //PUTFIELD,        // -      NA, //INVOKEVIRTUAL,   // visitMethodInsn      NA, //INVOKESPECIAL,   // -      NA, //INVOKESTATIC,    // -      NA, //INVOKEINTERFACE, // -      NA, //UNUSED,          // NOT VISITED      1,  //NEW,             // visitTypeInsn      0,  //NEWARRAY,        // visitIntInsn      0,  //ANEWARRAY,       // visitTypeInsn      0,  //ARRAYLENGTH,     // visitInsn      NA, //ATHROW,          // -      0,  //CHECKCAST,       // visitTypeInsn      0,  //INSTANCEOF,      // -      -1, //MONITORENTER,    // visitInsn      -1, //MONITOREXIT,     // -      NA, //WIDE,            // NOT VISITED      NA, //MULTIANEWARRAY,  // visitMultiANewArrayInsn      -1, //IFNULL,          // visitJumpInsn      -1, //IFNONNULL,       // -      NA, //GOTO_W,          // -      NA, //JSR_W,           // -    };    for (i = 0; i < b.length; ++i) {      System.err.print((char)('E' + b[i]));    }    System.err.println();    */  }  // --------------------------------------------------------------------------  // Constructor  // --------------------------------------------------------------------------  /**   * Constructs a CodeWriter.   *   * @param cw the class writer in which the method must be added.   * @param computeMaxs <tt>true</tt> if the maximum stack size and number of   *      local variables must be automatically computed.   */  protected CodeWriter (final ClassWriter cw, final boolean computeMaxs) {    if (cw.firstMethod == null) {      cw.firstMethod = this;      cw.lastMethod = this;    } else {      cw.lastMethod.next = this;      cw.lastMethod = this;    }    this.cw = cw;    this.computeMaxs = computeMaxs;    if (computeMaxs) {      // pushes the first block onto the stack of blocks to be visited      currentBlock = new Label();      currentBlock.pushed = true;      blockStack = currentBlock;    }  }  /**   * Initializes this CodeWriter to define the bytecode of the specified method.   *   * @param access the method's access flags (see {@link Constants}).   * @param name the method's name.   * @param desc the method's descriptor (see {@link Type Type}).   * @param exceptions the internal names of the method's exceptions. May be   *      <tt>null</tt>.   */  protected void init (    final int access,    final String name,    final String desc,    final String[] exceptions)  {    this.access = access;    this.name = cw.newUTF8(name);    this.desc = cw.newUTF8(desc);    if (exceptions != null && exceptions.length > 0) {      exceptionCount = exceptions.length;      this.exceptions = new int[exceptionCount];      for (int i = 0; i < exceptionCount; ++i) {        this.exceptions[i] = cw.newClass(exceptions[i]).index;      }    }    if (computeMaxs) {      // updates maxLocals      int size = getArgumentsAndReturnSizes(desc) >> 2;      if ((access & Constants.ACC_STATIC) != 0) {        --size;      }      if (size > maxLocals) {        maxLocals = size;      }    }  }  // --------------------------------------------------------------------------  // Implementation of the CodeVisitor interface  // --------------------------------------------------------------------------  public void visitInsn (final int opcode) {    if (computeMaxs) {      // updates current and max stack sizes      int size = stackSize + SIZE[opcode];      if (size > maxStackSize) {        maxStackSize = size;      }      stackSize = size;      // if opcode == ATHROW or xRETURN, ends current block (no successor)      if ((opcode >= Constants.IRETURN && opcode <= Constants.RETURN) ||          opcode == Constants.ATHROW)      {        if (currentBlock != null) {          currentBlock.maxStackSize = maxStackSize;          currentBlock = null;        }      }    }    // adds the instruction to the bytecode of the method    code.put1(opcode);  }  public void visitIntInsn (final int opcode, final int operand) {    if (computeMaxs && opcode != Constants.NEWARRAY) {      // updates current and max stack sizes only if opcode == NEWARRAY      // (stack size variation = 0 for BIPUSH or SIPUSH)      int size = stackSize + 1;      if (size > maxStackSize) {        maxStackSize = size;      }      stackSize = size;    }    // adds the instruction to the bytecode of the method    if (opcode == Constants.SIPUSH) {      code.put12(opcode, operand);    } else { // BIPUSH or NEWARRAY      code.put11(opcode, operand);    }  }  public void visitVarInsn (final int opcode, final int var) {    if (computeMaxs) {      // updates current and max stack sizes      if (opcode == Constants.RET) {        // no stack change, but end of current block (no successor)        if (currentBlock != null) {          currentBlock.maxStackSize = maxStackSize;          currentBlock = null;        }      } else { // xLOAD or xSTORE        int size = stackSize + SIZE[opcode];        if (size > maxStackSize) {          maxStackSize = size;        }        stackSize = size;      }      // updates max locals      int n;      if (opcode == Constants.LLOAD || opcode == Constants.DLOAD ||          opcode == Constants.LSTORE || opcode == Constants.DSTORE)      {        n = var + 2;      } else {        n = var + 1;      }      if (n > maxLocals) {        maxLocals = n;      }    }    // adds the instruction to the bytecode of the method    if (var < 4 && opcode != Constants.RET) {      int opt;      if (opcode < Constants.ISTORE) {        opt = 26 /*ILOAD_0*/ + ((opcode - Constants.ILOAD) << 2) + var;      } else {        opt = 59 /*ISTORE_0*/ + ((opcode - Constants.ISTORE) << 2) + var;      }      code.put1(opt);    } else if (var >= 256) {      code.put1(196 /*WIDE*/).put12(opcode, var);    } else {      code.put11(opcode, var);    }  }  public void visitTypeInsn (final int opcode, final String desc) {    if (computeMaxs && opcode == Constants.NEW) {      // updates current and max stack sizes only if opcode == NEW      // (stack size variation = 0 for ANEWARRAY, CHECKCAST, INSTANCEOF)      int size = stackSize + 1;      if (size > maxStackSize) {        maxStackSize = size;      }      stackSize = size;    }    // adds the instruction to the bytecode of the method    code.put12(opcode, cw.newClass(desc).index);  }  public void visitFieldInsn (    final int opcode,    final String owner,    final String name,    final String desc)  {    if (computeMaxs) {      int size;      // computes the stack size variation      char c = desc.charAt(0);      switch (opcode) {        case Constants.GETSTATIC:          size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);          break;        case Constants.PUTSTATIC:          size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);          break;        case Constants.GETFIELD:          size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);          break;        //case Constants.PUTFIELD:        default:          size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);          break;      }      // updates current and max stack sizes      if (size > maxStackSize) {        maxStackSize = size;      }      stackSize = size;    }    // adds the instruction to the bytecode of the method    code.put12(opcode, cw.newField(owner, name, desc).index);  }  public void visitMethodInsn (    final int opcode,    final String owner,    final String name,    final String desc)  {    Item i;    if (opcode == Constants.INVOKEINTERFACE) {      i = cw.newItfMethod(owner, name, desc);    } else {      i = cw.newMethod(owner, name, desc);    }    int argSize = i.intVal;    if (computeMaxs) {      // computes the stack size variation. In order not to recompute several      // times this variation for the same Item, we use the intVal field of      // this item to store this variation, once it has been computed. More      // precisely this intVal field stores the sizes of the arguments and of      // the return value corresponding to desc.      if (argSize == 0) {        // the above sizes have not been computed yet, so we compute them...        argSize = getArgumentsAndReturnSizes(desc);        // ... and we save them in order not to recompute them in the future        i.intVal = argSize;      }      int size;      if (opcode == Constants.INVOKESTATIC) {        size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;      } else {        size = stackSize - (argSize >> 2) + (argSize & 0x03);      }      // updates current and max stack sizes      if (size > maxStackSize) {        maxStackSize = size;      }      stackSize = size;    }    // adds the instruction to the bytecode of the method    if (opcode == Constants.INVOKEINTERFACE) {      if (!computeMaxs) {        if (argSize == 0) {          argSize = getArgumentsAndReturnSizes(desc);          i.intVal = argSize;        }      }      code.put12(Constants.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);    } else {      code.put12(opcode, i.index);    }  }  public void visitJumpInsn (final int opcode, final Label label) {    if (CHECK) {      if (label.owner == null) {        label.owner = this;      } else if (label.owner != this) {        throw new IllegalArgumentException();      }    }    if (computeMaxs) {      if (opcode == Constants.GOTO) {        // no stack change, but end of current block (with one new successor)        if (currentBlock != null) {          currentBlock.maxStackSize = maxStackSize;          addSuccessor(stackSize, label);          currentBlock = null;        }      } else if (opcode == Constants.JSR) {        if (currentBlock != null) {          addSuccessor(stackSize + 1, label);        }      } else {        // updates current stack size (max stack size unchanged because stack        // size variation always negative in this case)        stackSize += SIZE[opcode];        if (currentBlock != null) {          addSuccessor(stackSize, label);        }      }    }    // adds the instruction to the bytecode of the method    if (label.resolved && label.position - code.length < Short.MIN_VALUE) {      // case of a backward jump with an offset < -32768. In this case we      // automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx <l>      // with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the "opposite" opcode      // of IFxxx (i.e., IFNE for IFEQ) and where <l'> designates the      // instruction just after the GOTO_W.      if (opcode == Constants.GOTO) {        code.put1(200); // GOTO_W      } else if (opcode == Constants.JSR) {        code.put1(201); // JSR_W      } else {        code.put1(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1);        code.put2(8);   // jump offset        code.put1(200); // GOTO_W      }      label.put(this, code, code.length - 1, true);    } else {      // case of a backward jump with an offset >= -32768, or of a forward jump      // with, of course, an unknown offset. In these cases we store the offset      // in 2 bytes (which will be increased in resizeInstructions, if needed).      code.put1(opcode);      label.put(this, code, code.length - 1, false);    }  }  public void visitLabel (final Label label) {    if (CHECK) {      if (label.owner == null) {        label.owner = this;      } else if (label.owner != this) {        throw new IllegalArgumentException();      }    }    if (computeMaxs) {      if (currentBlock != null) {        // ends current block (with one new successor)        currentBlock.maxStackSize = maxStackSize;        addSuccessor(stackSize, label);      }      // begins a new current block,      // resets the relative current and max stack sizes      currentBlock = label;      stackSize = 0;      maxStackSize = 0;    }    // resolves previous forward references to label, if any    resize |= label.resolve(this, code.length, code.data);  }  public void visitLdcInsn (final Object cst) {    Item i = cw.newCst(cst);    if (computeMaxs) {      int size;      // computes the stack size variation      if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {        size = stackSize + 2;      } else {        size = stackSize + 1;      }      // updates current and max stack sizes      if (size > maxStackSize) {        maxStackSize = size;      }      stackSize = size;    }    // adds the instruction to the bytecode of the method    int index = i.index;    if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {      code.put12(20 /*LDC2_W*/, index);    } else if (index >= 256) {      code.put12(19 /*LDC_W*/, index);    } else {      code.put11(Constants.LDC, index);    }  }  public void visitIincInsn (final int var, final int increment) {    if (computeMaxs) {      // updates max locals only (no stack change)      int n = var + 1;      if (n > maxLocals) {        maxLocals = n;      }    }    // adds the instruction to the bytecode of the method    if ((var > 255) || (increment > 127) || (increment < -128)) {      code.put1(196 /*WIDE*/).put12(Constants.IINC, var).put2(increment);    } else {      code.put1(Constants.IINC).put11(var, increment);    }  }  public void visitTableSwitchInsn (    final int min,    final int max,    final Label dflt,    final Label labels[])  {    if (computeMaxs) {      // updates current stack size (max stack size unchanged)      --stackSize;      // ends current block (with many new successors)      if (currentBlock != null) {        currentBlock.maxStackSize = maxStackSize;        addSuccessor(stackSize, dflt);        for (int i = 0; i < labels.length; ++i) {          addSuccessor(stackSize, labels[i]);        }        currentBlock = null;      }    }    // adds the instruction to the bytecode of the method    int source = code.length;    code.put1(Constants.TABLESWITCH);    while (code.length % 4 != 0) {      code.put1(0);    }    dflt.put(this, code, source, true);    code.put4(min).put4(max);    for (int i = 0; i < labels.length; ++i) {

⌨️ 快捷键说明

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