JVariableRef cleanup.

Change-Id: I4ef1263de4b2dd269bcdfff5acb77877b549672f
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
index 400e1c6..02cf508 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
@@ -133,6 +133,12 @@
     return null;
   }
 
+
+  @Override
+  public JFieldRef makeRef(SourceInfo info) {
+    throw new UnsupportedOperationException();
+  }
+
   @Override
   public void setJsMemberInfo(
       JsMemberType jsMembertype, String namespace, String name, boolean exported) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JFieldRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JFieldRef.java
index 0c294d9..2f30441 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JFieldRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JFieldRef.java
@@ -39,7 +39,8 @@
    */
   private final JType overriddenType;
 
-  public JFieldRef(SourceInfo info, JExpression instance, JField field, JDeclaredType enclosingType) {
+  public JFieldRef(
+      SourceInfo info, JExpression instance, JField field, JDeclaredType enclosingType) {
     this(info, instance, field, enclosingType, null);
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocal.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocal.java
index 4eefd66..15c96c4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocal.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocal.java
@@ -27,6 +27,11 @@
   }
 
   @Override
+  public JLocalRef makeRef(SourceInfo info) {
+    return new JLocalRef(info, this);
+  }
+
+  @Override
   public void setInitializer(JDeclarationStatement declStmt) {
     this.declStmt = declStmt;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalRef.java
index 9a6a890..161292a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalRef.java
@@ -27,7 +27,7 @@
    */
   private final JLocal local;
 
-  public JLocalRef(SourceInfo info, JLocal local) {
+  JLocalRef(SourceInfo info, JLocal local) {
     super(info, local);
     this.local = local;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
index 78fa2a2..0eddc4c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -90,18 +90,30 @@
     return isJsNative() || isJsFunctionMethod() || isJsInterfaceMethod();
   }
 
+  /**
+   * Adds a new final parameter to this method.
+   */
   public JParameter createFinalParameter(SourceInfo info, String name, JType type) {
     return createParameter(info, name, type, true, false);
   }
 
+  /**
+   * Adds a new parameter to this method.
+   */
   public JParameter createParameter(SourceInfo info, String name, JType type) {
     return createParameter(info, name, type, false, false);
   }
 
+  /**
+   * Adds a new final parameter to this method.
+   */
   public JParameter createParameter(SourceInfo info, String name, JType type, boolean isFinal) {
     return createParameter(info, name, type, isFinal, false);
   }
 
+  /**
+   * Adds a new parameter to this method that is a copy of {@code from}.
+   */
   public JParameter cloneParameter(JParameter from) {
     return createParameter(
         from.getSourceInfo(), from.getName(), from.getType(), from.isFinal(), from.isThis());
@@ -114,13 +126,17 @@
     return createParameter(info,  "this$static", type, true, true);
   }
 
+  private void addParameter(JParameter x) {
+    params = Lists.add(params, x);
+  }
+
   private JParameter createParameter(SourceInfo info, String name, JType type,
       boolean isFinal, boolean isThis) {
     assert (name != null);
     assert (type != null);
 
     JParameter x = new JParameter(info, name, type, isFinal, isThis);
-    addParam(x);
+    addParameter(x);
     return x;
   }
 
@@ -446,12 +462,6 @@
     assert overridingMethod != this : this + " cannot override itself";
     overridingMethods.add(overridingMethod);
   }
-  /**
-   * Adds a parameter to this method.
-   */
-  public void addParam(JParameter x) {
-    params = Lists.add(params, x);
-  }
 
   public void addThrownException(JClassType exceptionType) {
     thrownExceptions = Lists.add(thrownExceptions, exceptionType);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java
index d051fc5..f6d385e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java
@@ -36,6 +36,11 @@
   }
 
   @Override
+  public JParameterRef makeRef(SourceInfo info) {
+    return new JParameterRef(info, this);
+  }
+
+  @Override
   public void setInitializer(JDeclarationStatement declStmt) {
     throw new UnsupportedOperationException("A JParameter cannot have an initializer");
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameterRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameterRef.java
index 1730b3d..90407ef 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameterRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameterRef.java
@@ -27,7 +27,7 @@
    */
   private final JParameter param;
 
-  public JParameterRef(SourceInfo info, JParameter param) {
+  JParameterRef(SourceInfo info, JParameter param) {
     super(info, param);
     this.param = param;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JVariable.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JVariable.java
index a688025..6eaa38b 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JVariable.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JVariable.java
@@ -60,6 +60,8 @@
     return null;
   }
 
+  public abstract JVariableRef makeRef(SourceInfo sourceInfo);
+
   @Override
   public String getName() {
     return name;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
index eb1f537..f89d434 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
@@ -79,10 +79,10 @@
 
       {
         // $e = Exceptions.wrap($e)
-        JMethodCall call = new JMethodCall(catchInfo, null, wrapMethod);
-        call.addArg(new JLocalRef(catchInfo, exceptionVariable));
-        newCatchBlock.addStmt(JProgram.createAssignmentStmt(catchInfo, new JLocalRef(catchInfo,
-            exceptionVariable), call));
+        JMethodCall call =
+            new JMethodCall(catchInfo, null, wrapMethod, exceptionVariable.makeRef(catchInfo));
+        newCatchBlock.addStmt(
+            JProgram.createAssignmentStmt(catchInfo, exceptionVariable.makeRef(catchInfo), call));
       }
 
       /*
@@ -93,7 +93,7 @@
        * Go backwards so we can nest the else statements in the correct order!
        */
       // rethrow the current exception if no one caught it.
-      JStatement cur = new JThrowStatement(catchInfo, new JLocalRef(catchInfo, exceptionVariable));
+      JStatement cur = new JThrowStatement(catchInfo, exceptionVariable.makeRef(catchInfo));
       for (int i = x.getCatchClauses().size() - 1; i >= 0; i--) {
         JTryStatement.CatchClause clause = x.getCatchClauses().get(i);
         JBlock block = clause.getBlock();
@@ -107,16 +107,16 @@
 
         // Handle the first Exception type.
         JExpression ifTest = new JInstanceOf(catchInfo, (JReferenceType) exceptionsTypes.get(0),
-            new JLocalRef(catchInfo, exceptionVariable));
+            exceptionVariable.makeRef(catchInfo));
         // Handle the rest of the Exception types if any.
         for (int j = 1; j < exceptionsTypes.size(); j++) {
           JExpression orExp = new JInstanceOf(catchInfo, (JReferenceType) exceptionsTypes.get(j),
-              new JLocalRef(catchInfo, exceptionVariable));
+              exceptionVariable.makeRef(catchInfo));
           ifTest = new JBinaryOperation(catchInfo, JPrimitiveType.BOOLEAN, JBinaryOperator.OR,
               ifTest, orExp);
         }
         JDeclarationStatement declaration =
-            new JDeclarationStatement(catchInfo, arg, new JLocalRef(catchInfo, exceptionVariable));
+            new JDeclarationStatement(catchInfo, arg, exceptionVariable.makeRef(catchInfo));
         block.addStmt(0, declaration);
         // nest the previous as an else for me
         cur = new JIfStatement(catchInfo, ifTest, block, cur);
@@ -129,7 +129,7 @@
       List<JType> newCatchTypes = new ArrayList<JType>(1);
       newCatchTypes.add(exceptionVariable.getType());
       x.getCatchClauses().add(new JTryStatement.CatchClause(newCatchTypes,
-          new JLocalRef(newCatchBlock.getSourceInfo(), exceptionVariable), newCatchBlock));
+          exceptionVariable.makeRef(catchInfo), newCatchBlock));
     }
 
     @Override
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
index d57a276..a453256 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
@@ -183,7 +183,7 @@
 
   @Override
   public boolean visit(JLocalRef x, Context ctx) {
-    expression = new JLocalRef(x.getSourceInfo(), x.getLocal());
+    expression = x.getLocal().makeRef(x.getSourceInfo());
     return false;
   }
 
@@ -244,7 +244,7 @@
 
   @Override
   public boolean visit(JParameterRef x, Context ctx) {
-    expression = new JParameterRef(x.getSourceInfo(), x.getParameter());
+    expression = x.getParameter().makeRef(x.getSourceInfo());
     return false;
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
index e0dd5bc..29de891 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
@@ -128,7 +128,7 @@
         JLocal tempLocal = createTempLocal(x.getSourceInfo(), x.getType());
 
         // Create an assignment for this temp and add it to multi.
-        JLocalRef tempRef = new JLocalRef(x.getSourceInfo(), tempLocal);
+        JLocalRef tempRef = tempLocal.makeRef(x.getSourceInfo());
         JBinaryOperation asg =
             new JBinaryOperation(x.getSourceInfo(), x.getType(), JBinaryOperator.ASG, tempRef, x);
         multi.addExpressions(asg);
@@ -207,7 +207,7 @@
       JLocal tempLocal = createTempLocal(x.getSourceInfo(), expressionReturn.getType());
 
       // t = x
-      JLocalRef tempRef = new JLocalRef(x.getSourceInfo(), tempLocal);
+      JLocalRef tempRef = tempLocal.makeRef(x.getSourceInfo());
       JBinaryOperation asg =
           new JBinaryOperation(x.getSourceInfo(), x.getType(), JBinaryOperator.ASG, tempRef,
               expressionReturn);
@@ -219,7 +219,7 @@
       multi.addExpressions(accept(asg));
 
       // t
-      tempRef = new JLocalRef(x.getSourceInfo(), tempLocal);
+      tempRef = tempLocal.makeRef(x.getSourceInfo());
       multi.addExpressions(tempRef);
 
       ctx.replaceMe(multi);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/Devirtualizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/Devirtualizer.java
index c3f3bb9..bdcb8b3 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/Devirtualizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/Devirtualizer.java
@@ -360,12 +360,12 @@
 
     if (!dispatchTo.isStatic()) {
       // This is a virtual dispatch, take the first parameter as the receiver.
-      thisParamRef = new JParameterRef(sourceInfo, parameters.remove(0));
+      thisParamRef = parameters.remove(0).makeRef(sourceInfo);
     }
 
     JMethodCall dispatchCall = new JMethodCall(sourceInfo, thisParamRef, dispatchTo);
     for (JParameter param : parameters) {
-      dispatchCall.addArg(new JParameterRef(sourceInfo, param));
+      dispatchCall.addArg(param.makeRef(sourceInfo));
     }
     return dispatchCall;
   }
@@ -494,7 +494,7 @@
     // Dispatch to array
     dispatchExpression = constructMinimalCondition(
         isJavaArray,
-        new JParameterRef(thisParam.getSourceInfo(), thisParam),
+        thisParam.makeRef(thisParam.getSourceInfo()),
         maybeCreateDispatch(dispatchToMethodByTargetType.get(DispatchType.JAVA_ARRAY),
             devirtualMethod),
         dispatchExpression);
@@ -502,7 +502,7 @@
     // Dispatch to regular object
     dispatchExpression = constructMinimalCondition(
         hasJavaObjectVirtualDispatch,
-        new JParameterRef(thisParam.getSourceInfo(), thisParam),
+        thisParam.makeRef(thisParam.getSourceInfo()),
         maybeCreateDispatch(
             dispatchToMethodByTargetType.get(DispatchType.HAS_JAVA_VIRTUAL_DISPATCH),
             devirtualMethod),
@@ -515,7 +515,7 @@
       String castInstanceOfQualifier = dispatchType.getTypeCategory().castInstanceOfQualifier();
       dispatchExpression = constructMinimalCondition(
           program.getIndexedMethod("Cast.instanceOf" + castInstanceOfQualifier),
-          new JParameterRef(thisParam.getSourceInfo(), thisParam),
+          thisParam.makeRef(thisParam.getSourceInfo()),
           maybeCreateDispatch(dispatchToMethodByTargetType.get(dispatchType), devirtualMethod),
           dispatchExpression);
     }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
index b1e46c2..2bc446f 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
@@ -774,10 +774,9 @@
 
         if (curClass.classType.isEnumOrSubclass() != null) {
           // Enums: wire up synthetic name/ordinal params to the super method.
-          JParameterRef enumNameRef = new JParameterRef(info, curMethod.method.getParams().get(0));
+          JParameterRef enumNameRef = curMethod.method.getParams().get(0).makeRef(info);
           call.addArg(enumNameRef);
-          JParameterRef enumOrdinalRef =
-              new JParameterRef(info, curMethod.method.getParams().get(1));
+          JParameterRef enumOrdinalRef = curMethod.method.getParams().get(1).makeRef(info);
           call.addArg(enumOrdinalRef);
         }
 
@@ -923,21 +922,21 @@
           // int i$index = 0
           initializers.add(makeDeclaration(info, indexVar, JIntLiteral.get(0)));
           // int i$max = i$array.length
-          initializers.add(makeDeclaration(info, maxVar, new JArrayLength(info, new JLocalRef(info,
-              arrayVar))));
+          initializers.add(makeDeclaration(info, maxVar,
+              new JArrayLength(info, arrayVar.makeRef(info))));
 
           // i$index < i$max
           JExpression condition =
-              new JBinaryOperation(info, JPrimitiveType.BOOLEAN, JBinaryOperator.LT, new JLocalRef(
-                  info, indexVar), new JLocalRef(info, maxVar));
+              new JBinaryOperation(info, JPrimitiveType.BOOLEAN, JBinaryOperator.LT,
+                  indexVar.makeRef(info), maxVar.makeRef(info));
 
           // ++i$index
           JExpression increments = new JPrefixOperation(info, JUnaryOperator.INC,
-              new JLocalRef(info, indexVar));
+              indexVar.makeRef(info));
 
           // T elementVar = i$array[i$index];
           elementDecl.initializer =
