Temporarily rolling back r10435 due to issue with uninstantiable type associated with a class literal getting pruned.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10436 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java b/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java
index 97cd1d7..368acec 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java
@@ -108,11 +108,6 @@
   int getQueryId();
 
   /**
-   * Returns the seedId for types.
-   */
-  int getSeedId();
-
-  /**
    * Returns the line number on which the symbol was originally declared or
    * <code>-1</code> if the line number is unknown.
    */
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
index 78cfb0c..fc57185 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
@@ -32,15 +32,15 @@
 public class StandardSymbolData implements SymbolData {
 
   public static StandardSymbolData forClass(String className, String uriString,
-      int lineNumber, int queryId, CastableTypeMap castableTypeMap, int seedId) {
+      int lineNumber, int queryId, CastableTypeMap castableTypeMap) {
     return new StandardSymbolData(className, null, null, uriString, lineNumber,
-        queryId, castableTypeMap, seedId);
+        queryId, castableTypeMap);
   }
 
   public static StandardSymbolData forMember(String className,
       String memberName, String methodSig, String uriString, int lineNumber) {
     return new StandardSymbolData(className, memberName, methodSig, uriString,
-        lineNumber, 0, null, -1);
+        lineNumber, 0, null);
   }
 
   public static String toUriString(String fileName) {
@@ -63,12 +63,11 @@
   private String sourceUri;
   private String symbolName;
   private int queryId;
-  private int seedId;
   private CastableTypeMap castableTypeMap;
 
   private StandardSymbolData(String className, String memberName,
       String methodSig, String sourceUri, int sourceLine, int queryId, 
-      CastableTypeMap castableTypeMap, int seedId) {
+      CastableTypeMap castableTypeMap) {
     assert className != null && className.length() > 0 : "className";
     assert memberName != null || methodSig == null : "methodSig without memberName";
     assert sourceLine >= -1 : "sourceLine: " + sourceLine;
@@ -80,7 +79,6 @@
     this.sourceLine = sourceLine;
     this.queryId = queryId;
     this.castableTypeMap = castableTypeMap;
-    this.seedId = seedId;
   }
   
   public CastableTypeMap getCastableTypeMap() {
@@ -109,10 +107,6 @@
     return queryId;
   }
 
-  public int getSeedId() {
-    return seedId;
-  }
-
   public int getSourceLine() {
     return sourceLine;
   }
@@ -167,7 +161,6 @@
     symbolName = in.readUTF();
     queryId = in.readInt();
     castableTypeMap = (CastableTypeMap) in.readObject();
-    seedId = in.readInt();
   }
 
   /**
@@ -196,6 +189,5 @@
     out.writeUTF(symbolName);
     out.writeInt(queryId);
     out.writeObject(castableTypeMap);
-    out.writeInt(seedId);
   }
 }
diff --git a/dev/core/src/com/google/gwt/dev/cfg/StaticPropertyOracle.java b/dev/core/src/com/google/gwt/dev/cfg/StaticPropertyOracle.java
index a32d252..47906e4 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/StaticPropertyOracle.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/StaticPropertyOracle.java
@@ -22,6 +22,9 @@
 import com.google.gwt.core.ext.TreeLogger;
 
 import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.TreeSet;
 
 /**
@@ -152,7 +155,7 @@
           possibleValues.add(v);
         }
         return new DefaultSelectionProperty(value, prop.getFallback(), name,
-            possibleValues, prop.getFallbackValuesMap());
+            possibleValues, (Map<String, List<Set<String>>>) prop.getFallbackValuesMap());
       }
     }
 
diff --git a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java
index ea413fb..ee1c256 100644
--- a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java
+++ b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java
@@ -302,12 +302,11 @@
       StringBuilder code = new StringBuilder();
       code.append("package java.lang;\n");
       code.append("public class Object {\n");
-      code.append("  private Class<?> ___clazz;");
       code.append("  public boolean equals(Object that){return this == that;}");
       code.append("  public int hashCode() { return 0; }\n");
       code.append("  public String toString() { return \"Object\"; }\n");
       code.append("  public Object clone() { return this; } ");
-      code.append("  public Class<?> getClass() { return ___clazz; } ");
+      code.append("  public Class<?> getClass() { return Object.class; } ");
       code.append("}\n");
       return code;
     }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index 67d86c7..bac3201 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -99,7 +99,6 @@
 import com.google.gwt.dev.jjs.impl.Pruner;
 import com.google.gwt.dev.jjs.impl.RecordRebinds;
 import com.google.gwt.dev.jjs.impl.RemoveEmptySuperCalls;
-import com.google.gwt.dev.jjs.impl.ReplaceGetClassOverrides;
 import com.google.gwt.dev.jjs.impl.ReplaceRebinds;
 import com.google.gwt.dev.jjs.impl.ReplaceRunAsyncs;
 import com.google.gwt.dev.jjs.impl.ResolveRebinds;
@@ -308,8 +307,6 @@
       // (6) Perform further post-normalization optimizations
       // Prune everything
       Pruner.exec(jprogram, false);
-      // prune all Object.getClass() overrides and replace with inline field ref
-      ReplaceGetClassOverrides.exec(jprogram);
 
       // (7) Generate a JavaScript code DOM from the Java type declarations
       jprogram.typeOracle.recomputeAfterOptimizations();
@@ -338,7 +335,7 @@
       /*
        * Creates new variables, must run before code splitter and namer.
        */
-      JsStackEmulator.exec(jprogram, jsProgram, propertyOracles, jjsmap);
+      JsStackEmulator.exec(jsProgram, propertyOracles);
 
       /*
        * Work around Safari 5 bug by rewriting a >> b as ~~a >> b.
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 eb6b85e..1363eb8 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
@@ -64,21 +64,6 @@
       "com.google.gwt.lang.CollapsedPropertyHolder", "com.google.gwt.lang.Exceptions",
       "com.google.gwt.lang.LongLib", "com.google.gwt.lang.Stats", "com.google.gwt.lang.Util"));
 
-  /*
-   * Types which are not referenced by any Java code, but are required to exist
-   * after Java optimizations have run in order to be used by backend
-   * code-generation. These classes and their members, are considered live
-   * by ControlFlowAnalysis, at all times. Immortal types always live in the
-   * initial fragment and their definitions are hoisted to appear before all
-   * other types. Only static methods and fields are allowed, and no clinits
-   * are run. Field initializers must be primitives, literals, or one of
-   * JSO.createObject() or JSO.createArray().
-   *
-   * Classes are inserted into the JsAST in the order they appear in the Set.
-   */
-  public static final Set<String> IMMORTAL_CODEGEN_TYPES_SET = new LinkedHashSet<String>(Arrays.asList(
-      "com.google.gwt.lang.SeedUtil"));
-
   public static final Set<String> INDEX_TYPES_SET = new LinkedHashSet<String>(Arrays.asList(
       "java.io.Serializable", "java.lang.Object", "java.lang.String", "java.lang.Class",
       "java.lang.CharSequence", "java.lang.Cloneable", "java.lang.Comparable", "java.lang.Enum",
@@ -113,7 +98,6 @@
       new HashMap<String, JPrimitiveType>();
 
   static {
-    CODEGEN_TYPES_SET.addAll(IMMORTAL_CODEGEN_TYPES_SET);
     INDEX_TYPES_SET.addAll(CODEGEN_TYPES_SET);
 
     /*
@@ -318,7 +302,6 @@
   }
 
   public final List<JClassType> codeGenTypes = new ArrayList<JClassType>();
-  public final List<JClassType> immortalCodeGenTypes = new ArrayList<JClassType>();
 
   public final JTypeOracle typeOracle = new JTypeOracle(this);
 
@@ -331,8 +314,6 @@
 
   private IdentityHashMap<JReferenceType, JsCastMap> castMaps;
 
-  private Map<JType, JField> classLiteralFields;
-
   /**
    * A factory to create correlations.
    */
@@ -410,11 +391,6 @@
     if (CODEGEN_TYPES_SET.contains(name)) {
       codeGenTypes.add((JClassType) type);
     }
-
-    if (IMMORTAL_CODEGEN_TYPES_SET.contains(name)) {
-      immortalCodeGenTypes.add((JClassType) type);
-    }
-    
     if (INDEX_TYPES_SET.contains(name)) {
       indexedTypes.put(type.getShortName(), type);
       for (JMethod method : type.getMethods()) {
@@ -754,10 +730,6 @@
     return castMaps.get(referenceType);
   }
 
-  public JField getClassLiteralField(JType type) {
-    return classLiteralFields.get(isJavaScriptObject(type) ? getJavaScriptObject() : type);
-  }
-
   public String getClassLiteralName(JType type) {
     return type.getJavahSignatureName() + "_classLit";
   }
@@ -1039,10 +1011,6 @@
     }
   }
 
-  public void recordClassLiteralFields(Map<JType, JField> classLiteralFields) {
-    this.classLiteralFields = classLiteralFields;
-  }
-
   public void recordQueryIds(Map<JReferenceType, Integer> queryIdsByType,
       List<JReferenceType> typesByQueryId) {
     this.queryIdsByType = queryIdsByType;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JSeedIdOf.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JSeedIdOf.java
deleted file mode 100644
index ab1ca95..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JSeedIdOf.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast;
-
-import com.google.gwt.dev.jjs.SourceInfo;
-
-/**
- * An AST node whose evaluation results in the seedId of its node.
- */
-public class JSeedIdOf extends JNameOf {
-
-  public JSeedIdOf(SourceInfo info, JClassType stringType, HasName node) {
-    super(info, stringType, node);
-  }
-
-  public void traverse(JVisitor visitor, Context ctx) {
-    if (visitor.visit(this, ctx)) {
-      // Intentionally not visiting referenced node
-    }
-    visitor.endVisit(this, ctx);
-  }
-
-}
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 8850cb6..b9095eb 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
@@ -565,10 +565,6 @@
     return results;
   }
 
-  public Set<JReferenceType> getInstantiatedTypes() {
-    return instantiatedTypes;
-  }
-
   public JMethod getPolyMethod(JClassType type, String signature) {
     return getOrCreatePolyMap(type).get(signature);
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
index 8e17e97..885d8e7 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
@@ -417,10 +417,6 @@
     endVisit((JExpression) x, ctx);
   }
 
-  public void endVisit(JSeedIdOf x, Context ctx) {
-    endVisit((JNameOf) x, ctx);
-  }
-
   public void endVisit(JsCastMap x, Context ctx) {
     endVisit((JsonArray) x, ctx);
   }
@@ -745,10 +741,6 @@
     return visit((JExpression) x, ctx);
   }
 
-  public boolean visit(JSeedIdOf x, Context ctx) {
-    return visit((JNameOf) x, ctx);
-  }
-
   public boolean visit(JsCastMap x, Context ctx) {
     return visit((JsonArray) x, ctx);
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java
index 4c85a0a..7730084 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java
@@ -24,7 +24,6 @@
 import com.google.gwt.dev.jjs.ast.Context;
 import com.google.gwt.dev.jjs.ast.JArrayType;
 import com.google.gwt.dev.jjs.ast.JClassLiteral;
-import com.google.gwt.dev.jjs.ast.JClassType;
 import com.google.gwt.dev.jjs.ast.JDeclaredType;
 import com.google.gwt.dev.jjs.ast.JExpression;
 import com.google.gwt.dev.jjs.ast.JField;
@@ -455,7 +454,7 @@
     cfa.setDependencyRecorder(dependencyRecorder);
     cfa.traverseEntryMethods();
     traverseClassArray(jprogram, cfa);
-    traverseImmortalTypes(jprogram, cfa);
+
     dependencyRecorder.endDependencyGraph();
     return cfa;
   }
@@ -581,21 +580,6 @@
     }
   }
 
