Refactor: Move getUnderlyingType() from JReferenceType to JType.

Change-Id: Ibda106dd06c590b27c77dd00e6a2bec256a6fb19
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayRef.java
index 9d80fba..dd17d9d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayRef.java
@@ -36,7 +36,7 @@
     if (type instanceof JNullType) {
       return null;
     }
-    return (JArrayType) ((JReferenceType) type).getUnderlyingType();
+    return (JArrayType) type.getUnderlyingType();
   }
 
   public JExpression getIndexExpr() {
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 5861181..5ea9fdd 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
@@ -1006,9 +1006,7 @@
    * cggcc.JavaScriptObject respectively; otherwise returns {@code type}.
    */
   public JType normalizeJsoType(JType type) {
-    if (type instanceof JReferenceType) {
-      type = ((JReferenceType) type).getUnderlyingType();
-    }
+    type = type.getUnderlyingType();
 
     if (type instanceof JArrayType) {
       return getOrCreateArrayType(normalizeJsoType(((JArrayType) type).getLeafType()),
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java
index 21eaa45..ec658c6 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java
@@ -67,6 +67,13 @@
     return shortName;
   }
 
+  /**
+   * If this type is a non-null type, returns the underlying (original) type.
+   */
+  public JType getUnderlyingType() {
+    return this;
+  }
+
   public String getPackageName() {
     if (packageName == null) {
       int dotpos = name.lastIndexOf('.');
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
index 9615494..222565e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
@@ -523,9 +523,7 @@
    * prototype.
    */
   public boolean canBeJavaScriptObject(JType type) {
-    if (type instanceof JNonNullType) {
-      type = ((JNonNullType) type).getUnderlyingType();
-    }
+    type = type.getUnderlyingType();
     return isJavaScriptObject(type) || isSingleJsoImpl(type);
   }
 
@@ -813,9 +811,7 @@
       return null;
     }
 
-    if (type instanceof JNonNullType) {
-      type = ((JNonNullType) type).getUnderlyingType();
-    }
+    type = type.getUnderlyingType();
 
     if (!(type instanceof JDeclaredType)) {
       return null;
@@ -918,7 +914,7 @@
     return Sets.newLinkedHashSet(castableDestinationTypes);
   }
 
-  public boolean isDualJsoInterface(JReferenceType maybeDualImpl) {
+  public boolean isDualJsoInterface(JType maybeDualImpl) {
     return dualImpls.contains(maybeDualImpl.getUnderlyingType().getName());
   }
 
@@ -969,16 +965,14 @@
       return false;
     }
 
-    JReferenceType referenceType = (JReferenceType) type;
-    // compare the underlying type
-    referenceType = referenceType.getUnderlyingType();
+    type = type.getUnderlyingType();
 
     // TODO(dankurka): Null should not be recognized as a possible JSO.
     // Take a look on how to refactor this inside of the compiler
-    if (referenceType instanceof JNullType) {
+    if (type instanceof JNullType) {
       return true;
     }
-    return isJavaScriptObject(referenceType.getName());
+    return isJavaScriptObject(type.getName());
   }
 
   // Note: This method does not account for null types and only relies on static
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
index 7d5980d..5cad266 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
@@ -113,7 +113,7 @@
          */
         elementType = program.getJavaScriptObject();
       } else {
-        elementType = ((JReferenceType) elementType).getUnderlyingType();
+        elementType = elementType.getUnderlyingType();
       }
 
       elementType = program.normalizeJsoType(elementType);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ComputeCastabilityInformation.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ComputeCastabilityInformation.java
index e315b57..10e1080 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ComputeCastabilityInformation.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ComputeCastabilityInformation.java
@@ -252,11 +252,11 @@
       if (!(targetType instanceof JReferenceType)) {
         return;
       }
-      targetType = ((JReferenceType) targetType).getUnderlyingType();
+      targetType = targetType.getUnderlyingType();
 
       assert rhs.getType() instanceof JReferenceType;
 
-      JReferenceType rhsType = ((JReferenceType) rhs.getType()).getUnderlyingType();
+      JReferenceType rhsType = (JReferenceType) rhs.getType().getUnderlyingType();
       if (!recordTrivialCasts
           && typeOracle.canTriviallyCast(rhsType, (JReferenceType) targetType)) {
         // don't record a type for trivial casts that won't generate code
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ComputeInstantiatedJsoInterfaces.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ComputeInstantiatedJsoInterfaces.java
index 6b69236..af7b999 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ComputeInstantiatedJsoInterfaces.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ComputeInstantiatedJsoInterfaces.java
@@ -39,10 +39,10 @@
       JType toType = x.getCastType();
 
       if (toType instanceof JReferenceType && !(toType instanceof JNullType)) {
-        JReferenceType refType = ((JReferenceType) toType).getUnderlyingType();
-        if (program.typeOracle.willCrossCastLikeJso(refType) ||
+        toType = toType.getUnderlyingType();
+        if (program.typeOracle.willCrossCastLikeJso(toType) ||
             program.typeOracle.isOrExtendsJsType(toType, true)) {
-          instantiateJsoInterface(refType);
+          instantiateJsoInterface((JReferenceType) toType);
         }
       }
     }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
index d935dde..5e49a17 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -419,9 +419,7 @@
       JDeclaredType targetType = target.getEnclosingType();
       if (targetType == program.getTypeJavaLangString() ||
           (x.getInstance() != null &&
-              x.getInstance().getType() instanceof JReferenceType &&
-              ((JReferenceType) x.getInstance().getType()).getUnderlyingType()
-                  == program.getTypeJavaLangString())) {
+           x.getInstance().getType().getUnderlyingType() == program.getTypeJavaLangString())) {
         tryOptimizeStringCall(x, ctx, target);
       } else if (JProgram.isClinit(target)) {
         // Eliminate the call if the target is now empty.
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 8fd6510..6516fce 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
@@ -107,7 +107,7 @@
       if (!mightNeedDevirtualization(method)) {
         return;
       }
-      JType instanceType = ((JReferenceType) x.getInstance().getType()).getUnderlyingType();
+      JType instanceType = x.getInstance().getType().getUnderlyingType();
 
       if (instanceType instanceof JInterfaceType && ((JInterfaceType) instanceType).isJsType()) {
         return;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
index 8c77117..2d988f5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
@@ -39,7 +39,6 @@
 import com.google.gwt.dev.jjs.ast.JNonNullType;
 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.JStatement;
 import com.google.gwt.dev.jjs.ast.JType;
 import com.google.gwt.dev.jjs.ast.JVariableRef;
@@ -697,7 +696,7 @@
     }
 
     private boolean canBeOrdinal(JType type) {
-      JType uType = getPossiblyUnderlyingType(type);
+      JType uType = type.getUnderlyingType();
       return uType instanceof JEnumType && !ordinalizationBlackList.contains(uType);
     }
 
@@ -707,7 +706,7 @@
       }
 
       boolean nonNull = type instanceof JNonNullType;
-      JType uType = nonNull ? ((JNonNullType) type).getUnderlyingType() : type;
+      JType uType = type.getUnderlyingType();
       if (uType instanceof JArrayType) {
         JArrayType aType = (JArrayType) uType;
         JType leafType = aType.getLeafType();
@@ -922,18 +921,11 @@
   }
 
   private JEnumType getEnumTypeFromArrayLeafType(JType type) {
-    type = getPossiblyUnderlyingType(type);
+    type = type.getUnderlyingType();
     if (type instanceof JArrayType) {
       type = ((JArrayType) type).getLeafType();
       return type.isEnumOrSubclass();
     }
     return null;
   }
-
-  private JType getPossiblyUnderlyingType(JType type) {
-    if (type instanceof JReferenceType) {
-      return ((JReferenceType) type).getUnderlyingType();
-    }
-    return type;
-  }
 }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index b02a10b..c867e09 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -1393,7 +1393,7 @@
 
           boolean isFluent = type instanceof JReferenceType
               && type != program.getTypeJavaLangObject() && typeOracle.canTriviallyCast(
-                  x.getTarget().getEnclosingType(), ((JReferenceType) type).getUnderlyingType());
+                  x.getTarget().getEnclosingType(), type.getUnderlyingType());
           JsExpression qualExpr = pop();
 
           if (getter != null) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementCastsAndTypeChecks.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementCastsAndTypeChecks.java
index 503919a..69e6597 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementCastsAndTypeChecks.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementCastsAndTypeChecks.java
@@ -84,7 +84,7 @@
 
       if (toType instanceof JReferenceType) {
         JExpression curExpr = expr;
-        JReferenceType refType = ((JReferenceType) toType).getUnderlyingType();
+        JReferenceType refType = (JReferenceType) toType.getUnderlyingType();
         JReferenceType argType = (JReferenceType) expr.getType();
 
         if (refType instanceof JArrayType) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java
index 69220fd..c5030c4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java
@@ -424,9 +424,7 @@
    * </pre>
    */
   private JMethodCall createLiteralCall(SourceInfo info, JProgram program, JType type) {
-    if (type instanceof JReferenceType) {
-      type = ((JReferenceType) type).getUnderlyingType();
-    }
+    type = type.getUnderlyingType();
 
     Class<? extends JType>  typeClass = type.getClass();
     if (type.isEnumOrSubclass() != null) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ImplicitUpcastAnalyzer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplicitUpcastAnalyzer.java
index 81cdcad..9842033 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ImplicitUpcastAnalyzer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplicitUpcastAnalyzer.java
@@ -29,7 +29,6 @@
 import com.google.gwt.dev.jjs.ast.JParameter;
 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;
 import com.google.gwt.dev.jjs.ast.JThrowStatement;
 import com.google.gwt.dev.jjs.ast.JType;
@@ -182,10 +181,7 @@
   @Override
   public void endVisit(JThrowStatement x, Context ctx) {
     // all things thrown are upcast to a Throwable
-    JType type = x.getExpr().getType();
-    if (type instanceof JReferenceType) {
-      type = ((JReferenceType) type).getUnderlyingType();
-    }
+    JType type = x.getExpr().getType().getUnderlyingType();
     processIfTypesNotEqual(type, throwableType, x.getSourceInfo());
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallSpecializer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallSpecializer.java
index 7309ea9..f9ef5f9 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallSpecializer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallSpecializer.java
@@ -19,7 +19,6 @@
 import com.google.gwt.dev.jjs.ast.JMethod;
 import com.google.gwt.dev.jjs.ast.JMethodCall;
 import com.google.gwt.dev.jjs.ast.JModVisitor;
-import com.google.gwt.dev.jjs.ast.JNonNullType;
 import com.google.gwt.dev.jjs.ast.JNullType;
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JType;
@@ -57,19 +56,15 @@
       List<JType> params = specialization.getParams();
       if (params.size() == x.getArgs().size()) {
         for (int i = 0; i < params.size(); i++) {
-          JType argType = x.getArgs().get(i).getType();
-          if (argType instanceof JNonNullType) {
-            argType = ((JNonNullType) argType).getUnderlyingType();
-          }
+          JType argType = x.getArgs().get(i).getType().getUnderlyingType();
+
           if (argType instanceof JNullType) {
             return;
           }
           // see if the args passed to the function can be cast to the
           // specialization pattern
-          JType qType = params.get(i);
-          if (qType instanceof JNonNullType) {
-            qType = ((JNonNullType) qType).getUnderlyingType();
-          }
+          JType qType = params.get(i).getUnderlyingType();
+
           if (!program.typeOracle.canTriviallyCast(argType, qType)) {
             // params don't match
             return;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
index b03e8eb..fa9ecd9 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
@@ -22,8 +22,8 @@
 import com.google.gwt.dev.jjs.ast.JModVisitor;
 import com.google.gwt.dev.jjs.ast.JNewInstance;
 import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.ast.JReferenceType;
 import com.google.gwt.dev.jjs.ast.JRunAsync;
+import com.google.gwt.dev.jjs.ast.JType;
 import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
 import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
@@ -61,8 +61,7 @@
         return;
       }
 
-      JReferenceType instanceType =
-          ((JReferenceType) x.getInstance().getType()).getUnderlyingType();
+      JType instanceType = x.getInstance().getType().getUnderlyingType();
       if (!(instanceType instanceof JClassType)) {
         // Cannot tighten.
         return;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
index 48edd23..d761f21 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
@@ -653,8 +653,7 @@
       printName(target);
     } else if (x.isStaticDispatchOnly()) {
       // super() or this() call.
-      JReferenceType thisType = (JReferenceType) x.getInstance().getType();
-      thisType = thisType.getUnderlyingType();
+      JReferenceType thisType = (JReferenceType) x.getInstance().getType().getUnderlyingType();
       if (thisType == target.getEnclosingType()) {
         print(CHARS_THIS);
       } else {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeCategory.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeCategory.java
index 8fd9ec4..df7c9e6 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeCategory.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeCategory.java
@@ -45,19 +45,19 @@
     }
 
     assert type instanceof JReferenceType;
-    JReferenceType underlyingType = ((JReferenceType) type).getUnderlyingType();
-    if (underlyingType == program.getTypeJavaLangObject()) {
+    type = type.getUnderlyingType();
+    if (type == program.getTypeJavaLangObject()) {
       return TypeCategory.TYPE_JAVA_LANG_OBJECT;
-    } else if (underlyingType == program.getTypeJavaLangString()) {
+    } else if (type == program.getTypeJavaLangString()) {
       return TypeCategory.TYPE_JAVA_LANG_STRING;
-    } else if (program.typeOracle.willCrossCastLikeJso(underlyingType)) {
+    } else if (program.typeOracle.willCrossCastLikeJso(type)) {
       return TypeCategory.TYPE_JSO;
-    } else if (program.typeOracle.isDualJsoInterface(underlyingType) ||
-        program.typeOracle.hasLiveImplementors(underlyingType) &&
-        program.typeOracle.isOrExtendsJsType(underlyingType, false) &&
-        !program.typeOracle.isOrExtendsJsType(underlyingType, true)) {
+    } else if (program.typeOracle.isDualJsoInterface(type) ||
+        program.typeOracle.hasLiveImplementors(type) &&
+        program.typeOracle.isOrExtendsJsType(type, false) &&
+        !program.typeOracle.isOrExtendsJsType(type, true)) {
       return TypeCategory.TYPE_JAVA_OBJECT_OR_JSO;
-    } else if (program.typeOracle.isOrExtendsJsType(underlyingType, true)) {
+    } else if (program.typeOracle.isOrExtendsJsType(type, true)) {
       return TypeCategory.TYPE_JS_INTERFACE;
     }
     return TypeCategory.TYPE_JAVA_OBJECT;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/codesplitter/ReplaceRunAsyncs.java b/dev/core/src/com/google/gwt/dev/jjs/impl/codesplitter/ReplaceRunAsyncs.java
index 189d643..c316d07 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/codesplitter/ReplaceRunAsyncs.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/codesplitter/ReplaceRunAsyncs.java
@@ -105,8 +105,7 @@
         runAsyncCall.addArg(new JNumericEntry(info, "RunAsyncFragmentIndex", splitPoint));
         runAsyncCall.addArg(asyncCallback);
 
-        JReferenceType callbackType = (JReferenceType) asyncCallback.getType();
-        callbackType = callbackType.getUnderlyingType();
+        JReferenceType callbackType = (JReferenceType) asyncCallback.getType().getUnderlyingType();
         JMethod callbackMethod;
         if (callbackType instanceof JClassType) {
           callbackMethod =