-              new JArrayRef(info, new JLocalRef(info, arrayVar), new JLocalRef(info, indexVar));
+              new JArrayRef(info, arrayVar.makeRef(info), indexVar.makeRef(info));
           body.addStmt(0, elementDecl);
 
           result = new JForStatement(info, initializers, condition, increments, body);
@@ -967,11 +966,11 @@
 
           // i$iterator.hasNext()
           JExpression condition =
-              new JMethodCall(info, new JLocalRef(info, iteratorVar), typeMap.get(hasNext));
+              new JMethodCall(info, iteratorVar.makeRef(info), typeMap.get(hasNext));
 
           // T elementVar = (T) i$iterator.next();
           elementDecl.initializer =
-              new JMethodCall(info, new JLocalRef(info, iteratorVar), typeMap.get(next));
+              new JMethodCall(info, iteratorVar.makeRef(info), typeMap.get(next));
 
           // Perform any implicit reference type casts (due to generics).
           // Note this occurs before potential unboxing.
@@ -1100,7 +1099,7 @@
           List<JExpression> dims = new ArrayList<JExpression>();
           JArrayType arrayType = (JArrayType) synthMethod.getType();
           JParameter dimParam = synthMethod.getParams().get(0);
-          JExpression dimArgExpr = new JParameterRef(dimParam.getSourceInfo(), dimParam);
+          JExpression dimArgExpr = dimParam.makeRef(dimParam.getSourceInfo());
           dims.add(dimArgExpr);
           JNewArray newArray = JNewArray.createArrayWithDimensionExpressions(
               synthMethod.getSourceInfo(), arrayType, dims);