-  /**
-   * Any immortal codegen types must be part of the initial download.
-   */
-  private static void traverseImmortalTypes(JProgram jprogram,
-      ControlFlowAnalyzer cfa) {
-    for (JClassType type : jprogram.immortalCodeGenTypes) {
-      cfa.traverseFromInstantiationOf(type);
-      for (JMethod method : type.getMethods()) {
-        if (!method.needsVtable()) {
-          cfa.traverseFrom(method);
-        }
-      }
-    }
-  }
-
   private static <T> Set<T> union(Set<? extends T> set1, Set<? extends T> set2) {
     Set<T> union = new HashSet<T>();
     union.addAll(set1);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
index f9b3aaa..36c534f 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
@@ -518,16 +518,6 @@
       return false;
     }
 
-    private void maybeRescueClassLiteral(JReferenceType type) {
-      if (liveFieldsAndMethods.contains(getClassMethod) || liveFieldsAndMethods.contains(getClassField)) {
-        // getClass() already live so rescue class literal immediately
-        rescue(program.getClassLiteralField(type));
-      } else {
-        // getClass() not live yet, so mark for later rescue
-        classLiteralsToBeRescuedIfGetClassIsLive.add(type);
-      }
-    }
-
     /**
      * Subclasses of JavaScriptObject are never instantiated directly. They are
      * implicitly created when a JSNI method passes a reference to an existing
@@ -584,9 +574,6 @@
             maybeRescueJavaScriptObjectPassingIntoJava(method.getType());
           }
           rescueOverridingMethods(method);
-          if (method == getClassMethod) {
-            rescueClassLiteralsIfGetClassIsLive();
-          }
           return true;
         }
       }
@@ -607,8 +594,6 @@
       boolean doVisit = false;
       if (isInstantiated && !instantiatedTypes.contains(type)) {
         instantiatedTypes.add(type);
-        maybeRescueClassLiteral(type);
-
         doVisit = true;
       }
 
@@ -638,10 +623,6 @@
       if (var != null) {
         if (liveFieldsAndMethods.add(var)) {
           membersToRescueIfTypeIsInstantiated.remove(var);
-          if (var == getClassField) {
-            rescueClassLiteralsIfGetClassIsLive();
-          }
-
           if (isStaticFieldInitializedToLiteral(var)) {
             /*
              * Rescue literal initializers when the field is rescued, not when
@@ -765,18 +746,6 @@
       }
     }
 
-    private void rescueClassLiteralsIfGetClassIsLive() {
-      if (classLiteralsToBeRescuedIfGetClassIsLive != null) {
-        // guard against re-entrant calls. This only needs to run once.
-        Set<JReferenceType> toRescue = classLiteralsToBeRescuedIfGetClassIsLive;
-        classLiteralsToBeRescuedIfGetClassIsLive = null;
-
-        for (JReferenceType classLit : toRescue) {
-          maybeRescueClassLiteral(classLit);
-        }
-      }
-    }
-
     /**
      * If the type is instantiable, rescue any of its virtual methods that a
      * previously seen method call could call.
@@ -838,13 +807,6 @@
 
   private final JMethod asyncFragmentOnLoad;
   private final JDeclaredType baseArrayType;
-
-  /**
-   * Schrodinger set of classLiterals to be rescued if type is instantiated AND getClass()
-   * is live.
-   */
-  private Set<JReferenceType> classLiteralsToBeRescuedIfGetClassIsLive = new HashSet<JReferenceType>();
-
   private DependencyRecorder dependencyRecorder;
   private Set<JField> fieldsWritten = new HashSet<JField>();
   private Set<JReferenceType> instantiatedTypes = new HashSet<JReferenceType>();
@@ -865,8 +827,6 @@
    */
   private Map<JMethod, List<JMethod>> methodsThatOverrideMe;
 
-  private final JField getClassField;
-  private final JMethod getClassMethod;
   private final JProgram program;
   private Set<JReferenceType> referencedTypes = new HashSet<JReferenceType>();
   private final RescueVisitor rescuer = new RescueVisitor();
@@ -891,8 +851,6 @@
           new HashMap<JParameter, List<JExpression>>(cfa.argsToRescueIfParameterRead);
     }
     methodsThatOverrideMe = cfa.methodsThatOverrideMe;
-    getClassField = program.getIndexedField("Object.___clazz");
-    getClassMethod = program.getIndexedMethod("Object.getClass");
   }
 
   public ControlFlowAnalyzer(JProgram program) {
@@ -900,8 +858,6 @@
     asyncFragmentOnLoad = program.getIndexedMethod("AsyncFragmentLoader.onLoad");
     runAsyncOnsuccess = program.getIndexedMethod("RunAsyncCallback.onSuccess");
     baseArrayType = program.getIndexedType("Array");
-    getClassField = program.getIndexedField("Object.___clazz");
-    getClassMethod = program.getIndexedMethod("Object.getClass");
     buildMethodsOverriding();
   }
 
@@ -1008,15 +964,6 @@
     runAsync.traverseOnSuccess(rescuer);
   }
 
-  /**
-   * Traverse the fragments for all runAsyncs.
-   */
-  public void traverseFromRunAsyncs() {
-    for (JRunAsync runAsync : program.getRunAsyncs()) {
-      traverseFromRunAsync(runAsync);
-    }
-  }
-
   private void buildMethodsOverriding() {
     methodsThatOverrideMe = new HashMap<JMethod, List<JMethod>>();
     for (JDeclaredType type : program.getDeclaredTypes()) {
@@ -1032,4 +979,13 @@
       }
     }
   }
+
+  /**
+   * Traverse the fragments for all runAsyncs.
+   */
+  private void traverseFromRunAsyncs() {
+    for (JRunAsync runAsync : program.getRunAsyncs()) {
+      traverseFromRunAsync(runAsync);
+    }
+  }
 }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
index 8d75fc9..a522b6e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
@@ -31,15 +31,15 @@
 import com.google.gwt.dev.js.ast.JsExpression;
 import com.google.gwt.dev.js.ast.JsFunction;
 import com.google.gwt.dev.js.ast.JsInvocation;
-import com.google.gwt.dev.js.ast.JsModVisitor;
 import com.google.gwt.dev.js.ast.JsName;
 import com.google.gwt.dev.js.ast.JsNameRef;
+import com.google.gwt.dev.js.ast.JsNew;
 import com.google.gwt.dev.js.ast.JsNumberLiteral;
+import com.google.gwt.dev.js.ast.JsObjectLiteral;
 import com.google.gwt.dev.js.ast.JsProgram;
 import com.google.gwt.dev.js.ast.JsStatement;
 import com.google.gwt.dev.js.ast.JsVars;
 import com.google.gwt.dev.js.ast.JsVars.JsVar;
-import com.google.gwt.dev.js.ast.JsVisitable;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -238,31 +238,21 @@
      * The type whose vtables can currently be installed.
      */
     JClassType currentVtableType = null;
-    JClassType pendingVtableType = null;
-    JsExprStmt pendingDefineSeed = null;
 
-
-      // Since we haven't run yet.
+    // Since we haven't run yet.
     assert jsprogram.getFragmentCount() == 1;
