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

📄 codewriter.java

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
      } 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 (itf) {
      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.putByte(200); // GOTO_W
      } else if (opcode == Constants.JSR) {
        code.putByte(201); // JSR_W
      } else {
        code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1);
        code.putShort(8);   // jump offset
        code.putByte(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.putByte(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.newConstItem(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.putByte(196 /*WIDE*/).put12(Constants.IINC, var).putShort(increment);
    } else {
      code.putByte(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.putByte(Constants.TABLESWITCH);
    while (code.length % 4 != 0) {
      code.putByte(0);
    }
    dflt.put(this, code, source, true);
    code.putInt(min).putInt(max);
    for (int i = 0; i < labels.length; ++i) {
      labels[i].put(this, code, source, true);
    }
  }

  public void visitLookupSwitchInsn (
    final Label dflt,
    final int keys[],
    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.putByte(Constants.LOOKUPSWITCH);
    while (code.length % 4 != 0) {
      code.putByte(0);
    }
    dflt.put(this, code, source, true);
    code.putInt(labels.length);
    for (int i = 0; i < labels.length; ++i) {
      code.putInt(keys[i]);
      labels[i].put(this, code, source, true);
    }
  }

  public void visitMultiANewArrayInsn (final String desc, final int dims) {
    if (computeMaxs) {
      // updates current stack size (max stack size unchanged because stack
      // size variation always negative or null)
      stackSize += 1 - dims;
    }
    // adds the instruction to the bytecode of the method
    code.put12(Constants.MULTIANEWARRAY, cw.newClass(desc)).putByte(dims);
  }

  public void visitTryCatchBlock (
    final Label start,
    final Label end,
    final Label handler,
    final String type)
  {
    if (CHECK) {
      if (start.owner != this || end.owner != this || handler.owner != this) {
        throw new IllegalArgumentException();
      }
      if (!start.resolved || !end.resolved || !handler.resolved) {
        throw new IllegalArgumentException();
      }
    }
    if (computeMaxs) {
      // pushes handler block onto the stack of blocks to be visited
      if (!handler.pushed) {
        handler.beginStackSize = 1;
        handler.pushed = true;
        handler.next = blockStack;
        blockStack = handler;
      }
    }
    ++catchCount;
    if (catchTable == null) {
      catchTable = new ByteVector();
    }
    catchTable.putShort(start.position);
    catchTable.putShort(end.position);
    catchTable.putShort(handler.position);
    catchTable.putShort(type != null ? cw.newClass(type) : 0);
  }

  public void visitMaxs (final int maxStack, final int maxLocals) {
    if (computeMaxs) {
      // true (non relative) max stack size
      int max = 0;
      // control flow analysis algorithm: while the block stack is not empty,
      // pop a block from this stack, update the max stack size, compute
      // the true (non relative) begin stack size of the successors of this
      // block, and push these successors onto the stack (unless they have
      // already been pushed onto the stack). Note: by hypothesis, the {@link
      // Label#beginStackSize} of the blocks in the block stack are the true
      // (non relative) beginning stack sizes of these blocks.
      Label stack = blockStack;
      while (stack != null) {
        // pops a block from the stack
        Label l = stack;
        stack = stack.next;
        // computes the true (non relative) max stack size of this block
        int start = l.beginStackSize;
        int blockMax = start + l.maxStackSize;
        // updates the global max stack size
        if (blockMax > max) {
          max = blockMax;
        }
        // analyses the successors of the block
        Edge b = l.successors;
        while (b != null) {
          l = b.successor;
          // if this successor has not already been pushed onto the stack...
          if (!l.pushed) {
            // computes the true beginning stack size of this successor block
            l.beginStackSize = start + b.stackSize;
            // pushes this successor onto the stack
            l.pushed = true;
            l.next = stack;
            stack = l;
          }
          b = b.next;
        }
      }
      this.maxStack = max;
      // releases all the Edge objects used by this CodeWriter
      synchronized (SIZE) {
        // appends the [head ... tail] list at the beginning of the pool list
        if (tail != null) {
          tail.poolNext = pool;
          pool = head;
        }
      }
    } else {
      this.maxStack = maxStack;
      this.maxLocals = maxLocals;
    }
  }

  public void visitLocalVariable (
    final String name,
    final String desc,
    final Label start,
    final Label end,
    final int index)
  {
    if (CHECK) {
      if (start.owner != this || !start.resolved) {
        throw new IllegalArgumentException();
      }
      if (end.owner != this || !end.resolved) {
        throw new IllegalArgumentException();
      }
    }
    if (localVar == null) {
      cw.newUTF8("LocalVariableTable");
      localVar = new ByteVector();
    }
    ++localVarCount;
    localVar.putShort(start.position);
    localVar.putShort(end.position - start.position);
    localVar.putShort(cw.newUTF8(name));
    localVar.putShort(cw.newUTF8(desc));
    localVar.putShort(index);
  }

  public void visitLineNumber (final int line, final Label start) {
    if (CHECK) {
      if (start.owner != this || !start.resolved) {
        throw new IllegalArgumentException();
      }
    }
    if (lineNumber == null) {
      cw.newUTF8("LineNumberTable");
      lineNumber = new ByteVector();
    }
    ++lineNumberCount;
    lineNumber.putShort(start.position);
    lineNumber.putShort(line);
  }

  public void visitAttribute (final Attribute attr) {
    attr.next = cattrs;
    cattrs = attr;
  }

  // --------------------------------------------------------------------------
  // Utility methods: control flow analysis algorithm
  // --------------------------------------------------------------------------

  /**
   * Computes the size of the arguments and of the return value of a method.
   *
   * @param desc the descriptor of a method.
   * @return the size of the arguments of the method (plus one for the implicit
   *      this argument), argSize, and the size of its return value, retSize,
   *      packed into a single int i = <tt>(argSize << 2) | retSize</tt>
   *      (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to

⌨️ 快捷键说明

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