Reduces code size for class literal instantiations by using static factory methods.  Class and package names are now separately interned again.

Patch by: mmastrac
Review by: me


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1535 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
index 7732c06..82261db 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
@@ -40,6 +40,11 @@
     this.dims = dims;
   }
 
+  @Override
+  public String getClassLiteralFactoryMethod() {
+    return "Class.createForArray";
+  }
+
   public int getDims() {
     return dims;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
index 25f07a6..ba4fd33 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
@@ -15,19 +15,10 @@
  */
 package com.google.gwt.dev.jjs.ast;
 
-import com.google.gwt.dev.jjs.InternalCompilerException;
-
 /**
  * Java class literal expression.
  */
 public class JClassLiteral extends JLiteral {
-
-  // Matches constants in our java.lang.Class
-  private static final int PRIMITIVE = 0x00000001;
-  private static final int INTERFACE = 0x00000002;
-  private static final int ARRAY = 0x00000004;
-  private static final int ENUM = 0x00000008;
-
   private static String getClassName(String fullName) {
     int pos = fullName.lastIndexOf(".");
     return fullName.substring(pos + 1);
@@ -38,26 +29,7 @@
     return fullName.substring(0, pos + 1);
   }
 
-  private static JIntLiteral getTypeBitsLit(JProgram program, JType type) {
-    int bits;
-    if (type instanceof JArrayType) {
-      bits = ARRAY;
-    } else if (type instanceof JEnumType) {
-      bits = ENUM;
-    } else if (type instanceof JClassType) {
-      bits = 0;
-    } else if (type instanceof JInterfaceType) {
-      bits = INTERFACE;
-    } else if (type instanceof JPrimitiveType) {
-      bits = PRIMITIVE;
-    } else {
-      throw new InternalCompilerException("Unknown kind of type");
-    }
-    return program.getLiteralInt(bits);
-  }
-
-  private static JExpression getTypeNameLit(JProgram program, JType type) {
-    JExpression typeNameLit;
+  private static String getTypeName(JType type) {
     String typeName;
     if (type instanceof JArrayType) {
       typeName = type.getJsniSignatureName().replace('/', '.');
@@ -65,21 +37,7 @@
       typeName = type.getName();
     }
 
-    // Split the full class name into package + class so package strings
-    // can be merged.
-    String className = getClassName(typeName);
-    String packageName = getPackageName(typeName);
-    if (packageName.length() > 0) {
-      // use "com.example.foo." + "Foo"
-      typeNameLit = new JBinaryOperation(program, null,
-          program.getTypeJavaLangString(), JBinaryOperator.ADD,
-          program.getLiteralString(packageName),
-          program.getLiteralString(className));
-    } else {
-      // no package name could be split, just use the full name
-      typeNameLit = program.getLiteralString(typeName);
-    }
-    return typeNameLit;
+    return typeName;
   }
 
   private JExpression classObjectAllocation;
@@ -92,15 +50,15 @@
     super(program);
     refType = type;
 
-    JNewInstance classAlloc = new JNewInstance(program, null,
-        program.getTypeJavaLangClass());
-    JMethodCall call = new JMethodCall(program, null, classAlloc,
-        program.getIndexedMethod("Class.Class"));
+    String typeName = getTypeName(type);
 
-    call.getArgs().add(getTypeNameLit(program, type));
-    call.getArgs().add(getTypeBitsLit(program, type));
-
-    // TODO: enums
+    JMethod method = program.getIndexedMethod(type.getClassLiteralFactoryMethod());
+    assert method != null;
+    
+    JMethodCall call = new JMethodCall(program, null, null,
+        method);
+    call.getArgs().add(program.getLiteralString(getPackageName(typeName)));
+    call.getArgs().add(program.getLiteralString(getClassName(typeName)));
 
     classObjectAllocation = call;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
index 210939f..b023c9a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
@@ -32,6 +32,11 @@
     this.isFinal = isFinal;
   }
 
+  @Override
+  public String getClassLiteralFactoryMethod() {
+    return "Class.createForClass";
+  }
+
   public boolean isAbstract() {
     return isAbstract;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JEnumType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JEnumType.java
index efce503..ee929e4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JEnumType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JEnumType.java
@@ -34,4 +34,8 @@
 
   // TODO: implement traverse?
 
+  @Override
+  public String getClassLiteralFactoryMethod() {
+    return "Class.createForEnum";
+  }
 }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JInterfaceType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JInterfaceType.java
index 328b53e..5a7c9da 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JInterfaceType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JInterfaceType.java
@@ -26,6 +26,11 @@
     super(program, info, name);
   }
 
+  @Override
+  public String getClassLiteralFactoryMethod() {
+    return "Class.createForInterface";
+  }
+
   public boolean isAbstract() {
     return true;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNullType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNullType.java
index aad4937..bc52521 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNullType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNullType.java
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.dev.jjs.ast;
 
+import com.google.gwt.dev.jjs.InternalCompilerException;
+
 /**
  * Java null reference type.
  */
@@ -24,6 +26,11 @@
     super(program, null, "<null>");
   }
 
+  @Override
+  public String getClassLiteralFactoryMethod() {
+    throw new InternalCompilerException("Cannot get class literal for null type");
+  }
+
   public String getJavahSignatureName() {
     return "N";
   }
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 30a1c7e..d6e9aef 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
@@ -33,6 +33,11 @@
     this.wrapperTypeName = wrapperTypeName;
   }
 