-
     List<JsStatement> stats = jsprogram.getGlobalBlock().getStatements();
     for (JsStatement stat : stats) {
-
       boolean keepIt;
       JClassType vtableTypeAssigned = vtableTypeAssigned(stat);
-      if (vtableTypeAssigned != null
-          && livenessPredicate.isLive(vtableTypeAssigned)) {
-        boolean[] anyCtorsSetup = new boolean[1];
-        JsExprStmt result = maybeRemoveCtorsFromDefineSeedStmt(livenessPredicate,
-            alreadyLoadedPredicate, stat, anyCtorsSetup);
-        boolean anyWorkDone = anyCtorsSetup[0]
-            || !alreadyLoadedPredicate.isLive(vtableTypeAssigned);
-        if (anyWorkDone) {
+      if (vtableTypeAssigned != null && livenessPredicate.isLive(vtableTypeAssigned)) {
+        JsExprStmt result =
+            extractPrototypeSetup(livenessPredicate, alreadyLoadedPredicate, stat,
+                vtableTypeAssigned);
+        if (result != null) {
           stat = result;
           keepIt = true;
         } else {
-          pendingDefineSeed = result;
-          pendingVtableType = vtableTypeAssigned;
           keepIt = false;
         }
       } else if (containsRemovableVars(stat)) {
@@ -280,11 +270,8 @@
         }
         JClassType vtableType = vtableTypeNeeded(stat);
         if (vtableType != null && vtableType != currentVtableType) {
-          assert pendingVtableType == vtableType;
-          extractedStats.add(pendingDefineSeed);
-          currentVtableType = pendingVtableType;
-          pendingDefineSeed = null;
-          pendingVtableType = null;
+          extractedStats.add(vtableStatFor(vtableType));
+          currentVtableType = vtableType;
         }
         extractedStats.add(stat);
       }
@@ -336,6 +323,57 @@
     return false;
   }
 
+  /**
+   * Weird case: the seed function's liveness is associated with the type
+   * itself. However, individual constructors can have a liveness that is a
+   * subset of the type's liveness. We essentially have to break up the
+   * prototype chain according to exactly what's newly live.
+   */
+  private JsExprStmt extractPrototypeSetup(final LivenessPredicate livenessPredicate,
+      final LivenessPredicate alreadyLoadedPredicate, JsStatement stat,
+      final JClassType vtableTypeAssigned) {
+    final boolean[] anyLiveCode = new boolean[1];
+    Cloner c = new Cloner() {
+      @Override
+      public void endVisit(JsBinaryOperation x, JsContext ctx) {
+        JsExpression rhs = stack.pop();
+        JsNameRef lhs = (JsNameRef) stack.pop();
+        if (rhs instanceof JsNew || rhs instanceof JsObjectLiteral) {
+          // The super op is being assigned to the seed prototype.
+          if (alreadyLoadedPredicate.isLive(vtableTypeAssigned)) {
+            stack.push(lhs);
+            return;
+          } else {
+            anyLiveCode[0] = true;
+          }
+        } else if (lhs.getQualifier() == null) {
+          // The underscore is being assigned to.
+          assert "_".equals(lhs.getIdent());
+        } else {
+          // A constructor function is being assigned to.
+          assert "prototype".equals(lhs.getIdent());
+          JsNameRef ctorRef = (JsNameRef) lhs.getQualifier();
+          JConstructor ctor = (JConstructor) map.nameToMethod(ctorRef.getName());
+          assert ctor != null;
+          if (livenessPredicate.isLive(ctor) && !alreadyLoadedPredicate.isLive(ctor)) {
+            anyLiveCode[0] = true;
+          } else {
+            stack.push(rhs);
+            return;
+          }
+        }
+
+        JsBinaryOperation toReturn = new JsBinaryOperation(x.getSourceInfo(), x.getOperator());
+        toReturn.setArg2(rhs);
+        toReturn.setArg1(lhs);
+        stack.push(toReturn);
+      }
+    };
+    c.accept(((JsExprStmt) stat).getExpression());
+    JsExprStmt result = anyLiveCode[0] ? c.getExpression().makeStmt() : null;
+    return result;
+  }
+
   private boolean isLive(JsStatement stat, LivenessPredicate livenessPredicate) {
     JClassType type = map.typeForStatement(stat);
     if (type != null) {
@@ -382,42 +420,6 @@
   }
 
   /**
-   * Weird case: the seed function's liveness is associated with the type
-   * itself. However, individual constructors can have a liveness that is a
-   * subset of the type's liveness.
-   */
-  private JsExprStmt maybeRemoveCtorsFromDefineSeedStmt(
-      final LivenessPredicate livenessPredicate,
-      final LivenessPredicate alreadyLoadedPredicate, JsStatement stat,
-      final boolean[] anyCtorsSetup) {
-    Cloner c = new Cloner();
-    c.accept(((JsExprStmt) stat).getExpression());
-    JsExprStmt result = c.getExpression().makeStmt();
-    new JsModVisitor() {
-      public void endVisit(JsNameRef x, JsContext ctx) {
-        JMethod maybeCtor = map.nameToMethod(x.getName());
-        if (maybeCtor instanceof JConstructor) {
-          JConstructor ctor = (JConstructor) maybeCtor;
-          if (!livenessPredicate.isLive(ctor)
-              || alreadyLoadedPredicate.isLive(ctor)) {
-            ctx.removeMe();
-          } else {
-            anyCtorsSetup[0] = true;
-          }
-        }
-      };
-
-      /**
-       * Overridden to allow insert/remove on the varargs portion.
-       */
-      protected <T extends JsVisitable> void doAcceptList(List<T> collection) {
-        doAcceptWithInsertRemove(collection);
-      };
-    }.accept(result);
-    return result;
-  }
-
-  /**
    * Return the Java method corresponding to <code>stat</code>, or
    * <code>null</code> if there isn't one. It recognizes JavaScript of the form
    * <code>function foo(...) { ...}</code>, where <code>foo</code> is the name
@@ -463,30 +465,40 @@
   }
 
   /**
-   * If <code>state</code> is of the form <code>_ = String.prototype</code>,
-   * then return <code>String</code>. If the form is
-   * <code>defineSeed(id, superId, cTM, ctor1, ctor2, ...)</code> return the type
-   * corresponding to that id. Otherwise return <code>null</code>.
+   * Compute a statement that can be used to set up for installing instance
+   * methods into a vtable. It will be of the form
+   * <code>_ = foo.prototype</code>, where <code>foo</code> is the constructor
+   * function for <code>vtableType</code>.
+   */
+  private JsStatement vtableStatFor(JClassType vtableType) {
+    JsNameRef prototypeField =
+        new JsNameRef(jsprogram.createSourceInfoSynthetic(FragmentExtractor.class), "prototype");
+    JsExpression constructorRef;
+    SourceInfo sourceInfoVtableSetup = jsprogram.createSourceInfoSynthetic(FragmentExtractor.class);
+    if (vtableType == jprogram.getTypeJavaLangString()) {
+      // The methods of java.lang.String are put onto JavaScript's String
+      // prototype
+      SourceInfo sourceInfoConstructorRef =
+          jsprogram.createSourceInfoSynthetic(FragmentExtractor.class);
+      constructorRef = new JsNameRef(sourceInfoConstructorRef, "String");
+    } else {
+      constructorRef = map.nameForType(vtableType).makeRef(sourceInfoVtableSetup);
+    }
+    prototypeField.setQualifier(constructorRef);
+    SourceInfo underlineSourceInfo = jsprogram.createSourceInfoSynthetic(FragmentExtractor.class);
+    return (new JsBinaryOperation(sourceInfoVtableSetup, JsBinaryOperator.ASG, jsprogram.getScope()
+        .declareName("_").makeRef(underlineSourceInfo), prototypeField)).makeStmt();
+  }
+
+  /**
+   * If <code>state</code> is of the form <code>_ = Foo.prototype = exp</code>,
+   * then return <code>Foo</code>. Otherwise return <code>null</code>.
    */
   private JClassType vtableTypeAssigned(JsStatement stat) {
     if (!(stat instanceof JsExprStmt)) {
       return null;
     }
     JsExprStmt expr = (JsExprStmt) stat;
-    if (expr.getExpression() instanceof JsInvocation) {
-      // Handle a defineSeed call.
-      JsInvocation call = (JsInvocation) expr.getExpression();
-      if (!(call.getQualifier() instanceof JsNameRef)) {
-        return null;
-      }
-      JsNameRef func = (JsNameRef) call.getQualifier();
-      if (func.getName() != jsprogram.getIndexedFunction("SeedUtil.defineSeed").getName()) {
-        return null;
-      }
-      return map.typeForStatement(stat);
-    }
-
-    // Handle String.
     if (!(expr.getExpression() instanceof JsBinaryOperation)) {
       return null;
     }
@@ -498,26 +510,30 @@
       return null;
     }
     JsNameRef lhs = (JsNameRef) binExpr.getArg1();
-    JsName underBar = jsprogram.getScope().findExistingName("_");
-    assert underBar != null;
-    if (lhs.getName() != underBar) {
+    if (lhs.getQualifier() != null) {
       return null;
     }
-    if (!(binExpr.getArg2() instanceof JsNameRef)) {
+    if (lhs.getName() == null) {
+      return null;
+    }
+    if (!lhs.getName().getShortIdent().equals("_")) {
+      return null;
+    }
+    if (!(binExpr.getArg2() instanceof JsBinaryOperation)) {
+      return null;
+    }
+    JsBinaryOperation binExprRhs = (JsBinaryOperation) binExpr.getArg2();
+    if (binExprRhs.getOperator() != JsBinaryOperator.ASG) {
+      return null;
+    }
+    if (!(binExprRhs.getArg1() instanceof JsNameRef)) {
+      return null;
+    }
+    JsNameRef middleNameRef = (JsNameRef) binExprRhs.getArg1();
+    if (!middleNameRef.getName().getShortIdent().equals("prototype")) {
       return null;
     }
 
-    JsNameRef rhsRef = (JsNameRef) binExpr.getArg2();
-    if (!(rhsRef.getQualifier() instanceof JsNameRef)) {
-      return null;
-    }
-    if (!((JsNameRef) rhsRef.getQualifier()).getShortIdent().equals("String")) {
-      return null;
-    }
-
-    if (!rhsRef.getName().getShortIdent().equals("prototype")) {
-      return null;
-    }
     return map.typeForStatement(stat);
   }
 
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 3c4883f..87a6aa7 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
@@ -514,17 +514,14 @@
             // Just use JavaScriptObject's implementation for all subclasses.
             currentClass.getMethods().remove(2);
           } else {
-            if (currentClass == program.getIndexedType("Array")) {
-              /*
-              * Don't implement, fall through to Object.getClass(). Array emulation code
-              * in com.google.gwt.lang.Array invokes Array.getClass() and expects to get the
-              * class literal for the actual runtime type of the array (e.g. Foo[].class) and
-              * not Array.class.
-              */
-              currentClass.getMethods().remove(2);
+            tryFindUpRefs(method);
+            SourceInfo info = method.getSourceInfo();
+            if (isScript(program) && currentClass == program.getIndexedType("Array")) {
+              // Special implementation: return this.arrayClass
+              implementMethod(method, new JFieldRef(info, new JThisRef(info,
+                  (JClassType) currentClass), program.getIndexedField("Array.arrayClass"),
+                  currentClass));
             } else {
-              tryFindUpRefs(method);
-              SourceInfo info = method.getSourceInfo();
               implementMethod(method, new JClassLiteral(info.makeChild(), currentClass));
             }
           }
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 708261b..287f1c1 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
@@ -76,7 +76,6 @@
 import com.google.gwt.dev.jjs.ast.JReboundEntryPoint;
 import com.google.gwt.dev.jjs.ast.JReferenceType;
 import com.google.gwt.dev.jjs.ast.JReturnStatement;
-import com.google.gwt.dev.jjs.ast.JSeedIdOf;
 import com.google.gwt.dev.jjs.ast.JStatement;
 import com.google.gwt.dev.jjs.ast.JSwitchStatement;
 import com.google.gwt.dev.jjs.ast.JThisRef;
@@ -139,7 +138,6 @@
 import com.google.gwt.dev.js.ast.JsReturn;
 import com.google.gwt.dev.js.ast.JsRootScope;
 import com.google.gwt.dev.js.ast.JsScope;
-import com.google.gwt.dev.js.ast.JsSeedIdOf;
 import com.google.gwt.dev.js.ast.JsStatement;
 import com.google.gwt.dev.js.ast.JsSwitch;
 import com.google.gwt.dev.js.ast.JsSwitchMember;
@@ -389,7 +387,7 @@
          * as var foo = function blah() {} and introduce a separate scope for
          * the function's name according to EcmaScript-262, but this would mess
          * up stack traces by allowing two inner scope function names to
-         * obfuscate to the same identifier, making function names no longer a
+         * onfuscate to the same identifier, making function names no longer a
          * 1:1 mapping to obfuscated symbols. Leaving them in global scope
          * causes no harm.
          */
@@ -406,7 +404,6 @@
             Maps.put(indexedFunctions, x.getEnclosingType().getShortName() + "." + x.getName(),
                 jsFunction);
       }
-
       return true;
     }
 
@@ -501,8 +498,7 @@
 
       StandardSymbolData symbolData =
           StandardSymbolData.forClass(x.getName(), x.getSourceInfo().getFileName(), x
-              .getSourceInfo().getStartLine(), program.getQueryId(x), castableTypeMap,
-              x instanceof JClassType ? getSeedId((JClassType) x) : -1);
+              .getSourceInfo().getStartLine(), program.getQueryId(x), castableTypeMap);
       assert !symbolTable.containsKey(symbolData);
       symbolTable.put(symbolData, jsName);
     }