@@ -1284,7 +1283,7 @@
       // and now we propagate the rest of the actual interface method parameters on the end
       // (e.g. ClickEvent e)
       for (JParameter param : samMethod.getParams()) {
-        samCall.addArg(new JParameterRef(info, param));
+        samCall.addArg(param.makeRef(info));
       }
 
       // we either add a return statement, or don't, depending on what the interface wants
@@ -1426,7 +1425,7 @@
       // this.paramField = param
       JThisRef thisRef = new JThisRef(info, ctor.getEnclosingType());
       JFieldRef paramFieldRef = new JFieldRef(info, thisRef, paramField, ctor.getEnclosingType());
-      JParameterRef paramRef = new JParameterRef(info, param);
+      JParameterRef paramRef = param.makeRef(info);
       ctorBody.getBlock().addStmt(
           new JBinaryOperation(info, paramFieldRef.getType(),
               JBinaryOperator.ASG,
@@ -1478,7 +1477,7 @@
         SourceInfo info = makeSourceInfo(x);
         JLocal local = (JLocal) curMethod.locals.get(x.binding);
         assert local != null;
-        JLocalRef localRef = new JLocalRef(info, local);
+        JLocalRef localRef = local.makeRef(info);
         JExpression initialization = pop(x.initialization);
         push(new JDeclarationStatement(info, localRef, initialization));
       } catch (Throwable e) {
@@ -1837,7 +1836,7 @@
           // the instance qualifier is the first parameter in this case.
           // Needs to be cast the actual type due to generics.
           instance = new JCastOperation(info, typeMap.get(referredMethodBinding.declaringClass),
-              new JParameterRef(info, paramIt.next()));
+              paramIt.next().makeRef(info));
         }
         JMethodCall samCall = null;
 
