Esempio n. 1
0
  /** Loads the code of the method. */
  protected Instruction[] loadCode(Method m) {
    Code c = m.getCode();

    if (c == null) {
      return null;
    }

    InstructionList il = new InstructionList(c.getCode());
    InstructionHandle[] hs = il.getInstructionHandles();
    int length = hs.length;
    Instruction[] is = new Instruction[length];

    for (int i = 0; i < length; i++) {
      is[i] = insnFactory.createAndInitialize(this, hs[i], i, m.getConstantPool());

      if (c.getLineNumberTable() != null) {
        // annoying bug when BCEL don't seem to find linenumber - pos match
        // also sometimes linenumber tables are not available
        is[i].setContext(
            ci.getName(),
            name,
            c.getLineNumberTable().getSourceLine(is[i].getPosition()),
            is[i].getPosition());
      }
    }

    return is;
  }
Esempio n. 2
0
 public Instruction createInstructionGetfield(Element inst) throws IllegalXMLVMException {
   String classType = inst.getAttributeValue("class-type");
   String field = inst.getAttributeValue("field");
   String type = inst.getAttributeValue("type");
   Type t = parseTypeString(type);
   return _factory.createGetField(classType, field, t);
 }
  /** Marks the code starting at the given offset. */
  private void markCode(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset) {
    boolean oldNext = next;

    byte[] code = codeAttribute.code;

    // Continue with the current instruction as long as we haven't marked it
    // yet.
    while (!isReachable[offset]) {
      // Get the current instruction.
      Instruction instruction = InstructionFactory.create(code, offset);

      // Mark it as reachable.
      isReachable[offset] = true;

      // By default, we'll assume we can continue with the next
      // instruction in a moment.
      next = true;

      // Mark the branch targets, if any.
      instruction.accept(clazz, method, codeAttribute, offset, this);

      // Can we really continue with the next instruction?
      if (!next) {
        break;
      }

      // Go to the next instruction.
      offset += instruction.length(offset);
    }

    next = oldNext;
  }
Esempio n. 4
0
 private Instruction createInvokeInstruction(Element inst, short kind)
     throws IllegalXMLVMException {
   String classType = inst.getAttributeValue("class-type");
   String methodName = inst.getAttributeValue("method");
   Element signature = inst.getChild("signature", nsXMLVM);
   Type retType = collectReturnType(signature);
   Type[] argTypes = collectArgumentTypes(signature);
   return _factory.createInvoke(classType, methodName, retType, argTypes, kind);
 }
Esempio n. 5
0
  protected MethodInfo createCallStub(String originator, int id) {
    MethodInfo mi = new MethodInfo(id);
    String cname = ci.getName();
    Instruction insn;

    mi.name =
        originator
            + name; // + cname; // could maybe also include the called method, but keep it fast
    mi.signature = "()V";
    mi.maxLocals = isStatic() ? 0 : 1;
    mi.maxStack = getNumberOfCallerStackSlots(); // <2do> cache for optimization
    mi.localVariableNames = EMPTY;
    mi.localVariableTypes = EMPTY;
    mi.lineNumbers = null;
    mi.exceptions = null;
    mi.thrownExceptionClassNames = null;
    mi.uniqueName = mi.name;

    // createAndInitialize the code
    CodeBuilder cb = mi.getCodeBuilder();

    if (isStatic()) {
      mi.modifiers |= Modifier.STATIC;

      if (isClinit()) {
        insn = insnFactory.create(null, INVOKECLINIT.OPCODE);
      } else {
        insn = insnFactory.create(null, Constants.INVOKESTATIC);
      }
    } else if (name.equals("<init>")) {
      insn = insnFactory.create(null, Constants.INVOKESPECIAL);
    } else {
      insn = insnFactory.create(null, Constants.INVOKEVIRTUAL);
    }
    ((InvokeInstruction) insn).setInvokedMethod(cname, name, signature);
    cb.append(insn);

    insn = insnFactory.create(null, Constants.RETURN);
    cb.append(insn);

    cb.setCode();

    return mi;
  }