@@ -571,7 +567,6 @@
         JsName name = topScope.declareName("Q$" + longName, "Q$" + shortName);
         namesByQueryId.add(name);
       }
-      // TODO(cromwellian): see about moving this into an immortal type
       StringBuilder sb = new StringBuilder();
       sb.append("function makeCastMap(a) {");
       sb.append("  var result = {};");
@@ -611,16 +606,12 @@
 
     private final JsName prototype = objectScope.declareName("prototype");
 
-
     {
       globalTemp.setObfuscatable(false);
       prototype.setObfuscatable(false);
       arrayLength.setObfuscatable(false);
     }
 
-    public GenerateJavaScriptVisitor() {
-    }
-    
     @Override
     public void endVisit(JAbsentArrayDimension x, Context ctx) {
       throw new InternalCompilerException("Should not get here.");
@@ -727,11 +718,6 @@
         return;
       }
 
-      if (program.immortalCodeGenTypes.contains(x)) {
-        // Handled in generateImmortalTypes
-        return;
-      }
-
       alreadyRan.add(x);
 
       List<JsFunction> jsFuncs = popList(x.getMethods().size()); // methods
@@ -751,7 +737,6 @@
       // declare all methods into the global scope
       for (int i = 0; i < jsFuncs.size(); ++i) {
         JsFunction func = jsFuncs.get(i);
-
         // don't add polymorphic JsFuncs, inline decl into vtable assignment
         if (func != null && !polymorphicJsFunctions.contains(func)) {
           globalStmts.add(func.makeStmt());
@@ -1271,7 +1256,7 @@
 
       // Long lits must go at the top, they can be constant field initializers.
       generateLongLiterals(vars);
-      generateImmortalTypes(vars);
+
       generateQueryIdConstants(vars);
 
       // Class objects, but only if there are any.
@@ -1309,13 +1294,6 @@
     }
 
     @Override
-    public void endVisit(JSeedIdOf x, Context ctx) {
-      JsName name = names.get(x.getNode());
-      assert name != null : "Missing JsName for " + x.getNode().getName();
-      push(new JsSeedIdOf(x.getSourceInfo(), name));
-    }
-
-    @Override
     public void endVisit(JsCastMap x, Context ctx) {
       super.endVisit(x, ctx);
       JsArrayLiteral arrayLit = (JsArrayLiteral) pop();
@@ -1436,11 +1414,6 @@
         return false;
       }
 
-      if (program.immortalCodeGenTypes.contains(x)) {
-        // Handled in generateImmortalTypes
-        return false;
-      }
-
       // force super type to generate code first, this is required for prototype
       // chaining to work properly
       if (x.getSuperClass() != null && !alreadyRan.contains(x)) {
@@ -1471,7 +1444,6 @@
       for (int i = 0; i < entryMethods.size(); i++) {
         entryMethodToIndex.put(entryMethods.get(i), i);
       }
-
       return true;
     }
 
@@ -1651,20 +1623,27 @@
       return new JsBinaryOperation(lhs.getSourceInfo(), JsBinaryOperator.COMMA, lhs, rhs);
     }
 
-    private JsExpression generateCastableTypeMap(JClassType x) {
+    private void generateCastableTypeMap(JClassType x, List<JsStatement> globalStmts) {
       JsCastMap castMap = program.getCastMap(x);
       if (castMap != null) {
         JField castableTypeMapField = program.getIndexedField("Object.castableTypeMap");
         JsName castableTypeMapName = names.get(castableTypeMapField);
         if (castableTypeMapName == null) {
           // Was pruned; this compilation must have no dynamic casts.
-          return new JsObjectLiteral(SourceOrigin.UNKNOWN);
+          return;
         }
 
+        // Generate castableTypeMap for each type prototype
+        // _.castableTypeMap$ = ...
+        SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic(GenerateJavaScriptAST.class);
+        JsNameRef fieldRef = castableTypeMapName.makeRef(sourceInfo);
+        fieldRef.setQualifier(globalTemp.makeRef(sourceInfo));
         accept(castMap);
-        return (JsExpression) pop();
+        JsExpression asg = createAssignment(fieldRef, (JsExpression) pop());
+        JsExprStmt asgStmt = asg.makeStmt();
+        globalStmts.add(asgStmt);
+        typeForStatMap.put(asgStmt, x);
       }
-      return new JsObjectLiteral(SourceOrigin.UNKNOWN);
     }
 
     private void generateClassLiteral(JDeclarationStatement decl, JsVars vars) {
@@ -1701,6 +1680,8 @@
         // special: setup the identifying typeMarker field
         generateTypeMarker(globalStmts);
       }
+
+      generateCastableTypeMap(x, globalStmts);
     }
 
     private void generateGwtOnLoad(List<JsFunction> entryFuncs, List<JsStatement> globalStmts) {
@@ -1801,78 +1782,6 @@
       errCall.getArguments().add(modName.makeRef(sourceInfo));
     }
 
-    private void generateImmortalTypes(JsVars globals) {
-      List<JsStatement> globalStmts = jsProgram.getGlobalBlock().getStatements();
-      List<JClassType> immortalTypes = new ArrayList<JClassType>(
-          program.immortalCodeGenTypes);
-      // visit in reverse order since insertions start at head
-      Collections.reverse(immortalTypes);
-      JMethod createObjMethod = program.getIndexedMethod("JavaScriptObject.createObject");
-      JMethod createArrMethod = program.getIndexedMethod("JavaScriptObject.createArray");
-
-      for (JClassType x : immortalTypes) {
-        // should not be pruned
-        assert x.getMethods().size() > 0;
-        // insert all static methods
-        for (JMethod method : x.getMethods()) {
-          /*
-           * Skip virtual methods and constructors. Even in cases where there is no constructor
-           * defined, the compiler will synthesize a default constructor which invokes
-           * a synthensized $init() method. We must skip both of these inserted methods.
-           */
-          if (method.needsVtable() || method instanceof JConstructor) {
-            continue;
-          }
-          if (JProgram.isClinit(method)) {
-            /**
-             * Emit empty clinits that will be pruned. If a type B extends A, then even if
-             * B and A have no fields to initialize, there will be a call inserted in B's clinit
-             * to invoke A's clinit. Likewise, if you have a static field initialized to
-             * JavaScriptObject.createObject(), the clinit() will include this initializer code,
-             * which we don't want.
-             */
-            JsFunction func = new JsFunction(x.getSourceInfo(), topScope,
-                topScope.declareName(mangleNameForGlobal(method)), true);
-            func.setBody(new JsBlock(method.getBody().getSourceInfo()));
-            push(func);
-          } else {
-            accept(method);
-          }
-          // add after var declaration, but before everything else
-          JsFunction func = (JsFunction) pop();
-          assert func.getName() != null;
-          globalStmts.add(1, func.makeStmt());
-        }
-
-        // insert fields into global var declaration
-        for (JField field : x.getFields()) {
-          assert field.isStatic() : "All fields on immortal types must be static.";
-          accept(field);
-          JsNode node = pop();
-          assert node instanceof JsVar;
-          JsVar fieldVar = (JsVar) node;
-          JExpression init = field.getInitializer();
-          if (init != null
-              && field.getLiteralInitializer() == null) {
-            // no literal, but it could be a JavaScriptObject
-            if (init.getType() == program.getJavaScriptObject()) {
-              assert init instanceof JMethodCall;
-              JMethod meth = ((JMethodCall) init).getTarget();
-              // immortal types can only have non-primitive literal initializers of createArray,createObject
-              if (meth == createObjMethod) {
-                fieldVar.setInitExpr(new JsObjectLiteral(init.getSourceInfo()));
-              } else if (meth == createArrMethod) {
-                fieldVar.setInitExpr(new JsArrayLiteral(init.getSourceInfo()));
-              } else {
-                assert false : "Illegal initializer expression for immortal field " + field;
-              }
-            }
-          }
-          globals.add(fieldVar);
-        }
-      }
-    }
-
     private void generateLongLiterals(JsVars vars) {
       for (Entry<Long, JsName> entry : longLits.entrySet()) {
         JsName jsName = entry.getValue();
@@ -1898,31 +1807,44 @@
     private void generateSeedFuncAndPrototype(JClassType x, List<JsStatement> globalStmts) {
       SourceInfo sourceInfo = x.getSourceInfo();
       if (x != program.getTypeJavaLangString()) {
-        JsInvocation defineSeed = new JsInvocation(x.getSourceInfo());
-        JsName seedNameRef = indexedFunctions.get(
-            "SeedUtil.defineSeed").getName();
-        defineSeed.setQualifier(seedNameRef.makeRef(x.getSourceInfo()));
-        int newSeed = getSeedId(x);
-        assert newSeed > 0;
-        JClassType superClass = x.getSuperClass();
-        int superSeed = (superClass == null) ? -1 : getSeedId(x.getSuperClass());
-        // SeedUtil.defineSeed(queryId, superId, castableMap, constructors)
-        defineSeed.getArguments().add(new JsNumberLiteral(x.getSourceInfo(),
-            newSeed));
-        defineSeed.getArguments().add(new JsNumberLiteral(x.getSourceInfo(),
-            superSeed));
-        JsExpression castMap = generateCastableTypeMap(x);
-        defineSeed.getArguments().add(castMap);
-       
+        JsName seedFuncName = names.get(x);
+
+        // seed function
+        // function com_example_foo_Foo() { }
+        JsFunction seedFunc = new JsFunction(sourceInfo, topScope, seedFuncName, true);
+        seedFuncName.setStaticRef(seedFunc);
+        JsBlock body = new JsBlock(sourceInfo);
+        seedFunc.setBody(body);
+        JsExprStmt seedFuncStmt = seedFunc.makeStmt();
+        globalStmts.add(seedFuncStmt);
+        typeForStatMap.put(seedFuncStmt, x);
+
+        // Setup prototype chain.
+        // _ = Foo__V.prototype = FooSeed.prototype = new FooSuper();
+        JsNameRef seedProtoRef = prototype.makeRef(sourceInfo);
+        seedProtoRef.setQualifier(seedFuncName.makeRef(sourceInfo));
+        JsExpression protoObj;
+        if (x.getSuperClass() != null) {
+          JsNameRef superPrototypeRef = names.get(x.getSuperClass()).makeRef(sourceInfo);
+          JsNew newExpr = new JsNew(sourceInfo, superPrototypeRef);
+          protoObj = newExpr;
+        } else {
+          protoObj = new JsObjectLiteral(sourceInfo);
+        }
+        JsExpression protoAsg = createAssignment(seedProtoRef, protoObj);
+
         // Chain assign the same prototype to every live constructor.
         for (JMethod method : x.getMethods()) {
           if (liveCtors.contains(method)) {
-            defineSeed.getArguments().add(names.get(method).makeRef(
-                sourceInfo));
+            JsNameRef protoRef = prototype.makeRef(sourceInfo);
+            protoRef.setQualifier(names.get(method).makeRef(sourceInfo));
+            protoAsg = createAssignment(protoRef, protoAsg);
           }
         }
 
-        JsStatement tmpAsgStmt = defineSeed.makeStmt();
+        // Finally, assign to the temp var for setup code.
+        JsExpression tmpAsg = createAssignment(globalTemp.makeRef(sourceInfo), protoAsg);
+        JsExprStmt tmpAsgStmt = tmpAsg.makeStmt();
         globalStmts.add(tmpAsgStmt);
         typeForStatMap.put(tmpAsgStmt, x);
       } else {
@@ -1937,16 +1859,6 @@
         JsExprStmt tmpAsgStmt = tmpAsg.makeStmt();
         globalStmts.add(tmpAsgStmt);
         typeForStatMap.put(tmpAsgStmt, x);
-        JField castableTypeMapField = program.getIndexedField("Object.castableTypeMap");
-        JsName castableTypeMapName = names.get(castableTypeMapField);
-        JsNameRef ctmRef = castableTypeMapName.makeRef(sourceInfo);
-        ctmRef.setQualifier(globalTemp.makeRef(sourceInfo));
-        JsExpression castMapLit = generateCastableTypeMap(x);
-        JsExpression ctmAsg = createAssignment(ctmRef,
-            castMapLit);
-        JsExprStmt ctmAsgStmt = ctmAsg.makeStmt();
-        globalStmts.add(ctmAsgStmt);
-        typeForStatMap.put(ctmAsgStmt, x);
       }
     }
 
@@ -2249,7 +2161,6 @@
   private final Map<JAbstractMethodBody, JsFunction> methodBodyMap =
       new IdentityHashMap<JAbstractMethodBody, JsFunction>();
   private final Map<HasName, JsName> names = new IdentityHashMap<HasName, JsName>();
-  private int nextSeedId = 1;
   private List<JsName> namesByQueryId;
   private JsFunction nullFunc;
 
@@ -2264,11 +2175,6 @@
   private final JProgram program;
 
   /**
-   * Map of class type to allocated seed id.
-   */
-  private final Map<JClassType, Integer> seedIdMap = new HashMap<JClassType, Integer>();
-
-  /**
    * All of the fields in String and Array need special handling for interop.
    */
   private final Map<JField, String> specialObfuscatedFields = new HashMap<JField, String>();
@@ -2350,8 +2256,8 @@
     namesToIdents.put("expando", "eX");
     namesToIdents.put("typeMarker", "tM");
     namesToIdents.put("castableTypeMap", "cM");
-    namesToIdents.put("___clazz", "cZ");
     // Array magic field
+    namesToIdents.put("arrayClass", "aC");
     namesToIdents.put("queryId", "qI");
 
     List<JField> fields = new ArrayList<JField>(program.getTypeJavaLangObject().getFields());
@@ -2363,11 +2269,6 @@
         specialObfuscatedFields.put(field, ident);
       }
     }