+  @Override
+  public String getClassLiteralFactoryMethod() {
+    return "Class.createForPrimitive";
+  }
+
   public String getJavahSignatureName() {
     return signatureName;
   }
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 c69cc6f..e6232d7 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
@@ -32,6 +32,8 @@
     this.defaultValue = defaultValue;
   }
 
+  public abstract String getClassLiteralFactoryMethod();
+
   public JLiteral getDefaultValue() {
     return defaultValue;
   }
diff --git a/user/super/com/google/gwt/emul/java/lang/Class.java b/user/super/com/google/gwt/emul/java/lang/Class.java
index 1e4f83b..b0630aa 100644
--- a/user/super/com/google/gwt/emul/java/lang/Class.java
+++ b/user/super/com/google/gwt/emul/java/lang/Class.java
@@ -28,17 +28,80 @@
   private static final int ARRAY = 0x00000004;
   private static final int ENUM = 0x00000008;
 
-  private final String typeName;
-  private final int modifiers;
+  /**
+   * Create a Class object for an array.
+   * 
+   * @skip
+   */
+  static Class<?> createForArray(String packageName, String className) {
+    // Initialize here to avoid method inliner
+    Class<?> clazz = new Class();
+    clazz.typeName = packageName + className;
+    clazz.modifiers = ARRAY;
+    return clazz;
+  }
+
+  /**
+   * Create a Class object for a class.
+   * 
+   * @skip
+   */
+  static Class<?> createForClass(String packageName, String className) {
+    // Initialize here to avoid method inliner
+    Class<?> clazz = new Class<Object>();
+    clazz.typeName = packageName + className;
+    return clazz;
+  }
+
+  /**
+   * Create a Class object for an enum.
+   * 
+   * @skip
+   */
+  static Class<?> createForEnum(String packageName, String className) {
+    // Initialize here to avoid method inliner
+    Class<?> clazz = new Class<Object>();
+    clazz.typeName = packageName + className;
+    clazz.modifiers = ENUM;
+    return clazz;
+  }
+
+  /**
+   * Create a Class object for an interface.
+   * 
+   * @skip
+   */
+  static Class<?> createForInterface(String packageName, String className) {
+    // Initialize here to avoid method inliner
+    Class<?> clazz = new Class<Object>();
+    clazz.typeName = packageName + className;
+    clazz.modifiers = INTERFACE;
+    return clazz;
+  }
+
+  /**
+   * Create a Class object for a primitive.
+   * 
+   * @skip
+   */
+  static Class<?> createForPrimitive(String packageName, String className) {
+    // Initialize here to avoid method inliner
+    Class<?> clazz = new Class<Object>();
+    clazz.typeName = packageName + className;
+    clazz.modifiers = PRIMITIVE;
+    return clazz;
+  }
+
+  private int modifiers;
+
+  private String typeName;
 
   /**
    * Not publicly instantiable.
    * 
    * @skip
    */
-  Class(String typeName, int modifiers) {
-    this.typeName = typeName;
-    this.modifiers = modifiers;
+  private Class() {
   }
 
   public T[] getEnumConstants() {