@@ -1874,7 +1873,7 @@
 
         while (paramIt.hasNext()) {
           JParameter param = paramIt.next();
-          JExpression paramExpr = new JParameterRef(info, param);
+          JExpression paramExpr = param.makeRef(info);
           // params may need to be boxed or unboxed
           TypeBinding destParam = null;
           // if it is not the trailing param or varargs, or interface method is already varargs
@@ -2127,7 +2126,7 @@
               // Regular exception
               catchTypes.add(local.getType());
             }
-            catchClauses.add(new JTryStatement.CatchClause(catchTypes, new JLocalRef(info, local),
+            catchClauses.add(new JTryStatement.CatchClause(catchTypes, local.makeRef(info),
                 catchBlocks.get(i)));
           }
         }
@@ -2196,9 +2195,9 @@
 
       JBlock catchBlock = new JBlock(info);
       catchBlock.addStmt(createAssignment(info, javaLangThrowable, exceptionVar, catchVar));
-      catchBlock.addStmt(new JThrowStatement(info, new JLocalRef(info, exceptionVar)));
+      catchBlock.addStmt(new JThrowStatement(info, exceptionVar.makeRef(info)));
 
-      catchClauses.add(new JTryStatement.CatchClause(clauseTypes, new JLocalRef(info, catchVar),
+      catchClauses.add(new JTryStatement.CatchClause(clauseTypes, catchVar.makeRef(info),
           catchBlock));
 
       // create finally block
@@ -2210,9 +2209,9 @@
 
       // if (exception != null) throw exception
       JExpression exceptionNotNull = new JBinaryOperation(info, JPrimitiveType.BOOLEAN,
-          JBinaryOperator.NEQ, new JLocalRef(info, exceptionVar), JNullLiteral.INSTANCE);
+          JBinaryOperator.NEQ, exceptionVar.makeRef(info), JNullLiteral.INSTANCE);
       finallyBlock.addStmt(new JIfStatement(info, exceptionNotNull,
-          new JThrowStatement(info, new JLocalRef(info, exceptionVar)), null));
+          new JThrowStatement(info, exceptionVar.makeRef(info)), null));
 
       // Stitch all together into a inner try block
       outerTryBlock.addStmt(new JTryStatement(info, tryBlock, catchClauses,
@@ -2248,16 +2247,16 @@
        */
 
       JMethodCall safeCloseCall = new JMethodCall(info, null, SAFE_CLOSE_METHOD);
-      safeCloseCall.addArg(0, new JLocalRef(info, resourceVar));
-      safeCloseCall.addArg(1, new JLocalRef(info, exceptionVar));
+      safeCloseCall.addArg(0, resourceVar.makeRef(info));
+      safeCloseCall.addArg(1, exceptionVar.makeRef(info));
 
-      return new JBinaryOperation(info, javaLangThrowable, JBinaryOperator.ASG, new JLocalRef(info,
-          exceptionVar), safeCloseCall).makeStatement();
+      return new JBinaryOperation(info, javaLangThrowable, JBinaryOperator.ASG,
+          exceptionVar.makeRef(info), safeCloseCall).makeStatement();
     }
 
     private JStatement createAssignment(SourceInfo info, JType type, JLocal lhs, JLocal rhs) {
-      return new JBinaryOperation(info, type, JBinaryOperator.ASG, new JLocalRef(info, lhs),
-          new JLocalRef(info, rhs)).makeStatement();
+      return new JBinaryOperation(info, type, JBinaryOperator.ASG, lhs.makeRef(info),
+          rhs.makeRef(info)).makeStatement();
     }
 
     @Override
@@ -2730,10 +2729,8 @@
       JField field = curClass.syntheticFields.get(arg);
       assert field != null;
       JFieldRef lhs = makeInstanceFieldRef(info, field);
-      JParameterRef rhs = new JParameterRef(info, param);
-      JBinaryOperation asg =
-          new JBinaryOperation(info, lhs.getType(), JBinaryOperator.ASG, lhs, rhs);
-      return asg;
+      return
+          new JBinaryOperation(info, lhs.getType(), JBinaryOperator.ASG, lhs, param.makeRef(info));
     }
 
     private JExpression box(JExpression original, int implicitConversion) {
@@ -2788,8 +2785,7 @@
       JMethodCall call = new JMethodCall(info, makeThisRef(info), implmeth);
       for (int i = 0; i < bridgeMethod.getParams().size(); i++) {
         JParameter param = bridgeMethod.getParams().get(i);
-        JParameterRef paramRef = new JParameterRef(info, param);
-        call.addArg(maybeCast(implParams.get(i).getType(), paramRef));
+        call.addArg(maybeCast(implParams.get(i).getType(), param.makeRef(info)));
       }
 
       JMethodBody body = (JMethodBody) bridgeMethod.getBody();
@@ -2925,25 +2921,15 @@
 
     private JDeclarationStatement makeDeclaration(SourceInfo info, JLocal local,
         JExpression value) {
-      return new JDeclarationStatement(info, new JLocalRef(info, local), value);
+      return new JDeclarationStatement(info, local.makeRef(info), value);
     }
 
     private JFieldRef makeInstanceFieldRef(SourceInfo info, JField field) {
       return new JFieldRef(info, makeThisRef(info), field, curClass.classType);
     }
 
-    private JExpression makeLocalRef(SourceInfo info, LocalVariableBinding b, MethodInfo cur) {
-      JVariable variable = cur.locals.get(b);
-      assert variable != null;
-      if (variable instanceof JLocal) {
-        return new JLocalRef(info, (JLocal) variable);
-      } else {
-        return new JParameterRef(info, (JParameter) variable);
-      }
-    }
-
-    private JExpression makeLocalRef(SourceInfo info, LocalVariableBinding b) {
-      return makeLocalRef(info, b, curMethod);
+    private JExpression makeLocalRef(SourceInfo info, LocalVariableBinding b, MethodInfo method) {
+      return method.locals.get(b).makeRef(info);
     }
 
     private JThisRef makeThisRef(SourceInfo info) {
@@ -2973,7 +2959,7 @@
         SyntheticArgumentBinding b = (SyntheticArgumentBinding) path[0];
         JParameter param = (JParameter) curMethod.locals.get(b);
         assert param != null;
-        ref = new JParameterRef(info, param);
+        ref = param.makeRef(info);
         type = (ReferenceBinding) b.type.erasure();
       } else if (path[0] instanceof FieldBinding) {
         FieldBinding b = (FieldBinding) path[0];
@@ -3119,7 +3105,7 @@
             throw new InternalCompilerException(
                 "Could not find matching local arg for explicit super ctor call.");
           }
-          call.addArg(new JParameterRef(call.getSourceInfo(), param));
+          call.addArg(param.makeRef(call.getSourceInfo()));
         }
       }
     }