-
-    // force java.lang.Object,java.lang.String
-    // to have seed ids 1,2
-    getSeedId(program.getTypeJavaLangObject());
-    getSeedId(program.getTypeJavaLangString());
   }
 
   String getNameString(HasName hasName) {
@@ -2375,20 +2276,6 @@
     return s;
   }
 
-  /**
-   * Looks up or assigns a seed id for a type..
-   */
-  int getSeedId(JClassType type) {
-    Integer val = seedIdMap.get(type);
-    int seedId = val == null ? 0 : val;
-
-    if (seedId == 0) {
-      seedId = nextSeedId++;
-      seedIdMap.put(type, seedId);
-    }
-    return seedId;
-  }
-
   String mangleName(JField x) {
     String s = getNameString(x.getEnclosingType()) + '_' + getNameString(x);
     return s;
@@ -2522,11 +2409,6 @@
         return constructorNameToTypeMap.get(name);
       }
 
-      public int seedIdForType(JClassType type) {
-        Integer seedId = seedIdMap.get(type);
-        return seedId != null ? seedId : -1;
-      }
-
       public JClassType typeForStatement(JsStatement stat) {
         return typeForStatMap.get(stat);
       }
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 831aa25..ae2e645 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
@@ -2158,13 +2158,15 @@
       assert ("getClass".equals(method.getName()));
       SourceInfo info = method.getSourceInfo();
       if ("com.google.gwt.lang.Array".equals(type.getName())) {
-        /*
-         * Don't implement, fall through to Object.getClass(). Array emulation code
-         * in com.google.gwt.lang.Array invokes Array.getClass() and expects to get the
-         * class literal for the actual runtime type of the array (e.g. Foo[].class) and
-         * not Array.class.
-         */
-        type.getMethods().remove(2);
+        // Special implementation: return this.arrayClass
+        JField arrayClassField = null;
+        for (JField field : type.getFields()) {
+          if ("arrayClass".equals(field.getName())) {
+            arrayClassField = field;
+          }
+        }
+        assert arrayClassField != null;
+        implementMethod(method, new JFieldRef(info, makeThisRef(info), arrayClassField, type));
       } else {
         implementMethod(method, new JClassLiteral(info, type));
       }
@@ -2765,7 +2767,8 @@
    * 
    * TODO(zundel): something much more awesome?
    */
-  private static final long AST_VERSION = 3;
+  private static final long AST_VERSION = 2;
+
   private static final char[] _STRING = "_String".toCharArray();
   private static final String ARRAY_LENGTH_FIELD = "length";
 
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 7d31cae..f525c3a 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
@@ -34,10 +34,10 @@
 import com.google.gwt.dev.jjs.ast.JMethodBody;
 import com.google.gwt.dev.jjs.ast.JMethodCall;
 import com.google.gwt.dev.jjs.ast.JModVisitor;
+import com.google.gwt.dev.jjs.ast.JNameOf;
 import com.google.gwt.dev.jjs.ast.JNullLiteral;
 import com.google.gwt.dev.jjs.ast.JPrimitiveType;
 import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.ast.JSeedIdOf;
 import com.google.gwt.dev.jjs.ast.JStringLiteral;
 import com.google.gwt.dev.jjs.ast.JType;
 import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
@@ -58,20 +58,15 @@
  * Ordinarily, accessing one of these fields would trigger a clinit to run, but
  * we've special-cased class literal fields to evaluate as top-level code before
  * the application starts running to avoid the clinit.
- *
- * Class literal factory methods are responsible for installing references
- * to themselves on the Object.clazz field of their JS runtime prototype
- * since getClass() is no longer an overridden method.  Prototypes can be
- * looked up via 'seedId' from the global seedTable object, and so each
- * class literal factory method is passed the seedId of its type.
  * <p>
