Decentralize JClassLiterals.
This change allows JClassLiterals to be created apart from a JProgram. A new normalization pass runs before optimizations and creates all the ClassLiteralHolder implementation fields.
http://gwt-code-reviews.appspot.com/1375801/
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9808 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java b/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java
index fa14b5e..f256ff9 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java
@@ -18,7 +18,6 @@
import com.google.gwt.core.client.impl.ArtificialRescue;
import com.google.gwt.core.client.impl.ArtificialRescue.Rescue;
import com.google.gwt.dev.jjs.ast.Context;
-import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.JAnnotation;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JField;
@@ -26,6 +25,7 @@
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
+import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.impl.JsniRefLookup;
import com.google.gwt.dev.util.JsniRef;
@@ -97,7 +97,7 @@
for (String name : toRescue) {
JsniRef ref = JsniRef.parse("@" + classType.getName() + "::" + name);
final String[] errors = {null};
- HasEnclosingType node = JsniRefLookup.findJsniRefTarget(ref, program,
+ JNode node = JsniRefLookup.findJsniRefTarget(ref, program,
new JsniRefLookup.ErrorReporter() {
public void reportError(String error) {
errors[0] = error;
@@ -109,7 +109,11 @@
"Unable to artificially rescue " + name + ": " + errors[0]);
}
- currentClass.addArtificialRescue((JNode) node);
+ if (node instanceof JType) {
+ // Already added the type above.
+ } else {
+ currentClass.addArtificialRescue(node);
+ }
if (node instanceof JField) {
JField field = (JField) node;
if (!field.isFinal()) {
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 1b58ac7..19bbba7 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -81,6 +81,7 @@
import com.google.gwt.dev.jjs.impl.GenerateJavaAST;
import com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST;
import com.google.gwt.dev.jjs.impl.HandleCrossFragmentReferences;
+import com.google.gwt.dev.jjs.impl.ImplementClassLiteralsAsFields;
import com.google.gwt.dev.jjs.impl.JavaScriptObjectNormalizer;
import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.jjs.impl.JsFunctionClusterer;
@@ -622,6 +623,8 @@
// Replace references to JSO subtypes with JSO itself.
JavaScriptObjectNormalizer.exec(jprogram);
+ ImplementClassLiteralsAsFields.exec(jprogram);
+
/*
* 4) Possibly optimize some.
*
@@ -675,12 +678,6 @@
*/
protected static void draftOptimize(JProgram jprogram) {
Event draftOptimizeEvent = SpeedTracerLogger.start(CompilerEventType.DRAFT_OPTIMIZE);
- /*
- * Record the beginning of optimizations; this turns on certain checks that
- * guard against problematic late construction of things like class
- * literals.
- */
- jprogram.beginOptimizations();
Finalizer.exec(jprogram);
MakeCallsStatic.exec(jprogram);
jprogram.typeOracle.recomputeAfterOptimizations();
@@ -692,13 +689,6 @@
throws InterruptedException {
Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE);
- /*
- * Record the beginning of optimizations; this turns on certain checks that
- * guard against problematic late construction of things like class
- * literals.
- */
- jprogram.beginOptimizations();
-
List<OptimizerStats> allOptimizerStats = new ArrayList<OptimizerStats>();
int counter = 0;
int optimizationLevel = options.getOptimizationLevel();
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
index 5184def..2e33f6d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
@@ -15,9 +15,8 @@
*/
package com.google.gwt.dev.jjs.ast;
-import com.google.gwt.dev.jjs.InternalCompilerException;
+import com.google.gwt.dev.jjs.Correlation.Literal;
import com.google.gwt.dev.jjs.SourceInfo;
-import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
/**
* Java class literal expression.
@@ -27,152 +26,19 @@
* initializer.
*/
public class JClassLiteral extends JLiteral implements JAnnotationArgument {
- /**
- * Create an expression that will evaluate, at run time, to the class literal.
- * Cannot be called after optimizations begin.
- */
- static JMethodCall computeClassObjectAllocation(JProgram program,
- SourceInfo info, JType type) {
- String typeName = getTypeName(program, type);
- JMethod method = program.getIndexedMethod(type.getClassLiteralFactoryMethod());
-
- /*
- * Use the classForEnum() constructor even for enum subtypes to aid in
- * pruning supertype data.
- */
- boolean isEnumOrSubclass = false;
- if (type instanceof JClassType) {
- JEnumType maybeEnum = ((JClassType) type).isEnumOrSubclass();
- if (maybeEnum != null) {
- isEnumOrSubclass = true;
- method = program.getIndexedMethod(maybeEnum.getClassLiteralFactoryMethod());
- }
- }
-
- assert method != null;
-
- JMethodCall call = new JMethodCall(info, null, method);
- JStringLiteral packageName = program.getLiteralString(info,
- getPackageName(typeName));
- JStringLiteral className = program.getLiteralString(info,
- getClassName(typeName));
- call.addArgs(packageName, className);
-
- if (type instanceof JArrayType) {
- // There's only one seed function for all arrays
- JDeclaredType arrayType = program.getIndexedType("Array");
- call.addArg(new JNameOf(info, className.getType(), arrayType));
-
- } else if (type instanceof JClassType) {
- // Add the name of the seed function for concrete types
- call.addArg(new JNameOf(info, className.getType(), type));
-
- } else if (type instanceof JPrimitiveType) {
- // And give primitive types an illegal, though meaningful, value
- call.addArg(program.getLiteralString(info, " "
- + type.getJavahSignatureName()));
- }
-
- if (type instanceof JClassType) {
- /*
- * For non-array classes and enums, determine the class literal of the
- * supertype, if there is one. Arrays are excluded because they always
- * have Object as their superclass.
- */
- JClassType classType = (JClassType) type;
-
- JLiteral superclassLiteral;
- if (classType.getSuperClass() != null) {
- superclassLiteral = program.getLiteralClass(classType.getSuperClass());
- } else {
- superclassLiteral = program.getLiteralNull();
- }
-
- call.addArg(superclassLiteral);
-
- if (classType instanceof JEnumType) {
- JEnumType enumType = (JEnumType) classType;
- JMethod valuesMethod = null;
- JMethod valueOfMethod = null;
- for (JMethod methodIt : enumType.getMethods()) {
- if ("values".equals(methodIt.getName())) {
- if (methodIt.getParams().size() != 0) {
- continue;
- }
- valuesMethod = methodIt;
- } else if ("valueOf".equals(methodIt.getName())) {
- if (methodIt.getParams().size() != 1 ||
- methodIt.getParams().get(0).getType() != program.getTypeJavaLangString()) {
- continue;
- }
- valueOfMethod = methodIt;
- }
- }
- if (valuesMethod == null) {
- throw new InternalCompilerException(
- "Could not find enum values() method");
- }
- if (valueOfMethod == null) {
- throw new InternalCompilerException(
- "Could not find enum valueOf() method");
- }
- call.addArg(new JsniMethodRef(info, null, valuesMethod,
- program.getJavaScriptObject()));
- call.addArg(new JsniMethodRef(info, null, valueOfMethod,
- program.getJavaScriptObject()));
- } else if (isEnumOrSubclass) {
- // A subclass of an enum class
- call.addArg(program.getLiteralNull());
- call.addArg(program.getLiteralNull());
- }
- } else if (type instanceof JArrayType) {
- JArrayType arrayType = (JArrayType) type;
- JClassLiteral componentLiteral = program.getLiteralClass(arrayType.getElementType());
- call.addArg(componentLiteral);
- } else {
- assert (type instanceof JInterfaceType || type instanceof JPrimitiveType);
- }
- assert call.getArgs().size() == method.getParams().size() : "Argument / param mismatch "
- + call.toString() + " versus " + method.toString();
- return call;
+ private static SourceInfo addCorrelation(SourceInfo info) {
+ info.addCorrelation(info.getCorrelator().by(Literal.CLASS));
+ return info;
}
- private static String getClassName(String fullName) {
- int pos = fullName.lastIndexOf(".");
- return fullName.substring(pos + 1);
- }
+ private JField field;
- private static String getPackageName(String fullName) {
- int pos = fullName.lastIndexOf(".");
- return fullName.substring(0, pos + 1);
- }
-
- private static String getTypeName(JProgram program, JType type) {
- String typeName;
- if (type instanceof JArrayType) {
- typeName = type.getJsniSignatureName().replace('/', '.');
- // Mangle the class name to match hosted mode.
- if (program.isJavaScriptObject(((JArrayType) type).getLeafType())) {
- typeName = typeName.replace(";", "$;");
- }
- } else {
- typeName = type.getName();
- // Mangle the class name to match hosted mode.
- if (program.isJavaScriptObject(type)) {
- typeName += '$';
- }
- }
- return typeName;
- }
-
- private final JField field;
private final JType refType;
- public JClassLiteral(SourceInfo sourceInfo, JType type, JField field) {
- super(sourceInfo);
+ public JClassLiteral(SourceInfo sourceInfo, JType type) {
+ super(addCorrelation(sourceInfo));
refType = type;
- this.field = field;
}
public JNode annotationNode() {
@@ -194,6 +60,14 @@
return field.getType();
}
+ /**
+ * @param field the field to set
+ */
+ public void setField(JField field) {
+ assert field != null;
+ this.field = field;
+ }
+
public void traverse(JVisitor visitor, Context ctx) {
if (visitor.visit(this, ctx)) {
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
index 3a206fb..1ce797a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
@@ -25,8 +25,8 @@
*/
public class JNewArray extends JExpression {
- public static JNewArray createDims(JProgram program, SourceInfo info,
- JArrayType arrayType, List<JExpression> dims) {
+ public static JNewArray createDims(SourceInfo info, JArrayType arrayType,
+ List<JExpression> dims) {
List<JClassLiteral> classLiterals = new ArrayList<JClassLiteral>();
// Produce all class literals that will eventually get generated.
@@ -41,7 +41,7 @@
JType cur = arrayType;
for (int i = 0; i < realDims; ++i) {
// Walk down each type from most dims to least.
- JClassLiteral classLit = program.getLiteralClass(cur);
+ JClassLiteral classLit = new JClassLiteral(info.makeChild(), cur);
classLiterals.add(classLit);
cur = ((JArrayType) cur).getElementType();
}
@@ -49,10 +49,10 @@
classLiterals);
}
- public static JNewArray createInitializers(JProgram program, SourceInfo info,
+ public static JNewArray createInitializers(SourceInfo info,
JArrayType arrayType, List<JExpression> initializers) {
List<JClassLiteral> classLiterals = new ArrayList<JClassLiteral>();
- classLiterals.add(program.getLiteralClass(arrayType));
+ classLiterals.add(new JClassLiteral(info.makeChild(), arrayType));
return new JNewArray(info, arrayType.getNonNull(), null, initializers,
classLiterals);
}
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 aa3977f..af5e68e 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
@@ -311,7 +311,7 @@
*/
public final List<List<JMethod>> entryMethods = new ArrayList<List<JMethod>>();
- public final Map<String, HasEnclosingType> jsniMap = new HashMap<String, HasEnclosingType>();
+ public final Map<String, JNode> jsniMap = new HashMap<String, JNode>();
public final JTypeOracle typeOracle = new JTypeOracle(this);
@@ -322,8 +322,6 @@
private final HashMap<JType, JArrayType> arrayTypes = new HashMap<JType, JArrayType>();
- private final Map<JType, JClassLiteral> classLiterals = new IdentityHashMap<JType, JClassLiteral>();
-
/**
* A factory to create correlations.
*/
@@ -343,11 +341,6 @@
private JMethod nullMethod;
- /**
- * Turned on once optimizations begin.
- */
- private boolean optimizationsStarted = false;
-
private Map<JReferenceType, Integer> queryIds;
/**
@@ -411,15 +404,6 @@
}
}
- /**
- * Record the start of optimizations, which disables certain problematic
- * constructions. In particular, new class literals cannot be created once
- * optimization starts.
- */
- public void beginOptimizations() {
- optimizationsStarted = true;
- }
-
public JClassType createClass(SourceInfo info, String name,
boolean isAbstract, boolean isFinal) {
JClassType x = new JClassType(info, name, isAbstract, isFinal);
@@ -860,61 +844,6 @@
return JCharLiteral.get(value);
}
- /**
- * May not be called once optimizations begin; all possible class literals
- * must be created up front.
- */
- public JClassLiteral getLiteralClass(JType type) {
- JClassLiteral classLiteral = classLiterals.get(type);
- if (classLiteral == null) {
- if (optimizationsStarted) {
- throw new InternalCompilerException(
- "New class literals cannot be created once optimizations have started; type '"
- + type + "'");
- }
-
- SourceInfo info = typeSpecialClassLiteralHolder.getSourceInfo();
-
- // Create the allocation expression FIRST since this may be recursive on
- // super type (this forces the super type classLit to be created first).
- boolean isObjectExternal = getTypeJavaLangObject().isExternal();
- JExpression alloc = isObjectExternal ? null :
- JClassLiteral.computeClassObjectAllocation(this,info, type);
-
- // Create a field in the class literal holder to hold the object.
- JField field = new JField(info, getClassLiteralName(type),
- typeSpecialClassLiteralHolder, getTypeJavaLangClass(),
- true, Disposition.FINAL);
- typeSpecialClassLiteralHolder.addField(field);
-
- // Initialize the field.
- if (alloc != null) {
- JFieldRef fieldRef = new JFieldRef(info, null, field,
- typeSpecialClassLiteralHolder);
- JDeclarationStatement decl = new JDeclarationStatement(info, fieldRef,
- alloc);
- JMethodBody clinitBody = (JMethodBody)
- typeSpecialClassLiteralHolder.getMethods().get(0).getBody();
- clinitBody.getBlock().addStmt(decl);
- }
-
- SourceInfo literalInfo = createSourceInfoSynthetic(JProgram.class);
- literalInfo.addCorrelation(correlator.by(Literal.CLASS));
- classLiteral = new JClassLiteral(literalInfo, type, field);
- classLiterals.put(type, classLiteral);
- } else {
- // Make sure the field hasn't been pruned.
- JField field = classLiteral.getField();
- if (optimizationsStarted
- && !field.getEnclosingType().getFields().contains(field)) {
- throw new InternalCompilerException(
- "Getting a class literal whose field holder has already been pruned; type '"
- + type + " '");
- }
- }
- return classLiteral;
- }
-
public JDoubleLiteral getLiteralDouble(double d) {
return JDoubleLiteral.get(d);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodBody.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodBody.java
index c5d5f09..a64b394 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodBody.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodBody.java
@@ -18,6 +18,7 @@
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JAbstractMethodBody;
+import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsFunction;
@@ -36,6 +37,7 @@
*/
public class JsniMethodBody extends JAbstractMethodBody {
+ private List<JClassLiteral> classRefs = Collections.emptyList();
private JsFunction jsFunction = null;
private List<JsniFieldRef> jsniFieldRefs = Collections.emptyList();
private List<JsniMethodRef> jsniMethodRefs = Collections.emptyList();
@@ -47,6 +49,13 @@
}
/**
+ * Adds a reference from this method to a Java class literal.
+ */
+ public void addClassRef(JClassLiteral ref) {
+ classRefs = Lists.add(classRefs, ref);
+ }
+
+ /**
* Adds a reference from this method to a Java field.
*/
public void addJsniRef(JsniFieldRef ref) {
@@ -60,6 +69,13 @@
jsniMethodRefs = Lists.add(jsniMethodRefs, ref);
}
+ /**
+ * Return this method's references to Java class literals.
+ */
+ public List<JClassLiteral> getClassRefs() {
+ return classRefs;
+ }
+
public JsFunction getFunc() {
assert (this.jsFunction != null);
return jsFunction;
@@ -104,6 +120,7 @@
public void traverse(JVisitor visitor, Context ctx) {
if (visitor.visit(this, ctx)) {
+ classRefs = visitor.acceptImmutable(classRefs);
jsniFieldRefs = visitor.acceptImmutable(jsniFieldRefs);
jsniMethodRefs = visitor.acceptImmutable(jsniMethodRefs);
}
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 de107d4..54871d6 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
@@ -21,14 +21,12 @@
import com.google.gwt.dev.cfg.Properties;
import com.google.gwt.dev.cfg.Property;
import com.google.gwt.dev.jjs.InternalCompilerException;
-import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.Context;
-import com.google.gwt.dev.jjs.ast.HasEnclosingType;
-import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JField;
+import com.google.gwt.dev.jjs.ast.JIntLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNewArray;
@@ -282,8 +280,8 @@
throw new UnableToCompleteException();
}
final String lookupErrorHolder[] = new String[1];
- HasEnclosingType referent = JsniRefLookup.findJsniRefTarget(jsniRef,
- program, new JsniRefLookup.ErrorReporter() {
+ JNode referent = JsniRefLookup.findJsniRefTarget(jsniRef, program,
+ new JsniRefLookup.ErrorReporter() {
public void reportError(String error) {
lookupErrorHolder[0] = error;
}
@@ -512,21 +510,15 @@
*/
private static void installInitialLoadSequenceField(JProgram program,
LinkedHashSet<Integer> initialLoadSequence) {
+ // Arg 1 is initialized in the source as "new int[]{}".
JMethodCall constructorCall = ReplaceRunAsyncs.getBrowserLoaderConstructor(program);
- assert ((JReferenceType) constructorCall.getArgs().get(1).getType()).getUnderlyingType() instanceof JArrayType;
- assert ((JArrayType) ((JReferenceType) constructorCall.getArgs().get(1).getType()).getUnderlyingType()).getElementType() == JPrimitiveType.INT;
+ JNewArray newArray = (JNewArray) constructorCall.getArgs().get(1);
+ assert newArray.getArrayType().getElementType() == JPrimitiveType.INT;
+ assert newArray.initializers.size() == 0;
- SourceInfo info = program.createSourceInfoSynthetic(ReplaceRunAsyncs.class);
- List<JExpression> intExprs = new ArrayList<JExpression>();
for (int sp : initialLoadSequence) {
- intExprs.add(program.getLiteralInt(sp));
+ newArray.initializers.add(JIntLiteral.get(sp));
}
- /*
- * Note: the following field is known to have a manually installed
- * initializer, of new int[0].
- */
- constructorCall.setArg(1, JNewArray.createInitializers(program, info,
- program.getTypeArray(JPrimitiveType.INT), intExprs));
}
private static <T> T last(T[] array) {
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 42e284c..1ebe42e 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
@@ -192,6 +192,7 @@
@Override
public boolean visit(JClassLiteral x, Context ctx) {
JField field = x.getField();
+ assert field != null;
rescue(field);
return true;
}
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 f727a48..b0f4fbb 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
@@ -23,7 +23,6 @@
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.HasAnnotations;
-import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.JAnnotation;
import com.google.gwt.dev.jjs.ast.JAnnotation.Property;
import com.google.gwt.dev.jjs.ast.JAnnotationArgument;
@@ -39,6 +38,7 @@
import com.google.gwt.dev.jjs.ast.JCaseStatement;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JCharLiteral;
+import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConditional;
import com.google.gwt.dev.jjs.ast.JConstructor;
@@ -524,17 +524,18 @@
currentClass.getMethods().remove(2);
} else {
tryFindUpRefs(method);
+ SourceInfo info = method.getSourceInfo();
if (isScript(program)
&& currentClass == program.getIndexedType("Array")) {
// Special implementation: return this.arrayClass
- SourceInfo info = method.getSourceInfo();
implementMethod(
method,
new JFieldRef(info, new JThisRef(info,
(JClassType) currentClass),
program.getIndexedField("Array.arrayClass"), currentClass));
} else {
- implementMethod(method, program.getLiteralClass(currentClass));
+ implementMethod(method, new JClassLiteral(info.makeChild(),
+ currentClass));
}
}
}
@@ -919,7 +920,7 @@
initializers.add(dispProcessExpression(expression));
}
}
- return JNewArray.createInitializers(program, info, type, initializers);
+ return JNewArray.createInitializers(info, type, initializers);
} else {
List<JExpression> dims = new ArrayList<JExpression>();
for (Expression dimension : x.dimensions) {
@@ -930,7 +931,7 @@
dims.add(dispProcessExpression(dimension));
}
}
- return JNewArray.createDims(program, info, type, dims);
+ return JNewArray.createDims(info, type, dims);
}
}
@@ -944,7 +945,7 @@
initializers.add(dispProcessExpression(expression));
}
}
- return JNewArray.createInitializers(program, info, type, initializers);
+ return JNewArray.createInitializers(info, type, initializers);
}
JExpression processExpression(ArrayReference x) {
@@ -1034,8 +1035,9 @@
}
JExpression processExpression(ClassLiteralAccess x) {
+ SourceInfo info = makeSourceInfo(x);
JType type = (JType) typeMap.get(x.targetType);
- return program.getLiteralClass(type);
+ return new JClassLiteral(info, type);
}
JExpression processExpression(CombinedBinaryExpression x) {
@@ -1699,7 +1701,7 @@
} else {
/**
* <pre>
- * for (Iterator<T> i$iterator = collection.iterator(); i$iterator.hasNext(); ) {
+ * for (Iterator<T> i$iterator = collection.iterator(); i$iterator.hasNext();) {
* T elementVar = i$iterator.next();
* // user action
* }
@@ -2086,8 +2088,8 @@
initializers.add(args[i]);
}
JArrayType lastParamType = (JArrayType) typeMap.get(params[varArg]);
- JNewArray newArray = JNewArray.createInitializers(program,
- SourceOrigin.UNKNOWN, lastParamType, initializers);
+ JNewArray newArray = JNewArray.createInitializers(SourceOrigin.UNKNOWN,
+ lastParamType, initializers);
call.addArg(newArray);
}
@@ -2571,7 +2573,8 @@
type = getOrCreateExternalType(info,
((ReferenceBinding) value).compoundName);
}
- return Lists.<JAnnotationArgument> create(program.getLiteralClass(type));
+ return Lists.<JAnnotationArgument> create(new JClassLiteral(
+ info.makeChild(), type));
} else if (value instanceof Constant) {
return Lists.create((JAnnotationArgument) dispatch("processConstant",
@@ -2910,7 +2913,7 @@
JFieldRef fieldRef = new JFieldRef(fieldInfo, null, field, type);
initializers.add(fieldRef);
}
- JNewArray newExpr = JNewArray.createInitializers(program, fieldInfo,
+ JNewArray newExpr = JNewArray.createInitializers(fieldInfo,
enumArrayType, initializers);
JFieldRef valuesRef = new JFieldRef(fieldInfo, null, valuesField, type);
JDeclarationStatement declStmt = new JDeclarationStatement(fieldInfo,
@@ -2962,8 +2965,7 @@
}
}
- private HasEnclosingType findJsniRefTarget(final SourceInfo info,
- String ident) {
+ private JNode findJsniRefTarget(final SourceInfo info, String ident) {
JsniRef parsed = JsniRef.parse(ident);
if (parsed == null) {
JsniCollector.reportJsniError(info, methodDecl,
@@ -2981,6 +2983,11 @@
});
}
+ private void processClassLiteral(JClassLiteral classLiteral, JsContext ctx) {
+ assert !ctx.isLvalue();
+ nativeMethodBody.addClassRef(classLiteral);
+ }
+
private void processField(JsNameRef nameRef, SourceInfo info,
JField field, JsContext ctx) {
/*
@@ -3020,12 +3027,15 @@
// TODO: make this tighter when we have real source info
// JSourceInfo info = translateInfo(nameRef.getInfo());
String ident = nameRef.getIdent();
- HasEnclosingType node = program.jsniMap.get(ident);
+ JNode node = program.jsniMap.get(ident);
if (node == null) {
node = findJsniRefTarget(info, ident);
if (node == null) {
return; // already reported error
}
+ if (node instanceof JType) {
+ node = new JClassLiteral(info.makeChild(), (JType) node);
+ }
program.jsniMap.put(ident, node);
}
@@ -3033,9 +3043,11 @@
processField(nameRef, info, (JField) node, ctx);
} else if (node instanceof JMethod) {
processMethod(nameRef, info, (JMethod) node, ctx);
+ } else if (node instanceof JClassLiteral) {
+ processClassLiteral((JClassLiteral) node, ctx);
} else {
- throw new InternalCompilerException((HasSourceInfo) node,
- "JSNI reference to something other than a field or method?", null);
+ throw new InternalCompilerException(node,
+ "JSNI reference to something other than a class, field, or method?", null);
}
}
}
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 82531e9..80517a8 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
@@ -1340,7 +1340,7 @@
JsNameRef ref = (JsNameRef) x.getQualifier();
String ident = ref.getIdent();
if (isJsniIdent(ident)) {
- HasEnclosingType node = program.jsniMap.get(ident);
+ JNode node = program.jsniMap.get(ident);
assert node instanceof JConstructor;
assert ref.getQualifier() == null;
JsName jsName = names.get(node);
@@ -1357,8 +1357,12 @@
public void endVisit(JsNameRef x, JsContext ctx) {
String ident = x.getIdent();
if (isJsniIdent(ident)) {
- HasEnclosingType node = program.jsniMap.get(ident);
+ JNode node = program.jsniMap.get(ident);
assert (node != null);
+ if (node instanceof JClassLiteral) {
+ node = ((JClassLiteral) node).getField();
+ assert node != null;
+ }
if (node instanceof JField) {
JField field = (JField) node;
JsName jsName = names.get(field);
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
new file mode 100644
index 0000000..017e69b
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java
@@ -0,0 +1,309 @@
+/*
+ * 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.Correlation.Literal;
+import com.google.gwt.dev.jjs.InternalCompilerException;
+import com.google.gwt.dev.jjs.SourceInfo;
+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.JDeclarationStatement;
+import com.google.gwt.dev.jjs.ast.JDeclaredType;
+import com.google.gwt.dev.jjs.ast.JEnumType;
+import com.google.gwt.dev.jjs.ast.JField;
+import com.google.gwt.dev.jjs.ast.JFieldRef;
+import com.google.gwt.dev.jjs.ast.JInterfaceType;
+import com.google.gwt.dev.jjs.ast.JLiteral;
+import com.google.gwt.dev.jjs.ast.JMethod;
+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.JStringLiteral;
+import com.google.gwt.dev.jjs.ast.JType;
+import com.google.gwt.dev.jjs.ast.JField.Disposition;
+import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
+import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+/**
+ * Create fields to represent the mechanical implementation of class literals.
+ * Must be done after all class literals are created, but before optimizations
+ * begin. {@link ControlFlowAnalyzer} depends on this.
+ * <p>
+ * Class literals are implemented as static field references. The static fields
+ * are all put into the special com.google.gwt.lang.ClassLiteralHolder class.
+ * 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.
+ * <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);
+ x.setField(field);
+ }
+ }
+
+ public static void exec(JProgram program) {
+ Event normalizerEvent = SpeedTracerLogger.start(CompilerEventType.NORMALIZER);
+ new ImplementClassLiteralsAsFields(program).execImpl();
+ normalizerEvent.end();
+ }
+
+ private static String getClassName(String fullName) {
+ int pos = fullName.lastIndexOf(".");
+ return fullName.substring(pos + 1);
+ }
+
+ private static String getPackageName(String fullName) {
+ int pos = fullName.lastIndexOf(".");
+ return fullName.substring(0, pos + 1);
+ }
+
+ private final Map<JType, JField> classLiteralFields = new IdentityHashMap<JType, JField>();
+ private final JMethodBody classLiteralHolderClinitBody;
+ private final JProgram program;
+ private final JClassType typeClassLiteralHolder;
+
+ private ImplementClassLiteralsAsFields(JProgram program) {
+ this.program = program;
+ this.typeClassLiteralHolder = program.getTypeClassLiteralHolder();
+ this.classLiteralHolderClinitBody =
+ (JMethodBody) typeClassLiteralHolder.getMethods().get(0).getBody();
+ }
+
+ /**
+ * Create an expression that will evaluate, at run time, to the class literal.
+ * Causes recursive literal create (super type, array element type). Examples:
+ *
+ * Class:
+ *
+ * <pre>
+ * Class.createForClass("java.lang.", "Object", /JNameOf/"java.lang.Object", null)
+ * Class.createForClass("java.lang.", "Exception", /JNameOf/"java.lang.Exception", Throwable.class)
+ * </pre>
+ *
+ * Interface:
+ *
+ * <pre>
+ * Class.createForInterface("java.lang.", "Comparable")
+ * </pre>
+ *
+ * Primitive:
+ *
+ * <pre>
+ * Class.createForPrimitive("", "int", " I")
+ * </pre>
+ *
+ * Array:
+ *
+ * <pre>
+ * 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", /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", /JNameOf/"com.example.MyEnum$1", MyEnum.class,
+ * null, null))
+ * </pre>
+ */
+ private JMethodCall computeClassObjectAllocation(SourceInfo info, JType type) {
+ String typeName = getTypeName(type);
+
+ JMethod method = program.getIndexedMethod(type.getClassLiteralFactoryMethod());
+
+ /*
+ * Use the classForEnum() constructor even for enum subtypes to aid in
+ * pruning supertype data.
+ */
+ boolean isEnumOrSubclass = false;
+ if (type instanceof JClassType) {
+ JEnumType maybeEnum = ((JClassType) type).isEnumOrSubclass();
+ if (maybeEnum != null) {
+ isEnumOrSubclass = true;
+ method = program.getIndexedMethod(maybeEnum.getClassLiteralFactoryMethod());
+ }
+ }
+
+ assert method != null;
+
+ JMethodCall call = new JMethodCall(info, null, method);
+ JStringLiteral packageName = program.getLiteralString(info, getPackageName(typeName));
+ JStringLiteral className = program.getLiteralString(info, getClassName(typeName));
+ call.addArgs(packageName, className);
+
+ if (type instanceof JArrayType) {
+ // There's only one seed function for all arrays
+ JDeclaredType arrayType = program.getIndexedType("Array");
+ call.addArg(new JNameOf(info, className.getType(), arrayType));
+
+ } else if (type instanceof JClassType) {
+ // Add the name of the seed function for concrete types
+ call.addArg(new JNameOf(info, className.getType(), type));
+
+ } else if (type instanceof JPrimitiveType) {
+ // And give primitive types an illegal, though meaningful, value
+ call.addArg(program.getLiteralString(info, " " + type.getJavahSignatureName()));
+ }
+
+ if (type instanceof JClassType) {
+ /*
+ * For non-array classes and enums, determine the class literal of the
+ * supertype, if there is one. Arrays are excluded because they always
+ * have Object as their superclass.
+ */
+ JClassType classType = (JClassType) type;
+
+ JLiteral superclassLiteral;
+ if (classType.getSuperClass() != null) {
+ superclassLiteral = createDependentClassLiteral(info, classType.getSuperClass());
+ } else {
+ superclassLiteral = JNullLiteral.INSTANCE;
+ }
+
+ call.addArg(superclassLiteral);
+
+ if (classType instanceof JEnumType) {
+ JEnumType enumType = (JEnumType) classType;
+ JMethod valuesMethod = null;
+ JMethod valueOfMethod = null;
+ for (JMethod methodIt : enumType.getMethods()) {
+ if ("values".equals(methodIt.getName())) {
+ if (methodIt.getParams().size() != 0) {
+ continue;
+ }
+ valuesMethod = methodIt;
+ } else if ("valueOf".equals(methodIt.getName())) {
+ if (methodIt.getParams().size() != 1
+ || methodIt.getParams().get(0).getType() != program.getTypeJavaLangString()) {
+ continue;
+ }
+ valueOfMethod = methodIt;
+ }
+ }
+ if (valuesMethod == null) {
+ throw new InternalCompilerException("Could not find enum values() method");
+ }
+ if (valueOfMethod == null) {
+ throw new InternalCompilerException("Could not find enum valueOf() method");
+ }
+ call.addArg(new JsniMethodRef(info, null, valuesMethod, program.getJavaScriptObject()));
+ call.addArg(new JsniMethodRef(info, null, valueOfMethod, program.getJavaScriptObject()));
+ } else if (isEnumOrSubclass) {
+ // A subclass of an enum class
+ call.addArg(JNullLiteral.INSTANCE);
+ call.addArg(JNullLiteral.INSTANCE);
+ }
+ } else if (type instanceof JArrayType) {
+ JArrayType arrayType = (JArrayType) type;
+ JClassLiteral componentLiteral =
+ createDependentClassLiteral(info, arrayType.getElementType());
+ call.addArg(componentLiteral);
+ } else {
+ assert (type instanceof JInterfaceType || type instanceof JPrimitiveType);
+ }
+ assert call.getArgs().size() == method.getParams().size() : "Argument / param mismatch "
+ + call.toString() + " versus " + method.toString();
+ return call;
+ }
+
+ private JClassLiteral createDependentClassLiteral(SourceInfo info, JType type) {
+ JClassLiteral classLiteral = new JClassLiteral(info.makeChild(), type);
+ JField field = resolveClassLiteralField(classLiteral);
+ classLiteral.setField(field);
+ return classLiteral;
+ }
+
+ private void execImpl() {
+ NormalizeVisitor visitor = new NormalizeVisitor();
+ visitor.accept(program);
+ }
+
+ private String getTypeName(JType type) {
+ String typeName;
+ if (type instanceof JArrayType) {
+ typeName = type.getJsniSignatureName().replace('/', '.');
+ // Mangle the class name to match hosted mode.
+ if (program.isJavaScriptObject(((JArrayType) type).getLeafType())) {
+ typeName = typeName.replace(";", "$;");
+ }
+ } else {
+ typeName = type.getName();
+ // Mangle the class name to match hosted mode.
+ if (program.isJavaScriptObject(type)) {
+ typeName += '$';
+ }
+ }
+ return typeName;
+ }
+
+ /**
+ * Takes the form:
+ *
+ * <pre>
+ * class ClassLiteralHolder {
+ * Class Ljava_lang_Object_2_classLit =
+ * Class.createForClass("java.lang.", "Object", /JNameOf/"java.lang.Object", null)
+ * }
+ * </pre>
+ */
+ private JField resolveClassLiteralField(JClassLiteral classLiteral) {
+ JType type = classLiteral.getRefType();
+ JField field = classLiteralFields.get(type);
+ if (field == null) {
+ // Create the allocation expression FIRST since this may be recursive on
+ // super type (this forces the super type classLit to be created first).
+ SourceInfo info = typeClassLiteralHolder.getSourceInfo().makeChild();
+ JMethodCall alloc = computeClassObjectAllocation(info, type);
+ // Create a field in the class literal holder to hold the object.
+ field =
+ new JField(info, program.getClassLiteralName(type), typeClassLiteralHolder, program
+ .getTypeJavaLangClass(), true, Disposition.FINAL);
+ typeClassLiteralHolder.addField(field);
+ info.addCorrelation(info.getCorrelator().by(Literal.CLASS));
+
+ // Initialize the field.
+ JFieldRef fieldRef = new JFieldRef(info, null, field, typeClassLiteralHolder);
+ JDeclarationStatement decl = new JDeclarationStatement(info, fieldRef, alloc);
+ classLiteralHolderClinitBody.getBlock().addStmt(decl);
+ classLiteralFields.put(type, field);
+ }
+ return field;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectNormalizer.java
index a137b88..743b6b9 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectNormalizer.java
@@ -69,7 +69,7 @@
public void endVisit(JClassLiteral x, Context ctx) {
JType newType = translate(x.getRefType());
if (newType != x.getRefType()) {
- ctx.replaceMe(program.getLiteralClass(newType));
+ ctx.replaceMe(new JClassLiteral(x.getSourceInfo(), newType));
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsniRefLookup.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsniRefLookup.java
index 7ea3d1d..b43a622 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsniRefLookup.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsniRefLookup.java
@@ -15,14 +15,13 @@
*/
package com.google.gwt.dev.jjs.impl;
-import com.google.gwt.dev.jjs.ast.HasEnclosingType;
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.JConstructor;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JMethod;
+import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
@@ -56,8 +55,8 @@
* found. If the return value is <code>null</code>,
* <code>errorReporter</code> will have been invoked.
*/
- public static HasEnclosingType findJsniRefTarget(JsniRef ref,
- JProgram program, JsniRefLookup.ErrorReporter errorReporter) {
+ public static JNode findJsniRefTarget(JsniRef ref, JProgram program,
+ JsniRefLookup.ErrorReporter errorReporter) {
String className = ref.className();
JType type = null;
if (!className.equals("null")) {
@@ -78,8 +77,7 @@
}
} else if (fieldName.equals(JsniRef.CLASS)) {
- JClassLiteral lit = program.getLiteralClass(type);
- return lit.getField();
+ return type;
} else if (type instanceof JPrimitiveType) {
errorReporter.reportError("May not refer to fields on primitive types");
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
index 84302ec..19627d5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
@@ -20,7 +20,6 @@
import com.google.gwt.dev.jdt.RebindPermutationOracle;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.ast.Context;
-import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
@@ -31,6 +30,7 @@
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.JNode;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
@@ -106,7 +106,7 @@
if (ref != null) {
final List<String> errors = new ArrayList<String>();
- HasEnclosingType node = JsniRefLookup.findJsniRefTarget(ref, program,
+ JNode node = JsniRefLookup.findJsniRefTarget(ref, program,
new JsniRefLookup.ErrorReporter() {
public void reportError(String error) {
errors.add(error);
diff --git a/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java b/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
index ce8b05e..f96623d 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
@@ -29,6 +29,7 @@
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.impl.AssertionNormalizer;
import com.google.gwt.dev.jjs.impl.BuildTypeMap;
+import com.google.gwt.dev.jjs.impl.ImplementClassLiteralsAsFields;
import com.google.gwt.dev.jjs.impl.TypeLinker;
import com.google.gwt.dev.jjs.impl.FixAssignmentToUnbox;
import com.google.gwt.dev.jjs.impl.GenerateJavaAST;
@@ -275,6 +276,8 @@
// Replace references to JSO subtypes with JSO itself.
JavaScriptObjectNormalizer.exec(jprogram);
+ ImplementClassLiteralsAsFields.exec(jprogram);
+
// Tree is now ready to optimize.
return jprogram;
}
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/JsniRefLookupTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/JsniRefLookupTest.java
index f6b24dc..f9a6557 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/JsniRefLookupTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/JsniRefLookupTest.java
@@ -17,9 +17,9 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.javac.impl.MockJavaResource;
-import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JMethod;
+import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.impl.JsniRefLookup.ErrorReporter;
@@ -238,17 +238,17 @@
{
MockErrorReporter errors = new MockErrorReporter();
- HasEnclosingType res = lookup("test.Foo::bogoField", errors);
+ lookup("test.Foo::bogoField", errors);
errors.assertHasError();
}
{
MockErrorReporter errors = new MockErrorReporter();
- HasEnclosingType res = lookup("test.Foo::bogoMethod()", errors);
+ lookup("test.Foo::bogoMethod()", errors);
errors.assertHasError();
}
{
MockErrorReporter errors = new MockErrorReporter();
- HasEnclosingType res = lookup("test.Foo::new(J)", errors);
+ lookup("test.Foo::new(J)", errors);
errors.assertHasError();
}
}
@@ -367,7 +367,7 @@
}
{
MockErrorReporter errors = new MockErrorReporter();
- HasEnclosingType res = lookup("test.Bar::addTwoOverloaded(*)", errors);
+ lookup("test.Bar::addTwoOverloaded(*)", errors);
errors.assertHasError();
}
@@ -398,7 +398,7 @@
}
{
MockErrorReporter errors = new MockErrorReporter();
- HasEnclosingType res = lookup("test.Bar::foo(*)", errors);
+ lookup("test.Bar::foo(*)", errors);
errors.assertHasError();
}
@@ -463,7 +463,7 @@
}
{
MockErrorReporter errors = new MockErrorReporter();
- JMethod res = (JMethod) lookup("test.Intf::foo(*)", errors);
+ lookup("test.Intf::foo(*)", errors);
errors.assertHasError();
}
}
@@ -488,12 +488,12 @@
// test private entries in the superclass
{
MockErrorReporter errors = new MockErrorReporter();
- JMethod res = (JMethod) lookup("test.PrivateSub::methodSup()", errors);
+ lookup("test.PrivateSub::methodSup()", errors);
errors.assertHasError();
}
{
MockErrorReporter errors = new MockErrorReporter();
- JField res = (JField) lookup("test.PrivateSub::fieldSup", errors);
+ lookup("test.PrivateSub::fieldSup", errors);
errors.assertHasError();
}
}
@@ -508,17 +508,17 @@
}
{
MockErrorReporter errors = new MockErrorReporter();
- HasEnclosingType res = lookup("test.Foo::addTwoOverloaded(*)", errors);
+ lookup("test.Foo::addTwoOverloaded(*)", errors);
errors.assertHasError();
}
{
MockErrorReporter errors = new MockErrorReporter();
- HasEnclosingType res = lookup("test.Foo::bogoMethod(*)", errors);
+ lookup("test.Foo::bogoMethod(*)", errors);
errors.assertHasError();
}
}
- private HasEnclosingType lookup(String refString, MockErrorReporter errors) {
+ private JNode lookup(String refString, MockErrorReporter errors) {
return JsniRefLookup.findJsniRefTarget(JsniRef.parse(refString), program,
errors);
}