@@ -3153,7 +3139,7 @@
         for (SyntheticArgumentBinding arg : binding.syntheticOuterLocalVariables()) {
           JParameter param = (JParameter) curMethod.locals.get(arg);
           assert param != null;
-          call.addArg(new JParameterRef(call.getSourceInfo(), param));
+          call.addArg(param.makeRef(call.getSourceInfo()));
         }
       }
     }
@@ -3169,7 +3155,7 @@
         for (@SuppressWarnings("unused")
         ReferenceBinding argType : binding.syntheticEnclosingInstanceTypes()) {
           JParameter param = paramIt.next();
-          call.addArg(new JParameterRef(call.getSourceInfo(), param));
+          call.addArg(param.makeRef(call.getSourceInfo()));
         }
       }
     }
@@ -3270,7 +3256,7 @@
               assert field != null;
               call.addArg(makeInstanceFieldRef(info, field));
             } else if (path[0] instanceof LocalVariableBinding) {
-              JExpression localRef = makeLocalRef(info, (LocalVariableBinding) path[0]);
+              JExpression localRef = makeLocalRef(info, (LocalVariableBinding) path[0], curMethod);
               call.addArg(localRef);
             } else if (path[0] instanceof FieldBinding) {
               JField field = typeMap.get((FieldBinding) path[0]);
@@ -3343,7 +3329,7 @@
             assert field != null;
             result = makeInstanceFieldRef(info, field);
           } else if (path[0] instanceof LocalVariableBinding) {
-            result = makeLocalRef(info, (LocalVariableBinding) path[0]);
+            result = makeLocalRef(info, (LocalVariableBinding) path[0], curMethod);
           } else if (path[0] instanceof FieldBinding) {
             FieldBinding fb = (FieldBinding) path[0];
             assert curClass.typeDecl.binding.isCompatibleWith(x.actualReceiverType.erasure());
@@ -3354,7 +3340,7 @@
             throw new InternalCompilerException("Unknown emulation path.");
           }
         } else {
-          result = makeLocalRef(info, b);
+          result = makeLocalRef(info, b, curMethod);
         }
       } else if (binding instanceof FieldBinding) {
         FieldBinding b = ((FieldBinding) x.binding).original();
@@ -3466,7 +3452,7 @@
         assert valueOfBinding != null;
 
         JFieldRef mapRef = new JFieldRef(info, null, mapField, type);
-        JParameterRef nameRef = new JParameterRef(info, method.getParams().get(0));
+        JParameterRef nameRef = method.getParams().get(0).makeRef(info);
         JMethodCall call = new JMethodCall(info, null, typeMap.get(valueOfBinding));
         call.addArgs(mapRef, nameRef);
         JjsUtils.replaceMethodBody(method, call);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JModVisitorWithTemporaryVariableCreation.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JModVisitorWithTemporaryVariableCreation.java
index 6f2ec01..39405da 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JModVisitorWithTemporaryVariableCreation.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JModVisitorWithTemporaryVariableCreation.java
@@ -19,7 +19,6 @@
 import com.google.gwt.dev.jjs.ast.Context;
 import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
 import com.google.gwt.dev.jjs.ast.JLocal;
-import com.google.gwt.dev.jjs.ast.JLocalRef;
 import com.google.gwt.dev.jjs.ast.JMethodBody;
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JStatement;
@@ -67,7 +66,7 @@
     String temporaryLocalName = newTemporaryLocalName(info, type, currentMethodBody);
     JLocal local = JProgram.createLocal(info, temporaryLocalName, type, false, currentMethodBody);
     JDeclarationStatement declarationStatement =
-        new JDeclarationStatement(info, new JLocalRef(info, local), null);
+        new JDeclarationStatement(info, local.makeRef(info), null);
     currentDeclarationInsertionPoint.peek().insertBefore(declarationStatement);
     return local;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java
index 78c2c8e..979a915 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java
@@ -44,7 +44,6 @@
 import com.google.gwt.dev.jjs.ast.JNewInstance;
 import com.google.gwt.dev.jjs.ast.JNullLiteral;
 import com.google.gwt.dev.jjs.ast.JParameter;
-import com.google.gwt.dev.jjs.ast.JParameterRef;
 import com.google.gwt.dev.jjs.ast.JPrimitiveType;
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JReferenceType;
@@ -212,7 +211,7 @@
     forwardingCall.setStaticDispatchOnly();
     // copy params
     for (JParameter p : forwardingMethod.getParams()) {
-      forwardingCall.addArg(new JParameterRef(p.getSourceInfo(), p));
+      forwardingCall.addArg(p.makeRef(p.getSourceInfo()));
     }
 
     // return statement if not void return type
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
index 1c4cb4f..e6a4be4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
@@ -118,14 +118,12 @@
       @Override
       public void endVisit(JParameterRef x, Context ctx) {
         JParameter param = varMap.get(x.getTarget());
-        JParameterRef paramRef = new JParameterRef(x.getSourceInfo(), param);
-        ctx.replaceMe(paramRef);
+        ctx.replaceMe(param.makeRef(x.getSourceInfo()));
       }
 
       @Override
       public void endVisit(JThisRef x, Context ctx) {
-        JParameterRef paramRef = new JParameterRef(x.getSourceInfo(), thisParam);
-        ctx.replaceMe(paramRef);
+        ctx.replaceMe(thisParam.makeRef(x.getSourceInfo()));
       }
     }
 
