/** * 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; } } }
/** * 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; }