Esempio n. 6
0
  public void visitExceptionInfo(
      Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) {
    int startPC = Math.max(exceptionInfo.u2startPC, clipStart);
    int endPC = Math.min(exceptionInfo.u2endPC, clipEnd);
    int handlerPC = exceptionInfo.u2handlerPC;
    int catchType = exceptionInfo.u2catchType;

    // Exclude any subroutine invocations that jump out of the try block,
    // by adding a try block before (and later on, after) each invocation.
    for (int offset = startPC; offset < endPC; offset++) {
      if (branchTargetFinder.isSubroutineInvocation(offset)) {
        Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
        int instructionLength = instruction.length(offset);

        // Is it a subroutine invocation?
        if (!exceptionInfo.isApplicable(offset + ((BranchInstruction) instruction).branchOffset)) {
          if (DEBUG) {
            System.out.println(
                "  Appending extra exception [" + startPC + " -> " + offset + "] -> " + handlerPC);
          }

          // Append a try block that ends before the subroutine invocation.
          codeAttributeComposer.appendException(
              new ExceptionInfo(startPC, offset, handlerPC, catchType));

          // The next try block will start after the subroutine invocation.
          startPC = offset + instructionLength;
        }
      }
    }

    if (DEBUG) {
      System.out.println(
          "  Appending exception [" + startPC + " -> " + endPC + "] -> " + handlerPC);
    }

    // Append the exception. Note that exceptions with empty try blocks
    // are automatically ignored.
    codeAttributeComposer.appendException(new ExceptionInfo(startPC, endPC, handlerPC, catchType));
  }
Esempio n. 7
0
  public void visitBranchInstruction(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      BranchInstruction branchInstruction) {
    // Check if the instruction is an unconditional goto instruction.
    byte opcode = branchInstruction.opcode;
    if (opcode == InstructionConstants.OP_GOTO || opcode == InstructionConstants.OP_GOTO_W) {
      // Check if the goto instruction points to another simple goto
      // instruction.
      int branchOffset = branchInstruction.branchOffset;
      int targetOffset = offset + branchOffset;

      if (branchOffset != branchInstruction.length(offset)
          && !codeAttributeEditor.isModified(offset)
          && !codeAttributeEditor.isModified(targetOffset)) {
        Instruction targetInstruction = InstructionFactory.create(codeAttribute.code, targetOffset);

        if (targetInstruction.opcode == InstructionConstants.OP_GOTO) {
          // Simplify the goto instruction.
          int targetBranchOffset = ((BranchInstruction) targetInstruction).branchOffset;

          Instruction newBranchInstruction =
              new BranchInstruction(opcode, (branchOffset + targetBranchOffset));
          codeAttributeEditor.replaceInstruction(offset, newBranchInstruction);

          // Visit the instruction, if required.
          if (extraInstructionVisitor != null) {
            extraInstructionVisitor.visitBranchInstruction(
                clazz, method, codeAttribute, offset, branchInstruction);
          }
        }
      }
    }
  }
Esempio n. 8
0
  public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) {
    //        DEBUG =
    //            clazz.getName().equals("abc/Def") &&
    //            method.getName(clazz).equals("abc");

    if (DEBUG) {
      method.accept(clazz, new ClassPrinter());
    }

    branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);

    // Don't bother if there aren't any subroutines anyway.
    if (!containsSubroutines(codeAttribute)) {
      return;
    }

    if (DEBUG) {
      System.out.println(
          "SubroutineInliner: processing ["
              + clazz.getName()
              + "."
              + method.getName(clazz)
              + method.getDescriptor(clazz)
              + "]");
    }

    // Append the body of the code.
    codeAttributeComposer.reset();
    codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);

    // Copy the non-subroutine instructions.
    int offset = 0;
    while (offset < codeAttribute.u4codeLength) {
      Instruction instruction = InstructionFactory.create(codeAttribute.code, offset);
      int instructionLength = instruction.length(offset);

      // Is this returning subroutine?
      if (branchTargetFinder.isSubroutine(offset)
          && branchTargetFinder.isSubroutineReturning(offset)) {
        // Skip the subroutine.
        if (DEBUG) {
          System.out.println(
              "  Skipping original subroutine instruction " + instruction.toString(offset));
        }

        // Append a label at this offset instead.
        codeAttributeComposer.appendLabel(offset);
      } else {
        // Copy the instruction, inlining any subroutine call recursively.
        instruction.accept(clazz, method, codeAttribute, offset, this);
      }

      offset += instructionLength;
    }

    // Copy the exceptions. Note that exceptions with empty try blocks
    // are automatically removed.
    codeAttribute.exceptionsAccept(clazz, method, subroutineExceptionInliner);

    if (DEBUG) {
      System.out.println("  Appending label after code at [" + offset + "]");
    }

    // Append a label just after the code.
    codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);

    // End and update the code attribute.
    codeAttributeComposer.endCodeFragment();
    codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);

    if (DEBUG) {
      method.accept(clazz, new ClassPrinter());
    }
  }