@@ -201,7 +199,7 @@
       newCall.addArg(new JThisRef(sourceInfo, enclosingType));
       for (int i = 0; i < x.getParams().size(); ++i) {
         JParameter param = x.getParams().get(i);
-        newCall.addArg(new JParameterRef(sourceInfo, param));
+        newCall.addArg(param.makeRef(sourceInfo));
       }
       newBody.getBlock().addStmt(JjsUtils.makeMethodEndStatement(returnType, newCall));
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
index 89c66c4..23fe33c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
@@ -244,7 +244,7 @@
           JLocal local = (JLocal) declStatement.getVariableRef().getTarget();
           JExpression clone = new JBinaryOperation(stmt.getSourceInfo(), local.getType(),
               JBinaryOperator.ASG,
-              new JLocalRef(declStatement.getVariableRef().getSourceInfo(), local),
+              local.makeRef(declStatement.getVariableRef().getSourceInfo()),
               cloner.cloneExpression(initializer));
           expressions.add(clone);
         } else if (stmt instanceof JExpressionStatement) {
@@ -543,7 +543,7 @@
         newLocalsByOriginalLocal.put(originalLocal, newLocal);
       }
 
-      ctx.replaceMe(new JLocalRef(x.getSourceInfo(), newLocal));
+      ctx.replaceMe(newLocal.makeRef(x.getSourceInfo()));
     }
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
index c2f62eb..f37f99f 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
@@ -32,7 +32,6 @@
 import com.google.gwt.dev.jjs.ast.JField;
 import com.google.gwt.dev.jjs.ast.JFieldRef;
 import com.google.gwt.dev.jjs.ast.JLocal;