+ * TODO(cromwellian): consider lazy-initialization to improve startup time.
  */
 public class ImplementClassLiteralsAsFields {
 
   private class NormalizeVisitor extends JModVisitor {
     @Override
     public void endVisit(JClassLiteral x, Context ctx) {
-      JField field = resolveClassLiteralField(x.getRefType());
+      JField field = resolveClassLiteralField(x);
       x.setField(field);
     }
   }
@@ -125,8 +120,8 @@
    * Class:
    * 
    * <pre>
-   * Class.createForClass("java.lang.", "Object", /JSeedIdOf/"java.lang.Object", null)
-   * Class.createForClass("java.lang.", "Exception", /JSeedIdOf/"java.lang.Exception", Throwable.class)
+   * Class.createForClass("java.lang.", "Object", /JNameOf/"java.lang.Object", null)
+   * Class.createForClass("java.lang.", "Exception", /JNameOf/"java.lang.Exception", Throwable.class)
    * </pre>
    * 
    * Interface:
@@ -144,21 +139,21 @@
    * Array:
    * 
    * <pre>
-   * Class.createForArray("", "[I", /JSeedIdOf/"com.google.gwt.lang.Array", int.class)
-   * Class.createForArray("[Lcom.example.", "Foo;", /JSeedIdOf/"com.google.gwt.lang.Array", Foo.class)
+   * Class.createForArray("", "[I", /JNameOf/"com.google.gwt.lang.Array", int.class)
+   * Class.createForArray("[Lcom.example.", "Foo;", /JNameOf/"com.google.gwt.lang.Array", Foo.class)
    * </pre>
    * 
    * Enum:
    * 
    * <pre>
-   * Class.createForEnum("com.example.", "MyEnum", /JSeedIdOf/"com.example.MyEnum", Enum.class,
+   * Class.createForEnum("com.example.", "MyEnum", /JNameOf/"com.example.MyEnum", Enum.class,
    *     public static MyEnum[] values(), public static MyEnum valueOf(String name))
    * </pre>
    * 
    * Enum subclass:
    * 
    * <pre>
-   * Class.createForEnum("com.example.", "MyEnum$1", /JSeedIdOf/"com.example.MyEnum$1", MyEnum.class,
+   * Class.createForEnum("com.example.", "MyEnum$1", /JNameOf/"com.example.MyEnum$1", MyEnum.class,
    *     null, null))
    * </pre>
    */
@@ -190,10 +185,12 @@
     if (type instanceof JArrayType) {
       // There's only one seed function for all arrays
       JDeclaredType arrayType = program.getIndexedType("Array");
-      call.addArg(new JSeedIdOf(info, program.getTypeJavaLangString(), arrayType));
+      call.addArg(new JNameOf(info, program.getTypeJavaLangString(), arrayType));
+
     } else if (type instanceof JClassType) {
       // Add the name of the seed function for concrete types
-      call.addArg(new JSeedIdOf(info, program.getTypeJavaLangString(), type));
+      call.addArg(new JNameOf(info, program.getTypeJavaLangString(), type));
+
     } else if (type instanceof JPrimitiveType) {
       // And give primitive types an illegal, though meaningful, value
       call.addArg(program.getLiteralString(info, " " + type.getJavahSignatureName()));
@@ -259,7 +256,7 @@
 
   private JClassLiteral createDependentClassLiteral(SourceInfo info, JType type) {
     JClassLiteral classLiteral = new JClassLiteral(info.makeChild(), type);
-    JField field = resolveClassLiteralField(classLiteral.getRefType());
+    JField field = resolveClassLiteralField(classLiteral);
     classLiteral.setField(field);
     return classLiteral;
   }
@@ -267,7 +264,6 @@
   private void execImpl() {
     NormalizeVisitor visitor = new NormalizeVisitor();
     visitor.accept(program);
-    program.recordClassLiteralFields(classLiteralFields);
   }
 
   private String getTypeName(JType type) {
@@ -313,7 +309,8 @@
    * }
    * </pre>
    */
-  private JField resolveClassLiteralField(JType type) {
+  private JField resolveClassLiteralField(JClassLiteral classLiteral) {
+    JType type = classLiteral.getRefType();
     type = normalizeJsoType(type);
     JField field = classLiteralFields.get(type);
     if (field == null) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java
index de9e7fa..89aace3 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java
@@ -55,11 +55,6 @@
   JClassType nameToType(JsName name);
 
   /**
-   * Return the seed id corresponding to the Java type.
-   */
-  int seedIdForType(JClassType type);
-
-  /**
    * If <code>stat</code> is used to set up the definition of some class, return
    * that class. Otherwise, return null.
    */
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 12b72c2..4375220 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
@@ -599,17 +599,13 @@
 
     ControlFlowAnalyzer livenessAnalyzer = new ControlFlowAnalyzer(program);
     livenessAnalyzer.setForPruning();
-
-    // SPECIAL: Immortal codegen types are never pruned
-    traverseTypes(livenessAnalyzer, program.immortalCodeGenTypes);
-
     if (saveCodeGenTypes) {
       /*
        * SPECIAL: Some classes contain methods used by code generation later.
        * Unless those transforms have already been performed, we must rescue all
        * contained methods for later user.
        */
-      traverseTypes(livenessAnalyzer, program.codeGenTypes);
+      traverseFromCodeGenTypes(livenessAnalyzer);
     }
     livenessAnalyzer.traverseEverything();
 
@@ -631,11 +627,11 @@
   }
 
   /**
-   * Traverse from all methods starting from a set of types.
+   * Traverse from all methods in the program's code-gen types. See
+   * {@link JProgram#CODEGEN_TYPES_SET}.
    */
-  private void traverseTypes(ControlFlowAnalyzer livenessAnalyzer,
-      List<JClassType> types) {
-    for (JClassType type : types) {
+  private void traverseFromCodeGenTypes(ControlFlowAnalyzer livenessAnalyzer) {
+    for (JClassType type : program.codeGenTypes) {
       livenessAnalyzer.traverseFromReferenceTo(type);
       for (JMethod method : type.getMethods()) {
         if (method instanceof JConstructor) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceGetClassOverrides.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceGetClassOverrides.java
deleted file mode 100644
index 18152d0..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceGetClassOverrides.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.impl;
-
-import com.google.gwt.dev.jjs.ast.Context;
-import com.google.gwt.dev.jjs.ast.JField;
-import com.google.gwt.dev.jjs.ast.JFieldRef;
-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.JProgram;
-
-/**
- * Prune all overrides of Object.getClass() except when the enclosing class is JavaScriptObject
- * (to permit getClass() devirtualization in JsoDevirtualizer to continue to work).
- * Also Inline all method calls to Object.getClass() as Object.clazz.
- */
-public class ReplaceGetClassOverrides {
-  public static void exec(JProgram program) {
-    new GetClassInlinerRemover(program).accept(program);
-  }
-
-  private static class GetClassInlinerRemover extends JModVisitor {
-
-    private JProgram program;
-    private JMethod getClassMethod;
-    private JField clazzField;
-
-    public GetClassInlinerRemover(JProgram program) {
-      this.program = program;
-      getClassMethod = program.getIndexedMethod("Object.getClass");
-      clazzField = program.getIndexedField("Object.___clazz");
-    }
-
-    public void endVisit(JMethod x, Context ctx) {
-      // don't prune JSO.getClass()
-      if (x.getEnclosingType() == program.getJavaScriptObject()) {
-        return;
-      }
-      if (x.getOverrides().contains(getClassMethod)) {
-        ctx.removeMe();
-      }
-    }
-
-    public void endVisit(JMethodCall x, Context ctx) {
-      // don't inline JSO.getClass()
-      if (x.getTarget().getEnclosingType() == program.getJavaScriptObject()) {
-        return;
-      }
-      // replace overridden getClass() with reference to Object.clazz field
-      if (x.getTarget() == getClassMethod ||
-          x.getTarget().getOverrides().contains(getClassMethod)) {
-        ctx.replaceMe(new JFieldRef(x.getSourceInfo(), x.getInstance(),
-            clazzField, clazzField.getEnclosingType()));
-      }
-    }
-  }
-}
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 691752a..829886f 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
@@ -76,7 +76,6 @@
 import com.google.gwt.dev.jjs.ast.JReboundEntryPoint;
 import com.google.gwt.dev.jjs.ast.JReferenceType;
 import com.google.gwt.dev.jjs.ast.JReturnStatement;
-import com.google.gwt.dev.jjs.ast.JSeedIdOf;
 import com.google.gwt.dev.jjs.ast.JStatement;
 import com.google.gwt.dev.jjs.ast.JStringLiteral;
 import com.google.gwt.dev.jjs.ast.JSwitchStatement;
@@ -136,7 +135,6 @@
   protected static final char[] CHARS_PROTECTED = "protected ".toCharArray();
   protected static final char[] CHARS_PUBLIC = "public ".toCharArray();
   protected static final char[] CHARS_RETURN = "return".toCharArray();
-  protected static final char[] CHARS_SEEDIDOF = " JSeedIdOf ".toCharArray();
   protected static final char[] CHARS_SLASHSTAR = "/*".toCharArray();
   protected static final char[] CHARS_STARSLASH = "*/".toCharArray();
   protected static final char[] CHARS_STATIC = "static ".toCharArray();
@@ -679,7 +677,7 @@
   @Override
   public boolean visit(JNameOf x, Context ctx) {
     print(CHARS_SLASHSTAR);
-    print(x instanceof JSeedIdOf ? CHARS_SEEDIDOF : CHARS_NAMEOF);
+    print(CHARS_NAMEOF);
     print(CHARS_STARSLASH);
     printStringLiteral(x.getNode().getName());
     return false;
diff --git a/dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java b/dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java
index 834bce7..2a430a5 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java
@@ -26,7 +26,6 @@
 import com.google.gwt.dev.js.ast.JsName;
 import com.google.gwt.dev.js.ast.JsProgram;
 import com.google.gwt.dev.js.ast.JsProgramFragment;
-import com.google.gwt.dev.js.ast.JsSeedIdOf;
 import com.google.gwt.dev.js.ast.JsStatement;
 import com.google.gwt.dev.js.ast.JsVisitable;
 import com.google.gwt.dev.js.ast.JsVars.JsVar;
@@ -83,17 +82,6 @@
   }
 
   @Override
-  public boolean visit(JsSeedIdOf x, JsContext ctx) {
-    Integer seedId = map.seedIdForType(map.nameToType(x.getName()));
-    if (seedId == null) {
-      seedId = -1;
-    }
-    out.print(Integer.toString(seedId));
-
-    return false;
-  }
-
-  @Override
   protected <T extends JsVisitable> T doAccept(T node) {
     JsName newName = nameToBillTo(node);
     if (newName == null) {
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java b/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
index 5df8898..82a6379 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
@@ -22,9 +22,6 @@
 import com.google.gwt.dev.jjs.HasSourceInfo;
 import com.google.gwt.dev.jjs.InternalCompilerException;
 import com.google.gwt.dev.jjs.SourceInfo;
-import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
 import com.google.gwt.dev.js.ast.JsArrayAccess;
 import com.google.gwt.dev.js.ast.JsArrayLiteral;
 import com.google.gwt.dev.js.ast.JsBinaryOperation;
@@ -562,22 +559,12 @@
   }
 
   /**
-   * Creates a visitor to instrument each JsFunction in the jsProgram.
+   * Creates a visitor to instrument each JsFunction in the program.
    */
   private class InstrumentAllFunctions extends JsVisitor {
-
     @Override
     public void endVisit(JsFunction x, JsContext ctx) {
       if (!x.getBody().getStatements().isEmpty()) {
-        JsName fnName = x.getName();
-        JMethod method = jjsmap.nameToMethod(fnName);
-        /**
-         * Do not instrumental immortal types because they are potentially
-         * evaluated before anything else has been defined.
-         */
-        if (method != null && jprogram.immortalCodeGenTypes.contains(method.getEnclosingType())) {
-          return;
-        }
         if (recordLineNumbers) {
           (new LocationVisitor(x)).accept(x.getBody());
         } else {
@@ -815,11 +802,9 @@
     STRIP, NATIVE, EMULATED;
   }
 
-  public static void exec(JProgram jprogram, JsProgram jsProgram,
-      PropertyOracle[] propertyOracles,
-      JavaToJavaScriptMap jjsmap) {
+  public static void exec(JsProgram program, PropertyOracle[] propertyOracles) {
     if (getStackMode(propertyOracles) == StackMode.EMULATED) {
-      (new JsStackEmulator(jprogram, jsProgram, propertyOracles, jjsmap)).execImpl();
+      (new JsStackEmulator(program, propertyOracles)).execImpl();
     }
   }
 
@@ -854,20 +839,14 @@
 
   private JsFunction caughtFunction;
   private JsName lineNumbers;
-  private JProgram jprogram;
-  private final JsProgram jsProgram;
-  private JavaToJavaScriptMap jjsmap;
+  private final JsProgram program;
   private boolean recordFileNames;
   private boolean recordLineNumbers;
   private JsName stack;
   private JsName stackDepth;
 
-  private JsStackEmulator(JProgram jprogram, JsProgram jsProgram,
-      PropertyOracle[] propertyOracles,
-      JavaToJavaScriptMap jjsmap) {
-    this.jprogram = jprogram;
-    this.jsProgram = jsProgram;
-    this.jjsmap = jjsmap;
+  private JsStackEmulator(JsProgram program, PropertyOracle[] propertyOracles) {
+    this.program = program;
 
     assert propertyOracles.length > 0;
     PropertyOracle oracle = propertyOracles[0];
@@ -886,27 +865,27 @@
   }
 
   private void execImpl() {
-    caughtFunction = jsProgram.getIndexedFunction("Exceptions.caught");
+    caughtFunction = program.getIndexedFunction("Exceptions.caught");
     if (caughtFunction == null) {
       // No exceptions caught? Weird, but possible.
       return;
     }
     initNames();
     makeVars();
-    (new ReplaceUnobfuscatableNames()).accept(jsProgram);
-    (new InstrumentAllFunctions()).accept(jsProgram);
+    (new ReplaceUnobfuscatableNames()).accept(program);
+    (new InstrumentAllFunctions()).accept(program);
   }
 
   private void initNames() {
-    stack = jsProgram.getScope().declareName("$JsStackEmulator_stack", "$stack");
-    stackDepth = jsProgram.getScope().declareName("$JsStackEmulator_stackDepth",
+    stack = program.getScope().declareName("$JsStackEmulator_stack", "$stack");
+    stackDepth = program.getScope().declareName("$JsStackEmulator_stackDepth",
         "$stackDepth");
-    lineNumbers = jsProgram.getScope().declareName("$JsStackEmulator_location",
+    lineNumbers = program.getScope().declareName("$JsStackEmulator_location",
         "$location");
   }
 
   private void makeVars() {
-    SourceInfo info = jsProgram.createSourceInfoSynthetic(getClass());
+    SourceInfo info = program.createSourceInfoSynthetic(getClass());
     JsVar stackVar = new JsVar(info, stack);
     stackVar.setInitExpr(new JsArrayLiteral(info));
     JsVar stackDepthVar = new JsVar(info, stackDepth);
@@ -915,12 +894,12 @@
     lineNumbersVar.setInitExpr(new JsArrayLiteral(info));
 
     JsVars vars;
-    JsStatement first = jsProgram.getGlobalBlock().getStatements().get(0);
+    JsStatement first = program.getGlobalBlock().getStatements().get(0);
     if (first instanceof JsVars) {
       vars = (JsVars) first;
     } else {
       vars = new JsVars(info);
-      jsProgram.getGlobalBlock().getStatements().add(0, vars);
+      program.getGlobalBlock().getStatements().add(0, vars);
     }
     vars.add(stackVar);
     vars.add(stackDepthVar);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsSeedIdOf.java b/dev/core/src/com/google/gwt/dev/js/ast/JsSeedIdOf.java
deleted file mode 100644
index 51d0ed5..0000000
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsSeedIdOf.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.js.ast;
-
-import com.google.gwt.dev.jjs.SourceInfo;
-
-/**
- * An AST node whose evaluation results in the numeric seed id of its type.
- */
-public class JsSeedIdOf extends JsNameOf {
-
-  public JsSeedIdOf(SourceInfo info, JsName name) {
-    super(info, name);
-  }
-
-  public void traverse(JsVisitor visitor, JsContext ctx) {
-    if (visitor.visit(this, ctx)) {
-    }
-    visitor.endVisit(this, ctx);
-  }
-}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java b/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
index 142e462..e64799f 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
@@ -219,10 +219,6 @@
   public void endVisit(JsReturn x, JsContext ctx) {
   }
 
-  public void endVisit(JsSeedIdOf x, JsContext ctx) {
-    endVisit((JsNameOf) x, ctx);
-  }
-
   public void endVisit(JsStringLiteral x, JsContext ctx) {
   }
 
@@ -387,10 +383,6 @@
     return true;
   }
 
-  public boolean visit(JsSeedIdOf x, JsContext ctx) {
-    return visit((JsNameOf) x, ctx);
-  }
-
   public boolean visit(JsStringLiteral x, JsContext ctx) {
     return true;
   }
diff --git a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
index 3c36c55..60c809f 100644
--- a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
+++ b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
@@ -173,7 +173,7 @@
   public static Array initValues(Class<?> arrayClass,
       JavaScriptObject castableTypeMap, int queryId, Array array) {
     ExpandoWrapper.wrapArray(array);
-    setClass(array, arrayClass);
+    array.arrayClass = arrayClass;
     Util.setCastableTypeMap(array, castableTypeMap);
     array.queryId = queryId;
     return array;
@@ -302,15 +302,17 @@
     return array[index] = value;
   }-*/;
 
-  // violator pattern so that the field remains private
-  private static native void setClass(Object o, Class<?> clazz) /*-{
-    o.@java.lang.Object::___clazz = clazz;
-  }-*/;
-
   /*
    * Explicitly initialize all fields to JS false values; see comment in
    * ExpandoWrapper.initExpandos().
    */
+  
+  /**
+   * Holds the real type-specific Class object for a given array instance. The
+   * compiler produces a magic implementation of getClass() which returns this
+   * field directly.
+   */
+  protected Class<?> arrayClass = null;
 
   /**
    * A representation of the necessary cast target for objects stored into this
diff --git a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/SeedUtil.java b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/SeedUtil.java
deleted file mode 100644
index bd80104..0000000
--- a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/SeedUtil.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.lang;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/**
- * Utility class for fetching prototype-seed functions for injection into JsAST.
- */
-public class SeedUtil {
-
-  /*
-  * Holds a map of seedId to anonymous Javascript functions (prototypes for class vtables).
-  */
-  private static JavaScriptObject seedTable = JavaScriptObject.createObject();
-
-  /**
-   * If not already created, generates an anonymous function and assigns it a slot in the global
-   * seedTable. If superSeed is > -1, it creates an instance of the superSeed by invoking
-   * newSeed() and then assigns it as the prototype of the seed being defined. It also sets up the
-   * castableTypeMap, as well as any ctors which are passed in via Javascript varargs. Finally, if
-   * the class literal for this seed id was setup first, which can happen if they are in separate
-   * code-split fragments, the Class.createFor* methods will have created a placeholder seedTable
-   * entry containing the Class literal, and this will be copied from the placeholder location
-   * onto the current prototype.
-   */
-  public static native JavaScriptObject defineSeed(int id, int superSeed,
-      JavaScriptObject castableTypeMap) /*-{
-    var seed = @com.google.gwt.lang.SeedUtil::seedTable[id];
-    if (seed && !seed.@java.lang.Object::___clazz) {
-      // not a placeholder entry setup by Class.setClassLiteral
-      _ = seed.prototype;
-    } else {
-      if (!seed) {
-        seed = @com.google.gwt.lang.SeedUtil::seedTable[id] = function() {
-        };
-      }
-      _ = seed.prototype = (superSeed < 0) ? {}
-          : @com.google.gwt.lang.SeedUtil::newSeed(I)(superSeed);
-      _.@java.lang.Object::castableTypeMap = castableTypeMap;
-    }
-    for (var i = 3; i < arguments.length; ++i) {
-      arguments[i].prototype = _;
-    }
-    if (seed.@java.lang.Object::___clazz) {
-      _.@java.lang.Object::___clazz = seed.@java.lang.Object::___clazz;
-      seed.@java.lang.Object::___clazz = null;
-    }
-  }-*/;
-
-  /**
-   * Lookup seed function by id and instantiate an object with it.
-   */
-  public static native JavaScriptObject newSeed(int id) /*-{
-    return new (@com.google.gwt.lang.SeedUtil::seedTable[id]);
-  }-*/;
-}
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/CodeSplitterTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/CodeSplitterTest.java
index d9cdc10..187b660 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/CodeSplitterTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/CodeSplitterTest.java
@@ -31,5 +31,7 @@
     ControlFlowAnalyzer cfa = CodeSplitter.computeInitiallyLive(program);
 
     assertTrue(cfa.getInstantiatedTypes().contains(findType(program, "com.google.gwt.lang.Array")));
+    assertTrue(cfa.getLiveFieldsAndMethods().contains(
+        findMethod(findType(program, "com.google.gwt.lang.Array"), "getClass")));
   }
 }
diff --git a/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java b/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
index 9bd5e36..eb3c555 100644
--- a/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
+++ b/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
@@ -77,8 +77,7 @@
           builder.add(symbolData.getSymbolName(), symbolData.getJsniIdent(),
               symbolData.getClassName(), symbolData.getMemberName(),
               symbolData.getQueryId(), 
-              new CastableTypeDataImpl(castableTypeMapString),
-              symbolData.getSeedId());
+              new CastableTypeDataImpl(castableTypeMapString));
         }
 
         ByteArrayOutputStream out = new ByteArrayOutputStream();
diff --git a/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java b/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java
index 602fabb..d91c0e3 100644
--- a/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java
+++ b/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java
@@ -52,8 +52,7 @@
     private WebModeClientOracle oracle = new WebModeClientOracle();
 
     public void add(String jsIdent, String jsniIdent, String className,
-        String memberName, int queryId, CastableTypeData castableTypeData,
-        int seedId) {
+        String memberName, int queryId, CastableTypeData castableTypeData) {
       
       oracle.idents.add(jsIdent);
       ClassData data = oracle.getClassData(className);
@@ -74,8 +73,6 @@
         data.typeName = className;
         data.seedName = jsIdent;
         oracle.seedNamesToClassData.put(jsIdent, data);
-        oracle.seedIdsToClassData.put(seedId, data);
-        data.seedId = seedId;
       } else {
         if (jsniIdent.contains("(")) {
           jsniIdent = jsniIdent.substring(jsniIdent.indexOf("::") + 2,
@@ -134,7 +131,6 @@
     public String seedName;
     public List<String> serializableFields = Collections.emptyList();
     public String typeName;
-    public int seedId;
   }
 
   /**
@@ -143,7 +139,7 @@
    * TODO: Use something other than Java serialization to store this type's
    * data.
    */
-  private static final long serialVersionUID = 2L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * Recreate a WebModeClientOracle based on the contents previously emitted by
@@ -226,7 +222,6 @@
   private final Set<String> idents = new HashSet<String>();
 
   private final Map<String, ClassData> seedNamesToClassData = new HashMap<String, ClassData>();
-  private final Map<Integer, ClassData> seedIdsToClassData = new HashMap<Integer, ClassData>();
 
   private transient Map<Class<?>, Field[]> operableFieldMap = new IdentityHashMap<Class<?>, Field[]>();
 
@@ -386,15 +381,6 @@
       seedName = seedName.substring(6);
     }
     ClassData data = seedNamesToClassData.get(seedName);
-    if (data == null) {
-      int seedId = 0;
-      try {
-        seedId = Integer.parseInt(seedName);
-      } catch (NumberFormatException e) {
-        return null;
-      }
-      data = seedIdsToClassData.get(seedId);
-    }
     return data == null ? null : data.typeName;
   }
 
diff --git a/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java b/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java
index 7e9f431..b5716fd 100644
--- a/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java
+++ b/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java
@@ -257,14 +257,12 @@
 
       byte[] currentBackRef = begin(x);
       byte[] constructorFunction = constructorFunction(x);
+      String seedName = clientOracle.getSeedName(x.getTargetClass());
 
-      String getSeedFunc = clientOracle.getMethodId("java.lang.Class",
-          "getSeedFunction", "Ljava/lang/Class;");
-      String classLitId = clientOracle.getFieldId(
-               "com.google.gwt.lang.ClassLiteralHolder",
-               getJavahSignatureName(x.getTargetClass()) + "_classLit");
-           assert classLitId != null : "No class literal for "
-               + x.getTargetClass().getName();
+      if (seedName == null) {
+        throw new IncompatibleRemoteServiceException(
+            "The client cannot create type " + x.getTargetClass());
+      }
 
       /*
        * If we need to maintain a backreference to the object, it's established
@@ -272,7 +270,7 @@
        * constructorFunction. This is done in case one of the fields should
        * require a reference to the object that is currently being constructed.
        */
-      // constructorFunctionFoo(x = new (classLit.getSeedFunction()), field1, field2)
+      // constructorFunctionFoo(x = new Foo, field1, field2)
       push(constructorFunction);
       lparen();
       if (hasBackRef) {
@@ -280,12 +278,7 @@
         eq();
       }
       _new();
-      lparen();
-      push(getSeedFunc);
-      lparen();
-      push(classLitId);
-      rparen();
-      rparen();
+      push(seedName);
       for (SetCommand setter : x.getSetters()) {
         comma();
         accept(setter.getValue());
@@ -569,7 +562,7 @@
 
       byte[] ident = getBytes("_0");
 
-      // function foo(_0) {return initValues(classLit, castableTypeData, queryId, _0)}
+      // function foo(_0) {return initValues(classLid, castableTypeData, queryId, _0)}
       function();
       push(functionName);
       lparen();
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 c41f7d3..d000d2d 100644
--- a/user/super/com/google/gwt/emul/java/lang/Class.java
+++ b/user/super/com/google/gwt/emul/java/lang/Class.java
@@ -30,20 +30,16 @@
   private static final int ARRAY = 0x00000004;
   private static final int ENUM = 0x00000008;
 
-  static native String asString(int number) /*-{
-    return number;
-  }-*/;
-
   /**
    * Create a Class object for an array.
    * 
    * @skip
    */
   static <T> Class<T> createForArray(String packageName, String className,
-      int seedId, Class<?> componentType) {
+      String seedName, Class<?> componentType) {
     // Initialize here to avoid method inliner
     Class<T> clazz = new Class<T>();
-    setName(clazz, packageName, className, -1);
+    setName(clazz, packageName, className, seedName);
     clazz.modifiers = ARRAY;
     clazz.superclass = Object.class;
     clazz.componentType = componentType;
@@ -56,10 +52,10 @@
    * @skip
    */
   static <T> Class<T> createForClass(String packageName, String className,
-      int seedId, Class<? super T> superclass) {
+      String seedName, Class<? super T> superclass) {
     // Initialize here to avoid method inliner
     Class<T> clazz = new Class<T>();
-    setName(clazz, packageName, className, seedId);
+    setName(clazz, packageName, className, seedName);
     clazz.superclass = superclass;
     return clazz;
   }
@@ -70,11 +66,11 @@
    * @skip
    */
   static <T> Class<T> createForEnum(String packageName, String className,
-      int seedId, Class<? super T> superclass,
+      String seedName, Class<? super T> superclass,
       JavaScriptObject enumConstantsFunc, JavaScriptObject enumValueOfFunc) {
     // Initialize here to avoid method inliner
     Class<T> clazz = new Class<T>();
-    setName(clazz, packageName, className, seedId);
+    setName(clazz, packageName, className, seedName);
     clazz.modifiers = (enumConstantsFunc != null) ? ENUM : 0;
     clazz.superclass = clazz.enumSuperclass = superclass;
     clazz.enumConstantsFunc = enumConstantsFunc;
@@ -90,7 +86,7 @@
   static <T> Class<T> createForInterface(String packageName, String className) {
     // Initialize here to avoid method inliner
     Class<T> clazz = new Class<T>();
-    setName(clazz, packageName, className, -1);
+    setName(clazz, packageName, className, null);
     clazz.modifiers = INTERFACE;
     return clazz;
   }
@@ -101,73 +97,21 @@
    * @skip
    */
   static Class<?> createForPrimitive(String packageName, String className,
-      int seedId) {
+      String seedName) {
     // Initialize here to avoid method inliner
     Class<?> clazz = new Class<Object>();
-    setName(clazz, packageName, className, seedId);
+    setName(clazz, packageName, className, seedName);
     clazz.modifiers = PRIMITIVE;
     return clazz;
   }
 
-  /**
-    * Used by {@link WebModePayloadSink} to create uninitialized instances.
-    */
-   static native JavaScriptObject getSeedFunction(Class<?> clazz) /*-{
-     var func = @com.google.gwt.lang.SeedUtil::seedTable[clazz.@java.lang.Class::seedId];
-     clazz = null; // HACK: prevent pruning via inlining by using param as lvalue
-     return func;
-   }-*/;
-
   static boolean isClassMetadataEnabled() {
     // This body may be replaced by the compiler
     return true;
   }
 
-  /**
-   * null or -1 implies lack of seed function / non-instantiable type
-   */
-  static native boolean isInstantiable(int seedId) /*-{
-    return seedId != null && seedId > -1;
-  }-*/;
-
-  /**
-   * Install class literal into seed.prototype.clazz field such that
-   * Object.getClass() returning this.clazz returns the literal. Also stores
-   * seedId on class literal for looking up prototypes given a literal. This
-   * is used for deRPC at the moment, but may be used to implement
-   * Class.newInstance() in the future.
-   */
-  static native void setClassLiteral(int seedId, Class<?> clazz) /*-{
-    var proto;
-    clazz.@java.lang.Class::seedId = seedId;
-    // String is the exception to the usual vtable setup logic
-    if (seedId == 2) {
-      proto = String.prototype
-    } else {
-      if (seedId > -1) {
-        // Guarantees virtual method won't be pruned by using a JSNI ref
-        // This is required because deRPC needs to call it.
-        var seed = @java.lang.Class::getSeedFunction(Ljava/lang/Class;)(clazz);
-        // A class literal may be referenced prior to an async-loaded vtable setup
-        // For example, class literal lives in inital fragment,
-        // but type is instantiated in another fragment
-        if (seed) {
-          proto = seed.prototype;
-        } else {
-          // Leave a place holder for now to be filled in by __defineSeed__ later
-          seed = @com.google.gwt.lang.SeedUtil::seedTable[seedId] = function(){};
-          seed.@java.lang.Object::___clazz = clazz;
-          return;
-        }
-      } else {
-        return;
-      }
-    }
-    proto.@java.lang.Object::___clazz = clazz;
-  }-*/;
-
   static void setName(Class<?> clazz, String packageName, String className,
-      int seedId) {
+      String seedName) {
     if (clazz.isClassMetadataEnabled()) {
       clazz.typeName = packageName + className;
     } else {
@@ -177,10 +121,7 @@
        * during application start up, before class Integer has been initialized.
        */
       clazz.typeName = "Class$"
-          + (seedId != -1 ? asString(seedId) : "" + clazz.hashCode());
-    }
-    if (isInstantiable(seedId)) {
-      setClassLiteral(seedId, clazz);
+          + (seedName != null ? seedName : "" + clazz.hashCode());
     }
   }
 
@@ -199,8 +140,6 @@
 
   private String typeName;
 
-  private int seedId;
-
   /**
    * Not publicly instantiable.
    * 
diff --git a/user/super/com/google/gwt/emul/java/lang/Object.java b/user/super/com/google/gwt/emul/java/lang/Object.java
index 63717d2..3b8efff 100644
--- a/user/super/com/google/gwt/emul/java/lang/Object.java
+++ b/user/super/com/google/gwt/emul/java/lang/Object.java
@@ -26,14 +26,6 @@
 public class Object {
 
   /**
-   * Holds class literal for subtypes of Object.
-   */
-  // BUG: If this field name conflicts with a method param name, JDT will complain
-  // CHECKSTYLE_OFF
-  private transient Class<?> ___clazz;
-  // CHECKSTYLE_ON
-
-  /**
    * Used by {@link com.google.gwt.core.client.impl.WeakMapping} in web mode
    * to store an expando containing a String -> Object mapping.
    * 
@@ -68,11 +60,14 @@
   }
 
   /*
-   * magic; Actual assignment to this field is done by Class.createFor() methods by injecting it
-   * into the prototype.
+   * Note: Unlike the real JRE, we don't spec this method as final because the
+   * compiler generates a polymorphic override on every other class which will
+   * return the correct class object.
+   * 
+   * TODO(scottb, compiler magician): declare this final, but have the compiler fix it up.
    */
   public Class<? extends Object> getClass() {
-    return ___clazz;
+    return Object.class;
   }
 
   public int hashCode() {
diff --git a/user/test/com/google/gwt/emultest/java/util/ArraysTest.java b/user/test/com/google/gwt/emultest/java/util/ArraysTest.java
index 8bc3344..6b17574 100644
--- a/user/test/com/google/gwt/emultest/java/util/ArraysTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/ArraysTest.java
@@ -402,7 +402,7 @@
   /**
    * Test Arrays.binarySearch(Object[], Object, Comparator).
    * 
-   * <pre>                                                  -draftCompile
+   * <pre>
    * Verify the following cases:
    *   empty array
    *   odd numbers of elements