Esempio n. 1
0
  /**
   * Pops a value off the operand stack.
   *
   * @param type the type that the value popped off the operand stack must be assignable to
   * @return the instruction that produced the popped value
   */
  public StackProducer pop(Klass type) {
    StackProducer producer;
    if (type.isDoubleWord()) {
      if (sp < 2) {
        throw codeParser.verifyError("operand stack underflow");
      }
      if (!isTopDoubleWord()) {
        throw codeParser.verifyError("incompatible type on operand stack " + tosKlassName());
      }
      sp -= 2;
      producer = stack[sp];
    } else {
      if (sp < 1) {
        throw codeParser.verifyError("operand stack underflow");
      }
      if (isTopDoubleWord()) {
        throw codeParser.verifyError("incompatible type on operand stack " + tosKlassName());
      }
      producer = stack[--sp];

      /*
       * The primitive one-word, non-float types are all assignment compatible with each other
       */
      if (type.isPrimitive() && type != Klass.FLOAT) {

        type = Klass.INT;
      }
    }

    Assert.that(producer != null);

    /*
     * Interfaces are treated as java.lang.Object in the verifier.
     */
    if (type.isInterface()) {
      type = Klass.OBJECT;
    }

    /*
     * Verify that the instruction is producing the correct type.
     */
    if (!type.isAssignableFrom(producer.getType())) {
      throw codeParser.verifyError(
          "incompatible type: '" + type + "' is not assignable from '" + producer.getType() + "'");
    }

    return producer;
  }
Esempio n. 2
0
 /**
  * Returns the internal name of the top type on the stack.
  *
  * @return the name
  */
 private String tosKlassName() {
   StackProducer top = stack[sp - (isTopDoubleWord() ? 2 : 1)];
   if (top == null) {
     return "null";
   }
   return top.getType().getInternalName();
 }
Esempio n. 3
0
 /**
  * Changes the type of any object in a local variable or on the operand stack whose current type
  * is matches <code>fromType</code> to be <code>toType</code>.
  */
 public void replaceTypeWithType(Klass fromType, Klass toType) {
   for (int i = 0; i < localTypes.length; i++) {
     if (localTypes[i] == fromType) {
       localTypes[i] = toType;
     }
   }
   for (int i = 0; i < sp; i++) {
     StackProducer producer = stack[i];
     if (producer != null && producer.getType() == fromType) {
       producer.updateType(toType);
     }
   }
 }
Esempio n. 4
0
 /**
  * Determines if the operand stack or local variable array currently contains an entry whose type
  * is equal to or a subtype of a given type.
  *
  * @param type the type to search for
  * @return true if an entry was found
  */
 public boolean containsType(Klass type) {
   for (int i = 0; i < localTypes.length; i++) {
     if (type.isAssignableFrom(localTypes[i])) {
       return true;
     }
   }
   for (int i = 0; i < sp; i++) {
     StackProducer producer = stack[i];
     if (producer != null && type.isAssignableFrom(producer.getType())) {
       return true;
     }
   }
   return false;
 }
Esempio n. 5
0
  /**
   * Pushes a value to the operand stack.
   *
   * @param producer the instruction producing the value being pushed
   */
  public void push(StackProducer producer) {
    Klass type = producer.getType();
    Assert.that(type != Klass.VOID);

    /*
     * Check for overflow and push the producer.
     */
    if (sp == maxStack) {
      throw codeParser.verifyError("operand stack overflow");
    }
    stack[sp++] = producer;

    /*
     * For long and double check for overflow and then add a null word to the stack.
     */
    if (type.isDoubleWord()) {
      if (sp == maxStack) {
        throw codeParser.verifyError("operand stack overflow");
      }
      stack[sp++] = null;
    }
  }
Esempio n. 6
0
 /**
  * Allocate local that is used for spilling.
  *
  * @param producer the instruction producing the value that needs to be spilled
  * @return a unique local to be used to hold the value
  */
 public Local allocateLocalForSpill(StackProducer producer) {
   Klass type = getLocalTypeFor(producer.getType());
   return new Local(type, --nextSpillLocalId, false);
 }