-import com.google.gwt.dev.jjs.ast.JLocalRef;
 import com.google.gwt.dev.jjs.ast.JMethod;
 import com.google.gwt.dev.jjs.ast.JMethodBody;
 import com.google.gwt.dev.jjs.ast.JMethodCall;
@@ -371,8 +370,8 @@
           createTempLocal(sourceInfo, Iterables.getLast(
               Iterables.filter(originalParams, Predicates.in(referencedNonTypes))).getType());
       unevaluatedArgumentsForPrunedParameters.addExpressions(0, JProgram.createAssignment(
-          lastArg.getSourceInfo(), new JLocalRef(sourceInfo, tempVar), lastArg));
-      unevaluatedArgumentsForPrunedParameters.addExpressions(new JLocalRef(sourceInfo, tempVar));
+          lastArg.getSourceInfo(), tempVar.makeRef(sourceInfo), lastArg));
+      unevaluatedArgumentsForPrunedParameters.addExpressions(tempVar.makeRef(sourceInfo));
       replacementCall.setArg(replacementCall.getArgs().size() - 1, unevaluatedArgumentsForPrunedParameters);
       ctx.replaceMe(replacementCall);
     }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
index e203666..8c54cea 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
@@ -37,7 +37,6 @@
 import com.google.gwt.dev.jjs.ast.JMethodCall;
 import com.google.gwt.dev.jjs.ast.JNewInstance;
 import com.google.gwt.dev.jjs.ast.JParameter;