Esempio n. 9
0
 public Instruction createInstructionNew(Element inst) {
   String t = inst.getAttributeValue("type");
   return _factory.createNew(t);
 }
Esempio n. 10
0
 public Instruction createInstructionAload(Element inst) throws IllegalXMLVMException {
   String t = inst.getAttributeValue("type");
   Type type = parseTypeString(t);
   int idx = Integer.parseInt(inst.getAttributeValue("index"));
   return _factory.createLoad(type, idx);
 }
Esempio n. 11
0
 public Instruction createInstructionLreturn(Element inst) {
   return _factory.createReturn(Type.LONG);
 }
Esempio n. 12
0
 public Instruction createInstructionFreturn(Element inst) {
   return _factory.createReturn(Type.FLOAT);
 }
Esempio n. 13
0
 public Instruction createInstructionDreturn(Element inst) {
   return _factory.createReturn(Type.DOUBLE);
 }
Esempio n. 14
0
 public Instruction createInstructionIreturn(Element inst) {
   return _factory.createReturn(Type.INT);
 }
Esempio n. 15
0
 public Instruction createInstructionReturn(Element inst) {
   return _factory.createReturn(Type.VOID);
 }
  /**
   * Evaluates a block of instructions that hasn't been handled before, starting at the given offset
   * and ending at a branch instruction, a return instruction, or a throw instruction. Branch
   * instructions are handled recursively.
   */
  private void evaluateInstructionBlock(
      Clazz clazz, Method method, CodeAttribute codeAttribute, int instructionOffset) {
    if (DEBUG) {
      if (evaluated[instructionOffset]) {
        System.out.println("-- (instruction block at " + instructionOffset + " already evaluated)");
      } else {
        System.out.println("-- instruction block:");
      }
    }

    // Remember the initial stack size.
    int initialStackSize = stackSize;

    // Remember the maximum stack size.
    if (maxStackSize < stackSize) {
      maxStackSize = stackSize;
    }

    // Evaluate any instructions that haven't been evaluated before.
    while (!evaluated[instructionOffset]) {
      // Mark the instruction as evaluated.
      evaluated[instructionOffset] = true;

      Instruction instruction = InstructionFactory.create(codeAttribute.code, instructionOffset);

      if (DEBUG) {
        int stackPushCount = instruction.stackPushCount(clazz);
        int stackPopCount = instruction.stackPopCount(clazz);
        System.out.println(
            "["
                + instructionOffset
                + "]: "
                + stackSize
                + " - "
                + stackPopCount
                + " + "
                + stackPushCount
                + " = "
                + (stackSize + stackPushCount - stackPopCount)
                + ": "
                + instruction.toString(instructionOffset));
      }

      // Compute the instruction's effect on the stack size.
      stackSize -= instruction.stackPopCount(clazz);

      if (stackSize < 0) {
        throw new IllegalArgumentException(
            "Stack size becomes negative after instruction "
                + instruction.toString(instructionOffset)
                + " in ["
                + clazz.getName()
                + "."
                + method.getName(clazz)
                + method.getDescriptor(clazz)
                + "]");
      }

      stackSizes[instructionOffset] = stackSize += instruction.stackPushCount(clazz);

      // Remember the maximum stack size.
      if (maxStackSize < stackSize) {
        maxStackSize = stackSize;
      }

      // Remember the next instruction offset.
      int nextInstructionOffset = instructionOffset + instruction.length(instructionOffset);

      // Visit the instruction, in order to handle branches.
      instruction.accept(clazz, method, codeAttribute, instructionOffset, this);

      // Stop evaluating after a branch.
      if (exitInstructionBlock) {
        break;
      }

      // Continue with the next instruction.
      instructionOffset = nextInstructionOffset;

      if (DEBUG) {
        if (evaluated[instructionOffset]) {
          System.out.println("-- (instruction at " + instructionOffset + " already evaluated)");
        }
      }
    }

    // Restore the stack size for possible subsequent instruction blocks.
    this.stackSize = initialStackSize;
  }
Esempio n. 17
0
 public Instruction createInstructionGetstatic(Element inst) throws IllegalXMLVMException {
   String classType = inst.getAttributeValue("class-type");
   String field = inst.getAttributeValue("field");
   Type type = parseTypeString(inst.getAttributeValue("type"));
   return _factory.createFieldAccess(classType, field, type, Constants.GETSTATIC);
 }