Example #1
0
 /**
  * Gets the type of a local variable that is used to store a value of a given class. This method
  * partitions all classes into one of the following categories:
  *
  * <p>
  *
  * <blockquote>
  *
  * <pre>
  *
  *     Local Variable Type  |  Types
  *     ---------------------+-------
  *     INT                  | boolean, byte, short, int
  *     FLOAT                | float
  *     LONG                 | long
  *     DOUBLE               | double
  *     ADDRESS              | Address
  *     UWORD                | UWord
  *     OFFSET               | Offset
  *     REFERENCE            | types in java.lang.Object hierarchy
  *
  * </pre>
  *
  * </blockquote>
  *
  * <p>
  *
  * @param type the type of a value that will be stored in a local variable
  * @return the local variable type for storing values of type <code>type</code>
  */
 public static Klass getLocalTypeFor(Klass type) {
   switch (type.getSystemID()) {
     case CID.BOOLEAN:
     case CID.BYTE:
     case CID.SHORT:
     case CID.CHAR:
     case CID.INT:
       {
         return Klass.INT;
       }
     case CID.FLOAT:
     case CID.LONG:
     case CID.DOUBLE:
       {
         return type;
       }
     case CID.UWORD:
     case CID.OFFSET:
     case CID.ADDRESS:
       {
         return type;
       }
     default:
       {
         Assert.that(Klass.REFERENCE.isAssignableFrom(type));
         return Klass.REFERENCE;
       }
   }
 }
Example #2
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;
  }