-import com.google.gwt.dev.jjs.ast.JParameterRef;
 import com.google.gwt.dev.jjs.ast.JPermutationDependentValue;
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JReferenceType;
@@ -310,7 +309,7 @@
       // Fake an assignment-to-self on all args to prevent tightening
       JMethod method = x.getTarget();
       for (JParameter param : method.getParams()) {
-        addAssignment(param, new JParameterRef(SourceOrigin.UNKNOWN, param));
+        addAssignment(param, param.makeRef(SourceOrigin.UNKNOWN));
       }
     }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/copy/CopyIntegratedFlowFunction.java b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/copy/CopyIntegratedFlowFunction.java
index c26c771..46f3c37 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/copy/CopyIntegratedFlowFunction.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/copy/CopyIntegratedFlowFunction.java
@@ -15,16 +15,10 @@
  */
 package com.google.gwt.dev.jjs.impl.gflow.copy;
 
-import com.google.gwt.dev.jjs.SourceInfo;
 import com.google.gwt.dev.jjs.ast.Context;
-import com.google.gwt.dev.jjs.ast.JLocal;
-import com.google.gwt.dev.jjs.ast.JLocalRef;
 import com.google.gwt.dev.jjs.ast.JModVisitor;
 import com.google.gwt.dev.jjs.ast.JNode;
-import com.google.gwt.dev.jjs.ast.JParameter;
-import com.google.gwt.dev.jjs.ast.JParameterRef;
 import com.google.gwt.dev.jjs.ast.JVariable;
-import com.google.gwt.dev.jjs.ast.JVariableRef;
 import com.google.gwt.dev.jjs.impl.gflow.AssumptionMap;
 import com.google.gwt.dev.jjs.impl.gflow.AssumptionUtil;
 import com.google.gwt.dev.jjs.impl.gflow.IntegratedFlowFunction;
@@ -65,7 +59,7 @@
             @Override
             public void endVisit(JNode x, Context ctx) {
               if (x == node.getJNode()) {
-                ctx.replaceMe(createRef(x.getSourceInfo(), original));
+                ctx.replaceMe(original.makeRef(x.getSourceInfo()));
               }
             }
           };
@@ -81,7 +75,7 @@
     @Override
     public Cfg getNewSubgraph() {
       CfgReadNode newNode = new CfgReadNode(node.getParent(),
-          createRef(node.getJNode().getSourceInfo(), original));
+          original.makeRef(node.getJNode().getSourceInfo()));
       return CfgUtil.createSingleNodeReplacementGraph(graph, node, newNode);
     }
 
@@ -89,16 +83,6 @@
     public String toString() {
       return "CopyTransformation(" + node + "," + original + ")";
     }
-
-    private JVariableRef createRef(SourceInfo sourceInfo, JVariable variable) {
-      if (variable instanceof JLocal) {
-        return new JLocalRef(sourceInfo, (JLocal) variable);
-      } else if (variable instanceof JParameter) {
-        return new JParameterRef(sourceInfo, (JParameter) variable);
-      }
-      throw new IllegalArgumentException("Unsupported variable: " +
-          variable.getClass());
-    }
   }
 
   private static final CopyFlowFunction FLOW_FUNCTION = new CopyFlowFunction();
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/JModVisitorWithTemporaryVariableCreationTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/JModVisitorWithTemporaryVariableCreationTest.java
index 1dbf024..5d58b3c 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/JModVisitorWithTemporaryVariableCreationTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/JModVisitorWithTemporaryVariableCreationTest.java
@@ -22,7 +22,6 @@
 import com.google.gwt.dev.jjs.ast.JExpression;
 import com.google.gwt.dev.jjs.ast.JExpressionStatement;
 import com.google.gwt.dev.jjs.ast.JLocal;
-import com.google.gwt.dev.jjs.ast.JLocalRef;
 import com.google.gwt.dev.jjs.ast.JMethodBody;
 import com.google.gwt.dev.jjs.ast.JType;
 
@@ -57,7 +56,7 @@
         JType type = x.getType();
         JLocal local = createTempLocal(info, type);
         ctx.replaceMe(new JBinaryOperation(info, type, JBinaryOperator.ASG,
-            new JLocalRef(info, local), x));
+            local.makeRef(info), x));
       }
     }
 
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/OptimizerTestBase.java b/dev/core/test/com/google/gwt/dev/jjs/impl/OptimizerTestBase.java
index ef1bd70..a6080e8 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/OptimizerTestBase.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/OptimizerTestBase.java
@@ -358,7 +358,7 @@
             JLocal var = JProgram.createLocal(instance.getSourceInfo(), "$t", instance.getType(),
                 false, body);
 
-            JLocalRef localRef = new JLocalRef(var.getSourceInfo(), var);
+            JLocalRef localRef = var.makeRef(var.getSourceInfo());
             instance = new JBinaryOperation(instance.getSourceInfo(), localRef.getType(),
                 JBinaryOperator.ASG, localRef, instance);
           }