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