Esempio n. 1
0
  /**
   * Get a <code>Local</code> instance to represent a value of a given type that will be
   * stored/loaded to/from a given local variable.
   *
   * @param type the type of the value
   * @param index the index of the local variable
   * @param isParameter true if the local is a parameter
   * @return the variable at index <code>index</code> in which values of type <code>type</code> are
   *     stored
   */
  private Local allocateLocalPrim(Klass type, int index, boolean isParameter) {
    Assert.that(localTypes.length < 0xFFFF);
    Assert.that(
        index >= 0 && index < localTypes.length,
        "index=" + index + " localTypes.length=" + localTypes.length);

    Klass localType = getLocalTypeFor(type);

    int key = localType.getSuiteID();

    /* We need a hard partition between uses of a slot as a reference vs. an Address, Offset, or UWord.
     * The partitioning of java primitives and objects is accomplished not only by the type passed in here, but
     * by the bytecode verifier. We can't be sure that some bytecodes are refering to the same local variable
     * as both a reference and as a Squawk primitive. Without that kind of support we are conservative here
     * and force a clash whenever javac uses the same local index for a reference and a Squawk primitive.
     */
    if (localType.isSquawkPrimitive()) {
      key = Klass.REFERENCE.getSuiteID();
    }
    key = key << 16 | index;
    if (localValues == null) {
      localValues = new IntHashtable();
    }
    Local local = (Local) localValues.get(key);
    if (local == null) {
      local = new Local(localType, index, isParameter);
      localValues.put(key, local);
    }

    /*
     * Ensure that the original class file does not use the same local variable
     * for both a Squawk primitive value and any other reference value. This prevents the
     * translator from having to do a complete liveness analysis to de-multiplex
     * such a local variable slot. Such de-multiplexing is required as Squawk primitives
     * are 'magically' translated into integers (or longs on a 64 bit system).
     */
    if (localType.isSquawkPrimitive() || local.getType().isSquawkPrimitive()) {
      if (localType != local.getType()) {
        throw codeParser.verifyError(
            getBadAddressLocalVariableMessage(index, localType, local.getType()));
      }
    }

    // System.out.println("allocated: "+local+" index "+index);
    /// *if[SCOPEDLOCALVARIABLES]*/
    codeParser.localVariableAllocated(codeParser.getCurrentIP(), local);
    /// *end[SCOPEDLOCALVARIABLES]*/
    return local;
  }
Esempio n. 2
0
 /**
  * Emulates the storing of a value to a local variable.
  *
  * @param index the index of the local variable being stored to
  * @param type the type of the value
  * @param local the variable to which the value is stored
  */
 public void store(int index, Klass type, Local local) {
   Klass localType = local.getType();
   Assert.that(localType.isAssignableFrom(type) || localType == getLocalTypeFor(type));
   verifyLocalVariableIndex(localType, index);
   localTypes[index] = type;
   if (localType.isDoubleWord()) {
     localTypes[index + 1] = Klass.getSecondWordType(localType);
   } else {
     verifyUseOfSquawkPrimitive(localType, type);
   }
 }
Esempio n. 3
0
  /**
   * Creates a Frame instance to emulate and verify the execution of a single class file method.
   *
   * @param codeParser the parser used to parse the "Code" attribute of the method being emulated
   * @param extraLocals the number of extra local variables needed
   */
  public Frame(CodeParser codeParser, int extraLocals) {
    this.maxStack = codeParser.getMaxStack();
    this.codeParser = codeParser;

    /*
     * Initialize the operand stack
     */
    stack = new StackProducer[maxStack];

    /*
     * Initialize the types in the local variables
     */
    localTypes = new Klass[codeParser.getMaxLocals() + extraLocals];
    Method method = codeParser.getMethod();
    Klass[] parameterTypes = method.getParameterTypes();
    Local[] parameterLocals = null;
    if (Translator.REVERSE_PARAMETERS && method.isInterpreterInvoked()) {
      parameterLocals = new Local[parameterTypes.length];
    }
    int javacIndex = 0;

    /*
     * Initialize 'this' in non-static methods. The type of 'this' is
     * UNINITIALIZED_THIS if this method is a constructor in any class
     * except java.lang.Object otherwise it is the class in which the
     * method was defined.
     */
    if (!method.isStatic() || method.isConstructor()) {
      Assert.that(parameterLocals == null);
      Klass thisType = method.getDefiningClass();
      if (method.isConstructor() && thisType != Klass.OBJECT) {
        thisType = Klass.UNINITIALIZED_THIS;
      }
      Local thisLocal = allocateParameter(thisType, javacIndex);
      store(javacIndex, thisType, thisLocal);
      javacIndex++;
    }

    /*
     * Initialize locals for the parameters.
     */
    int parameterIndex = javacIndex;
    for (int i = 0; i < parameterTypes.length; i++) {
      Klass parameterType = parameterTypes[i];
      Local parameterLocal = allocateParameter(parameterType, javacIndex);
      if (parameterLocals != null) {
        parameterLocals[i] = parameterLocal;
      }
      if (Klass.SQUAWK_64) {
        if (javacIndex != parameterIndex) {
          Assert.that(parameterIndex < javacIndex);
          parameterLocal.setParameterIndex(parameterIndex);
        }
        parameterIndex++;
      }
      store(javacIndex, parameterType, parameterLocal);
      javacIndex += (parameterType.isDoubleWord() ? 2 : 1);
    }
    parameterLocalsCount = javacIndex;

    /*
     * Adjust the parameter offsets for parameter order reversal.
     */
    if (parameterLocals != null) {
      parameterIndex = 0;
      for (int i = parameterTypes.length - 1; i >= 0; i--) {
        Klass parameterType = parameterTypes[i];
        parameterLocals[i].setParameterIndex(parameterIndex++);
        if (!Klass.SQUAWK_64 && parameterType.isDoubleWord()) {
          parameterIndex++;
        }
      }
    }

    /*
     * Initialize the remaining local variables to the TOP type
     */
    while (javacIndex < localTypes.length) {
      localTypes[javacIndex++] = Klass.TOP;
    }
  }