Adds autoboxing to the compiler.  Also some 1.5 cleanup.

Patch by: bruce
Review by: scottb

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1454 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JForStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JForStatement.java
index 9d8ec20..c485166 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JForStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JForStatement.java
@@ -25,13 +25,13 @@
 public class JForStatement extends JStatement {
 
   private JStatement body;
-  private final List/* <JExpressionStatement> */increments;
-  private final List/* <JStatement> */initializers;
+  private final List<JExpressionStatement> increments;
+  private final List<JStatement> initializers;
   private JExpression testExpr;
 
   public JForStatement(JProgram program, SourceInfo info,
-      List/* <JStatement> */initializers, JExpression testExpr,
-      List/* <JExpressionStatement> */increments, JStatement body) {
+      List<JStatement> initializers, JExpression testExpr,
+      List<JExpressionStatement> increments, JStatement body) {
     super(program, info);
     this.initializers = initializers;
     this.testExpr = testExpr;
@@ -43,11 +43,11 @@
     return body;
   }
 
-  public List/* <JExpressionStatement> */getIncrements() {
+  public List<JExpressionStatement> getIncrements() {
     return increments;
   }
 
-  public List/* <JStatement> */getInitializers() {
+  public List<JStatement> getInitializers() {
     return initializers;
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
index da9c632..7c382fa 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
@@ -24,8 +24,8 @@
  */
 public class JNewArray extends JExpression implements HasSettableType {
 
-  public ArrayList dims = null;
-  public ArrayList initializers = null;
+  public ArrayList<JExpression> dims = null;
+  public ArrayList<JExpression> initializers = null;
   private JArrayType arrayType;
 
   public JNewArray(JProgram program, SourceInfo info, JArrayType arrayType) {
@@ -44,14 +44,14 @@
   public boolean hasSideEffects() {
     if (initializers != null) {
       for (int i = 0, c = initializers.size(); i < c; ++i) {
-        if (((JExpression) initializers.get(i)).hasSideEffects()) {
+        if (initializers.get(i).hasSideEffects()) {
           return true;
         }
       }
     }
     if (dims != null) {
       for (int i = 0, c = dims.size(); i < c; ++i) {
-        if (((JExpression) dims.get(i)).hasSideEffects()) {
+        if (dims.get(i).hasSideEffects()) {
           return true;
         }
       }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
index d61e355..30a1c7e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
@@ -21,14 +21,16 @@
 public class JPrimitiveType extends JType {
 
   private final String signatureName;
+  private final String wrapperTypeName;
 
   /**
    * These are only supposed to be constructed by JProgram.
    */
   JPrimitiveType(JProgram program, String name, String signatureName,
-      JLiteral defaultValue) {
+      String wrapperTypeName, JLiteral defaultValue) {
     super(program, null, name, defaultValue);
     this.signatureName = signatureName;
+    this.wrapperTypeName = wrapperTypeName;
   }
 
   public String getJavahSignatureName() {
@@ -39,6 +41,10 @@
     return signatureName;
   }
 
+  public String getWrapperTypeName() {
+    return wrapperTypeName;
+  }
+
   public void traverse(JVisitor visitor, Context ctx) {
     if (visitor.visit(this, ctx)) {
     }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index 24abc11..e08cec5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -164,45 +164,45 @@
   private final Map<JMethod, JMethod> staticToInstanceMap = new IdentityHashMap<JMethod, JMethod>();
 
   private final JPrimitiveType typeBoolean = new JPrimitiveType(this,
-      "boolean", "Z", literalFalse);
+      "boolean", "Z", "java.lang.Boolean", literalFalse);
 
   private final JPrimitiveType typeByte = new JPrimitiveType(this, "byte", "B",
-      literalIntZero);
+      "java.lang.Byte", literalIntZero);
 
   private final JPrimitiveType typeChar = new JPrimitiveType(this, "char", "C",
-      getLiteralChar((char) 0));
+      "java.lang.Character", getLiteralChar((char) 0));
 
   private JClassType typeClass;
 
   private final JPrimitiveType typeDouble = new JPrimitiveType(this, "double",
-      "D", getLiteralDouble(0));
+      "D", "java.lang.Double", getLiteralDouble(0));
 
   private final JPrimitiveType typeFloat = new JPrimitiveType(this, "float",
-      "F", getLiteralFloat(0));
+      "F", "java.lang.Float", getLiteralFloat(0));
 
   private Map<JClassType, Integer> typeIdMap = new HashMap<JClassType, Integer>();
 
   private final JPrimitiveType typeInt = new JPrimitiveType(this, "int", "I",
-      literalIntZero);
+      "java.lang.Integer", literalIntZero);
 
   private JClassType typeJavaLangObject;
 
   private final JPrimitiveType typeLong = new JPrimitiveType(this, "long", "J",
-      getLiteralLong(0));
+      "java.lang.Long", getLiteralLong(0));
 
   private final Map<String, JReferenceType> typeNameMap = new HashMap<String, JReferenceType>();
 
   private final JNullType typeNull = new JNullType(this);
 
   private final JPrimitiveType typeShort = new JPrimitiveType(this, "short",
-      "S", literalIntZero);
+      "S", "java.lang.Short", literalIntZero);
 
   private JClassType typeSpecialJavaScriptObject;
 
   private JClassType typeString;
 
   private final JPrimitiveType typeVoid = new JPrimitiveType(this, "void", "V",
-      null);
+      "java.lang.Void", null);
 
   public JProgram(TreeLogger logger, RebindOracle rebindOracle) {
     super(null, null);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTryStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTryStatement.java
index 23fff58..b7a41be 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTryStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTryStatement.java
@@ -24,14 +24,13 @@
  */
 public class JTryStatement extends JStatement {
 
-  private final List catchArgs;
-  private final List catchBlocks;
+  private final List<JLocalRef> catchArgs;
+  private final List<JBlock> catchBlocks;
   private final JBlock finallyBlock;
   private final JBlock tryBlock;
 
   public JTryStatement(JProgram program, SourceInfo info, JBlock tryBlock,
-      List/* <JLocalRef> */catchArgs, List/* <JBlock> */catchBlocks,
-      JBlock finallyBlock) {
+      List<JLocalRef> catchArgs, List<JBlock> catchBlocks, JBlock finallyBlock) {
     super(program, info);
     assert (catchArgs.size() == catchBlocks.size());
     this.tryBlock = tryBlock;
@@ -40,11 +39,11 @@
     this.finallyBlock = finallyBlock;
   }
 
-  public List getCatchArgs() {
+  public List<JLocalRef> getCatchArgs() {
     return catchArgs;
   }
 
-  public List/* <JBlock> */getCatchBlocks() {
+  public List<JBlock> getCatchBlocks() {
     return catchBlocks;
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodBody.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodBody.java
index 76ae212..ccc613f 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodBody.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodBody.java
@@ -30,9 +30,9 @@
  */
 public class JsniMethodBody extends JAbstractMethodBody {
 
-  public final List/* <JsniFieldRef> */jsniFieldRefs = new ArrayList/* <JsniFieldRef> */();
+  public final List<JsniFieldRef> jsniFieldRefs = new ArrayList<JsniFieldRef>();
 
-  public final List/* <JsniMethodRef> */jsniMethodRefs = new ArrayList/* <JsniMethodRef> */();
+  public final List<JsniMethodRef> jsniMethodRefs = new ArrayList<JsniMethodRef>();
 
   private JsFunction jsFunction = null;
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index f142783..83a5f0d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -471,7 +471,8 @@
             assert newMethod.getName().equals("values");
             // TODO: hack
             JMethodBody body = (JMethodBody) newMethod.getBody();
-            body.getStatements().add(new JReturnStatement(program, null, program.getLiteralNull()));
+            body.getStatements().add(
+                new JReturnStatement(program, null, program.getLiteralNull()));
           } else if (parameters.length == 1) {
             assert newMethod.getName().equals("valueOf");
             assert typeMap.get(parameters[0]) == program.getTypeJavaLangString();
@@ -479,7 +480,8 @@
                 program.getTypeJavaLangString(), true, newMethod);
             // TODO: hack
             JMethodBody body = (JMethodBody) newMethod.getBody();
-            body.getStatements().add(new JReturnStatement(program, null, program.getLiteralNull()));
+            body.getStatements().add(
+                new JReturnStatement(program, null, program.getLiteralNull()));
           } else {
             assert false;
           }
@@ -538,7 +540,7 @@
       String syntheticFnHeader = "function (";
       boolean first = true;
       for (int i = 0; i < newMethod.params.size(); ++i) {
-        JParameter param = (JParameter) newMethod.params.get(i);
+        JParameter param = newMethod.params.get(i);
         if (first) {
           first = false;
         } else {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index 61e4f84..e9ffc37 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -38,6 +38,7 @@
 import com.google.gwt.dev.jjs.ast.JDoubleLiteral;
 import com.google.gwt.dev.jjs.ast.JEnumField;
 import com.google.gwt.dev.jjs.ast.JExpression;
+import com.google.gwt.dev.jjs.ast.JExpressionStatement;
 import com.google.gwt.dev.jjs.ast.JField;
 import com.google.gwt.dev.jjs.ast.JFieldRef;
 import com.google.gwt.dev.jjs.ast.JFloatLiteral;
@@ -62,6 +63,7 @@
 import com.google.gwt.dev.jjs.ast.JParameterRef;
 import com.google.gwt.dev.jjs.ast.JPostfixOperation;
 import com.google.gwt.dev.jjs.ast.JPrefixOperation;
+import com.google.gwt.dev.jjs.ast.JPrimitiveType;
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JReferenceType;
 import com.google.gwt.dev.jjs.ast.JReturnStatement;
@@ -88,6 +90,7 @@
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
 import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
@@ -162,6 +165,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
 import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
@@ -211,7 +215,7 @@
       sb.append(method.getName());
       sb.append("(");
       for (int i = 0; i < method.getOriginalParamTypes().size(); ++i) {
-        JType type = (JType) method.getOriginalParamTypes().get(i);
+        JType type = method.getOriginalParamTypes().get(i);
         sb.append(type.getJsniSignatureName());
       }
       sb.append(")");
@@ -231,8 +235,6 @@
       return ice;
     }
 
-    private Object[] args = new Object[1];
-
     private JReferenceType currentClass;
 
     private ClassScope currentClassScope;
@@ -247,9 +249,7 @@
 
     private int[] currentSeparatorPositions;
 
-    private final Map/* <JMethod, Map<String, JLabel>> */labelMap = new IdentityHashMap();
-
-    private Class[] params = new Class[1];
+    private final Map<JMethod, Map<String, JLabel>> labelMap = new IdentityHashMap<JMethod, Map<String, JLabel>>();
 
     private final JProgram program;
 
@@ -261,8 +261,8 @@
     }
 
     /**
-     * We emulate static initializers and intance initializers as methods. As in
-     * other cases, this gives us: simpler AST, easier to optimize, more like
+     * We emulate static initializers and instance initializers as methods. As
+     * in other cases, this gives us: simpler AST, easier to optimize, more like
      * output JavaScript.
      */
     public void processType(TypeDeclaration x) {
@@ -281,8 +281,8 @@
          * this). Call super class $clinit; $clinit is always in position 0.
          */
         if (currentClass.extnds != null) {
-          JMethod myClinit = (JMethod) currentClass.methods.get(0);
-          JMethod superClinit = (JMethod) currentClass.extnds.methods.get(0);
+          JMethod myClinit = currentClass.methods.get(0);
+          JMethod superClinit = currentClass.extnds.methods.get(0);
           JMethodCall superClinitCall = new JMethodCall(program,
               myClinit.getSourceInfo(), null, superClinit);
           JMethodBody body = (JMethodBody) myClinit.getBody();
@@ -295,12 +295,12 @@
             FieldDeclaration fieldDeclaration = x.fields[i];
             if (fieldDeclaration.isStatic()) {
               // clinit
-              currentMethod = (JMethod) currentClass.methods.get(0);
+              currentMethod = currentClass.methods.get(0);
               currentMethodBody = (JMethodBody) currentMethod.getBody();
               currentMethodScope = x.staticInitializerScope;
             } else {
               // init
-              currentMethod = (JMethod) currentClass.methods.get(1);
+              currentMethod = currentClass.methods.get(1);
               currentMethodBody = (JMethodBody) currentMethod.getBody();
               currentMethodScope = x.initializerScope;
             }
@@ -350,10 +350,8 @@
       }
 
       try {
-        params[0] = child.getClass();
-        Method method = getClass().getDeclaredMethod(name, params);
-        args[0] = child;
-        return (JNode) method.invoke(this, args);
+        Method method = getClass().getDeclaredMethod(name, child.getClass());
+        return (JNode) method.invoke(this, child);
       } catch (Throwable e) {
         if (e instanceof InvocationTargetException) {
           e = ((InvocationTargetException) e).getTargetException();
@@ -372,11 +370,52 @@
        * don't have to write processExpression methods for the numerous JDT
        * literal nodes because they ALWAYS have a constant value.
        */
+      JExpression result = null;
       if (x != null && x.constant != null
           && x.constant != Constant.NotAConstant) {
-        return (JExpression) dispatch("processConstant", x.constant);
+        result = (JExpression) dispatch("processConstant", x.constant);
       }
-      return (JExpression) dispatch("processExpression", x);
+
+      if (result == null) {
+        // The expression was not a constant, so use the general logic.
+        result = (JExpression) dispatch("processExpression", x);
+      }
+
+      // Check if we need to box the resulting expression.
+      if (x != null) {
+        if ((x.implicitConversion & TypeIds.BOXING) != 0) {
+          /*
+           * Beware! Passing in "primitiveTypeToBox" seems unnecessary, but it
+           * isn't. You cannot determine the true type to box directly by
+           * calling result.getType() in all cases because sometimes, such as
+           * when the expression is originally a int literal prefixed with a
+           * narrowing cast, the processExpression() calls returns JIntLiterals
+           * even when the actual type should be byte or short. So, unless you
+           * remember what the original expression type was, you'd incorrectly
+           * box a byte as an Integer.
+           */
+          JType primitiveTypeToBox = (JType) typeMap.get(x.resolvedType);
+
+          if (!(primitiveTypeToBox instanceof JPrimitiveType)) {
+            throw new InternalCompilerException(result,
+                "Attempt to box a non-primitive type: "
+                    + primitiveTypeToBox.getName(), null);
+          }
+
+          result = box(result, (JPrimitiveType) primitiveTypeToBox);
+        } else if ((x.implicitConversion & TypeIds.UNBOXING) != 0) {
+
+          JType typeToUnbox = (JType) typeMap.get(x.resolvedType);
+          if (!(typeToUnbox instanceof JClassType)) {
+            throw new InternalCompilerException(result,
+                "Attempt to unbox a non-class type: " + typeToUnbox.getName(),
+                null);
+          }
+
+          result = unbox(result, (JClassType) typeToUnbox);
+        }
+      }
+      return result;
     }
 
     /**
@@ -486,11 +525,11 @@
         JClassType enclosingType = (JClassType) ctor.getEnclosingType();
 
         // Call clinit; $clinit is always in position 0.
-        JMethod clinitMethod = (JMethod) enclosingType.methods.get(0);
+        JMethod clinitMethod = enclosingType.methods.get(0);
         JMethodCall clinitCall = new JMethodCall(program, info, null,
             clinitMethod);
         JMethodBody body = (JMethodBody) ctor.getBody();
-        List statements = body.getStatements();
+        List<JStatement> statements = body.getStatements();
         statements.add(clinitCall.makeStatement());
 
         /*
@@ -501,12 +540,12 @@
         if (!hasExplicitThis) {
           ReferenceBinding declaringClass = x.binding.declaringClass;
           if (declaringClass instanceof NestedTypeBinding) {
-            Iterator/* <JParameter> */paramIt = getSyntheticsIterator(ctor);
+            Iterator<JParameter> paramIt = getSyntheticsIterator(ctor);
             NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
             if (nestedBinding.enclosingInstances != null) {
               for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
                 SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
-                JParameter param = (JParameter) paramIt.next();
+                JParameter param = paramIt.next();
                 if (arg.matchingField != null) {
                   JField field = (JField) typeMap.get(arg);
                   statements.add(program.createAssignmentStmt(info,
@@ -519,7 +558,7 @@
             if (nestedBinding.outerLocalVariables != null) {
               for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
                 SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
-                JParameter param = (JParameter) paramIt.next();
+                JParameter param = paramIt.next();
                 JField field = (JField) typeMap.get(arg);
                 statements.add(program.createAssignmentStmt(info,
                     createVariableRef(info, field), createVariableRef(info,
@@ -542,7 +581,7 @@
          */
         if (!hasExplicitThis) {
           // $init is always in position 1 (clinit is in 0)
-          JMethod initMethod = (JMethod) enclosingType.methods.get(1);
+          JMethod initMethod = enclosingType.methods.get(1);
           JMethodCall initCall = new JMethodCall(program, info, thisRef,
               initMethod);
           statements.add(initCall.makeStatement());
@@ -594,12 +633,12 @@
         int ctorArgc = ctor.params.size();
         JMethod targetMethod = null;
         outer : for (int j = 0; j < javaLangString.methods.size(); ++j) {
-          JMethod method = (JMethod) javaLangString.methods.get(j);
+          JMethod method = javaLangString.methods.get(j);
           if (method.getName().equals("_String")
               && method.params.size() == ctorArgc) {
             for (int i = 0; i < ctorArgc; ++i) {
-              JParameter mparam = (JParameter) method.params.get(i);
-              JParameter cparam = (JParameter) ctor.params.get(i);
+              JParameter mparam = method.params.get(i);
+              JParameter cparam = ctor.params.get(i);
               if (mparam.getType() != cparam.getType()) {
                 continue outer;
               }
@@ -664,17 +703,15 @@
       JNewArray newArray = new JNewArray(program, info, type);
 
       if (x.initializer != null) {
-        newArray.initializers = new ArrayList();
+        newArray.initializers = new ArrayList<JExpression>();
         if (x.initializer.expressions != null) {
-          for (int i = 0; i < x.initializer.expressions.length; i++) {
-            Expression expression = x.initializer.expressions[i];
+          for (Expression expression : x.initializer.expressions) {
             newArray.initializers.add(dispProcessExpression(expression));
           }
         }
       } else {
-        newArray.dims = new ArrayList();
-        for (int i = 0; i < x.dimensions.length; i++) {
-          Expression dimension = x.dimensions[i];
+        newArray.dims = new ArrayList<JExpression>();
+        for (Expression dimension : x.dimensions) {
           // can be null if index expression was empty
           if (dimension == null) {
             newArray.dims.add(program.getLiteralAbsentArrayDimension());
@@ -692,10 +729,9 @@
       JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
       JNewArray newArray = new JNewArray(program, info, type);
 
-      newArray.initializers = new ArrayList();
+      newArray.initializers = new ArrayList<JExpression>();
       if (x.expressions != null) {
-        for (int i = 0; i < x.expressions.length; i++) {
-          Expression expression = x.expressions[i];
+        for (Expression expression : x.expressions) {
           newArray.initializers.add(dispProcessExpression(expression));
         }
       }
@@ -720,7 +756,7 @@
     JExpression processExpression(BinaryExpression x) {
       JBinaryOperator op;
 
-      int binOp = (x.bits & BinaryExpression.OperatorMASK) >> BinaryExpression.OperatorSHIFT;
+      int binOp = (x.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
       switch (binOp) {
         case BinaryExpression.LEFT_SHIFT:
           op = JBinaryOperator.SHL;
@@ -922,7 +958,7 @@
           /*
            * In cases where JDT had to synthesize a this ref for us, it could
            * actually be the wrong type, if the target method is in an enclosing
-           * class. We have to sythensize our own ref of the correct type.
+           * class. We have to synthesize our own ref of the correct type.
            */
           qualifier = createThisRef(info, method.getEnclosingType());
         }
@@ -1032,7 +1068,7 @@
       JNewInstance newInstance = new JNewInstance(program, info, enclosingType);
       JMethodCall call = new JMethodCall(program, info, newInstance, ctor);
       JExpression qualifier = dispProcessExpression(x.enclosingInstance);
-      List qualList = new ArrayList();
+      List<JExpression> qualList = new ArrayList<JExpression>();
       qualList.add(qualifier);
 
       /*
@@ -1096,8 +1132,7 @@
        * otherBindings takes the current expression as a qualifier.
        */
       if (x.otherBindings != null) {
-        for (int i = 0; i < x.otherBindings.length; i++) {
-          FieldBinding fieldBinding = x.otherBindings[i];
+        for (FieldBinding fieldBinding : x.otherBindings) {
           JField field;
           if (fieldBinding.declaringClass == null) {
             // probably array.length
@@ -1207,6 +1242,20 @@
       return preOp;
     }
 
+    List<JExpressionStatement> processExpressionStatements(
+        Statement[] statements) {
+      List<JExpressionStatement> jstatements = new ArrayList<JExpressionStatement>();
+      if (statements != null) {
+        for (int i = 0, n = statements.length; i < n; ++i) {
+          JStatement jstmt = dispProcessStatement(statements[i]);
+          if (jstmt != null) {
+            jstatements.add((JExpressionStatement) jstmt);
+          }
+        }
+      }
+      return jstatements;
+    }
+
     void processField(FieldDeclaration declaration) {
       JField field = (JField) typeMap.tryGet(declaration.binding);
       if (field == null) {
@@ -1291,7 +1340,7 @@
       }
 
       // resolve jsni refs
-      final List/* <JsNameRef> */nameRefs = new ArrayList/* <JsNameRef> */();
+      final List<JsNameRef> nameRefs = new ArrayList<JsNameRef>();
       new JsVisitor() {
         // @Override
         public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
@@ -1303,7 +1352,7 @@
       }.accept(func);
 
       for (int i = 0; i < nameRefs.size(); ++i) {
-        JsNameRef nameRef = (JsNameRef) nameRefs.get(i);
+        JsNameRef nameRef = nameRefs.get(i);
         SourceInfo info = nativeMethodBody.getSourceInfo();
         // TODO: make this tighter when we have real source info
         // JSourceInfo info = translateInfo(nameRef.getInfo());
@@ -1449,7 +1498,8 @@
             createVariableRef(info, indexVar), createVariableRef(info, maxVar));
 
         // ++i$index
-        List<JStatement> increments = new ArrayList<JStatement>(1);
+        List<JExpressionStatement> increments = new ArrayList<JExpressionStatement>(
+            1);
         increments.add(new JPrefixOperation(program, info, JUnaryOperator.INC,
             createVariableRef(info, indexVar)).makeStatement());
 
@@ -1515,7 +1565,7 @@
         body.statements.add(0, elementDecl);
 
         return new JForStatement(program, info, initializers, condition,
-            Collections.emptyList(), body);
+            Collections.<JExpressionStatement> emptyList(), body);
       }
     }
 
@@ -1525,9 +1575,9 @@
       // If the condition is false, don't process the body
       boolean removeBody = isOptimizedFalse(x.condition);
 
-      List/* <? extends JStatement> */init = processStatements(x.initializations);
+      List<JStatement> init = processStatements(x.initializations);
       JExpression expr = dispProcessExpression(x.condition);
-      List/* <JExpressionStatement> */incr = processStatements(x.increments);
+      List<JExpressionStatement> incr = processExpressionStatements(x.increments);
       JStatement body = removeBody ? null : dispProcessStatement(x.action);
       return new JForStatement(program, info, init, expr, incr, body);
     }
@@ -1616,15 +1666,15 @@
     JStatement processStatement(TryStatement x) {
       SourceInfo info = makeSourceInfo(x);
       JBlock tryBlock = (JBlock) dispProcessStatement(x.tryBlock);
-      List/* <JLocalRef> */catchArgs = new ArrayList/* <JLocalRef> */();
-      List/* <JBlock> */catchBlocks = new ArrayList/* <JBlock> */();
+      List<JLocalRef> catchArgs = new ArrayList<JLocalRef>();
+      List<JBlock> catchBlocks = new ArrayList<JBlock>();
       if (x.catchBlocks != null) {
         for (int i = 0, c = x.catchArguments.length; i < c; ++i) {
           JLocal local = (JLocal) typeMap.get(x.catchArguments[i].binding);
-          catchArgs.add(createVariableRef(info, local));
+          catchArgs.add((JLocalRef) createVariableRef(info, local));
         }
         for (int i = 0, c = x.catchBlocks.length; i < c; ++i) {
-          catchBlocks.add(dispProcessStatement(x.catchBlocks[i]));
+          catchBlocks.add((JBlock) dispProcessStatement(x.catchBlocks[i]));
         }
       }
       JBlock finallyBlock = (JBlock) dispProcessStatement(x.finallyBlock);
@@ -1650,8 +1700,8 @@
       return stmt;
     }
 
-    List/* <? extends JStatement> */processStatements(Statement[] statements) {
-      List/* <JStatement> */jstatements = new ArrayList/* <JStatement> */();
+    List<JStatement> processStatements(Statement[] statements) {
+      List<JStatement> jstatements = new ArrayList<JStatement>();
       if (statements != null) {
         for (int i = 0, n = statements.length; i < n; ++i) {
           JStatement jstmt = dispProcessStatement(statements[i]);
@@ -1696,11 +1746,10 @@
                * Unfortunately, my params might not work as-is, so we have to
                * check each one to see if any will make a suitable this ref.
                */
-              List/* <JExpression> */workList = new ArrayList/* <JExpression> */();
-              Iterator/* <JParameter> */paramIt = getSyntheticsIterator(currentMethod);
+              List<JExpression> workList = new ArrayList<JExpression>();
+              Iterator<JParameter> paramIt = getSyntheticsIterator(currentMethod);
               for (int i = 0; i < myBinding.enclosingInstances.length; ++i) {
-                workList.add(createVariableRef(info,
-                    (JParameter) paramIt.next()));
+                workList.add(createVariableRef(info, paramIt.next()));
               }
               call.getArgs().add(createThisRef(classType, workList));
             } else {
@@ -1753,18 +1802,16 @@
       // All synthetics must be passed through to the target ctor
       ReferenceBinding declaringClass = x.binding.declaringClass;
       if (declaringClass instanceof NestedTypeBinding) {
-        Iterator/* <JParameter> */paramIt = getSyntheticsIterator(currentMethod);
+        Iterator<JParameter> paramIt = getSyntheticsIterator(currentMethod);
         NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
         if (nestedBinding.enclosingInstances != null) {
           for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
-            call.getArgs().add(
-                createVariableRef(info, (JParameter) paramIt.next()));
+            call.getArgs().add(createVariableRef(info, paramIt.next()));
           }
         }
         if (nestedBinding.outerLocalVariables != null) {
           for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
-            call.getArgs().add(
-                createVariableRef(info, (JParameter) paramIt.next()));
+            call.getArgs().add(createVariableRef(info, paramIt.next()));
           }
         }
       }
@@ -1772,10 +1819,10 @@
       return call;
     }
 
-    private void addAllOuterThisRefs(List list, JExpression expr,
-        JClassType classType) {
+    private void addAllOuterThisRefs(List<? super JFieldRef> list,
+        JExpression expr, JClassType classType) {
       if (classType.fields.size() > 0) {
-        JField field = (JField) classType.fields.get(0);
+        JField field = classType.fields.get(0);
         if (field.getName().startsWith("this$")) {
           list.add(new JFieldRef(program, expr.getSourceInfo(), expr, field,
               currentClass));
@@ -1783,13 +1830,54 @@
       }
     }
 
-    private void addAllOuterThisRefsPlusSuperChain(List workList,
-        JExpression expr, JClassType classType) {
+    private void addAllOuterThisRefsPlusSuperChain(
+        List<? super JFieldRef> workList, JExpression expr, JClassType classType) {
       for (; classType != null; classType = classType.extnds) {
         addAllOuterThisRefs(workList, expr, classType);
       }
     }
 
+    private JExpression box(JExpression toBox, JPrimitiveType primitiveType) {
+      // Find the wrapper type for this primitive type.
+      String wrapperTypeName = primitiveType.getWrapperTypeName();
+      JClassType wrapperType = (JClassType) program.getFromTypeMap(wrapperTypeName);
+      if (wrapperType == null) {
+        throw new InternalCompilerException(toBox, "Cannot find wrapper type '"
+            + wrapperTypeName + "' associated with primitive type '"
+            + primitiveType.getName() + "'", null);
+      }
+
+      // Find the correct valueOf() method.
+      JMethod valueOfMethod = null;
+      for (JMethod method : wrapperType.methods) {
+        if ("valueOf".equals(method.getName())) {
+          if (method.params.size() == 1) {
+            JParameter param = method.params.get(0);
+            if (param.getType() == primitiveType) {
+              // Found it.
+              valueOfMethod = method;
+              break;
+            }
+          }
+        }
+      }
+
+      if (valueOfMethod == null || !valueOfMethod.isStatic()
+          || valueOfMethod.getType() != wrapperType) {
+        throw new InternalCompilerException(toBox,
+            "Expected to find a method on '" + wrapperTypeName
+                + "' whose signature matches 'public static "
+                + wrapperType.getName() + " valueOf(" + primitiveType.getName()
+                + ")'", null);
+      }
+
+      // Create the boxing call.
+      JMethodCall call = new JMethodCall(program, toBox.getSourceInfo(), null,
+          valueOfMethod);
+      call.getArgs().add(toBox);
+      return call;
+    }
+
     private JLocalDeclarationStatement createLocalDeclaration(SourceInfo info,
         JLocal arrayVar, JExpression value) {
       return new JLocalDeclarationStatement(program, info, new JLocalRef(
@@ -1805,7 +1893,7 @@
         JClassType targetType) {
       assert (currentClass instanceof JClassType);
       JExpression expr = program.getExprThisRef(info, (JClassType) currentClass);
-      List/* <JExpression> */list = new ArrayList();
+      List<JExpression> list = new ArrayList<JExpression>();
       addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) currentClass);
       return createThisRef(targetType, list);
     }
@@ -1822,7 +1910,7 @@
      * correct type, and we may need use one of its fields.
      */
     private JExpression createThisRef(JReferenceType qualType, JExpression expr) {
-      List/* <JExpression> */list = new ArrayList();
+      List<JExpression> list = new ArrayList<JExpression>();
       list.add(expr);
       return createThisRef(qualType, list);
     }
@@ -1847,11 +1935,11 @@
      * type. We have observed this to be consistent with how Java handles it.
      */
     private JExpression createThisRef(JReferenceType qualType,
-        List/* <JExpression> */list) {
-      LinkedList/* <JExpression> */workList = new LinkedList/* <JExpression> */();
+        List<JExpression> list) {
+      LinkedList<JExpression> workList = new LinkedList<JExpression>();
       workList.addAll(list);
       while (!workList.isEmpty()) {
-        JExpression expr = (JExpression) workList.removeFirst();
+        JExpression expr = workList.removeFirst();
         JClassType classType = (JClassType) expr.getType();
         for (; classType != null; classType = classType.extnds) {
           // prefer myself or myself-as-supertype over any of my this$ fields
@@ -1951,12 +2039,12 @@
         return null;
       }
       String sname = String.valueOf(name);
-      Map/* <String, JLabel> */lblMap = (Map) this.labelMap.get(enclosingMethod);
+      Map<String, JLabel> lblMap = this.labelMap.get(enclosingMethod);
       if (lblMap == null) {
-        lblMap = new HashMap();
+        lblMap = new HashMap<String, JLabel>();
         this.labelMap.put(enclosingMethod, lblMap);
       }
-      JLabel jlabel = (JLabel) lblMap.get(sname);
+      JLabel jlabel = lblMap.get(sname);
       if (jlabel == null) {
         jlabel = new JLabel(program, info, sname);
         lblMap.put(sname, jlabel);
@@ -1987,7 +2075,7 @@
       if (parenPos < 0) {
         // look for a field
         for (int i = 0; i < type.fields.size(); ++i) {
-          JField field = (JField) type.fields.get(i);
+          JField field = type.fields.get(i);
           if (field.getName().equals(rhs)) {
             return field;
           }
@@ -2000,7 +2088,7 @@
         String methodName = rhs.substring(0, parenPos);
         String almostMatches = null;
         for (int i = 0; i < type.methods.size(); ++i) {
-          JMethod method = (JMethod) type.methods.get(i);
+          JMethod method = type.methods.get(i);
           if (method.getName().equals(methodName)) {
             String jsniSig = getJsniSig(method);
             if (jsniSig.equals(rhs)) {
@@ -2054,7 +2142,7 @@
             JType type = (JType) typeMap.get(varBinding.type);
             String name = String.valueOf(varBinding.name);
             for (int i = 0; i < currentMethod.params.size(); ++i) {
-              JParameter param = (JParameter) currentMethod.params.get(i);
+              JParameter param = currentMethod.params.get(i);
               if (type == param.getType() && name.equals(param.getName())) {
                 variable = param;
                 break;
@@ -2171,6 +2259,55 @@
         }
       }
     }
+
+    private JExpression unbox(JExpression toUnbox, JClassType wrapperType) {
+      String wrapperTypeName = wrapperType.getName();
+      String primitiveName = null;
+      if ("java.lang.Integer".equals(wrapperTypeName)) {
+        primitiveName = "int";
+      } else if ("java.lang.Boolean".equals(wrapperTypeName)) {
+        primitiveName = "boolean";
+      } else if ("java.lang.Character".equals(wrapperTypeName)) {
+        primitiveName = "char";
+      } else if ("java.lang.Long".equals(wrapperTypeName)) {
+        primitiveName = "long";
+      } else if ("java.lang.Short".equals(wrapperTypeName)) {
+        primitiveName = "short";
+      } else if ("java.lang.Byte".equals(wrapperTypeName)) {
+        primitiveName = "byte";
+      } else if ("java.lang.Double".equals(wrapperTypeName)) {
+        primitiveName = "double";
+      } else if ("java.lang.Float".equals(wrapperTypeName)) {
+        primitiveName = "float";
+      } else {
+        throw new InternalCompilerException(toUnbox,
+            "Attempt to unbox unexpected type '" + wrapperTypeName + "'", null);
+      }
+
+      String valueMethodName = primitiveName + "Value";
+      JMethod valueMethod = null;
+      for (Object element : wrapperType.methods) {
+        JMethod method = (JMethod) element;
+        if (method.getName().equals(valueMethodName)) {
+          if (method.params.isEmpty()) {
+            // It's a match!
+            valueMethod = method;
+            break;
+          }
+        }
+      }
+
+      if (valueMethod == null) {
+        throw new InternalCompilerException(toUnbox,
+            "Expected to find a method on '" + wrapperTypeName
+                + "' whose signature matches 'public " + primitiveName + " "
+                + valueMethodName + "()'", null);
+      }
+
+      JMethodCall unboxCall = new JMethodCall(program, toUnbox.getSourceInfo(),
+          toUnbox, valueMethod);
+      return unboxCall;
+    }
   }
 
   /**
@@ -2205,8 +2342,8 @@
    * Gets a JParameter iterator for a constructor method over its synthetic
    * parameters.
    */
-  private static Iterator getSyntheticsIterator(JMethod method) {
-    Iterator it = method.params.iterator();
+  private static Iterator<JParameter> getSyntheticsIterator(JMethod method) {
+    Iterator<JParameter> it = method.params.iterator();
     for (int i = 0, c = method.getOriginalParamTypes().size(); i < c; ++i) {
       it.next();
     }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
index 6b29ceb..05b2a39 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
@@ -40,7 +40,7 @@
   /**
    * Maps Eclipse AST nodes to our JNodes.
    */
-  private final Map/* <Binding, JNode> */crossRefMap = new IdentityHashMap();
+  private final Map<Binding, JNode> crossRefMap = new IdentityHashMap<Binding, JNode>();
 
   /**
    * Centralizes creation and singleton management.
@@ -93,7 +93,7 @@
   }
 
   private JNode internalGet(Binding binding) {
-    JNode cached = (JNode) crossRefMap.get(binding);
+    JNode cached = crossRefMap.get(binding);
     if (cached != null) {
       // Already seen this one.
       return cached;
diff --git a/user/test/com/google/gwt/emultest/EmulSuite.java b/user/test/com/google/gwt/emultest/EmulSuite.java
index 4f641c0..90e7e55 100644
--- a/user/test/com/google/gwt/emultest/EmulSuite.java
+++ b/user/test/com/google/gwt/emultest/EmulSuite.java
@@ -30,11 +30,10 @@
 import junit.framework.TestSuite;
 
 /**
- * TODO: document me.
+ * Tests all classes in GWT JRE emulation library.
  */
 public class EmulSuite {
 
-  /** Note: due to compiler error, only can use one Test Case at a time */
   public static Test suite() {
     TestSuite suite = new TestSuite("Tests for com.google.gwt.emul.java");