Simplify JArrayType handling; reduce serialization footprint.
http://gwt-code-reviews.appspot.com/1352803/show
Review by: cromwellian@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9711 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
index 7652920..0fe86e0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
@@ -22,24 +22,15 @@
*/
public class JArrayType extends JReferenceType {
- private static String calcName(JType leafType, int dims) {
- String name = leafType.getName();
- for (int i = 0; i < dims; ++i) {
- name = name + "[]";
- }
- return name;
- }
+ private transient int dims = 0;
+ private final JType elementType;
+ private transient JType leafType = null;
- private int dims;
- private JType elementType;
- private JType leafType;
-
- public JArrayType(JType elementType, JType leafType, int dims) {
- super(leafType.getSourceInfo().makeChild(SourceOrigin.UNKNOWN), calcName(
- leafType, dims));
+ public JArrayType(JType elementType) {
+ super(elementType.getSourceInfo().makeChild(SourceOrigin.UNKNOWN),
+ elementType.getName() + "[]");
+ assert !(elementType instanceof JNonNullType);
this.elementType = elementType;
- this.leafType = leafType;
- this.dims = dims;
}
@Override
@@ -48,6 +39,12 @@
}
public int getDims() {
+ if (dims == 0) {
+ dims = 1;
+ if (elementType instanceof JArrayType) {
+ dims += ((JArrayType) elementType).getDims();
+ }
+ }
return dims;
}
@@ -57,23 +54,22 @@
@Override
public String getJavahSignatureName() {
- String s = leafType.getJavahSignatureName();
- for (int i = 0; i < dims; ++i) {
- s = "_3" + s;
- }
- return s;
+ return "_3" + elementType.getJavahSignatureName();
}
@Override
public String getJsniSignatureName() {
- String s = leafType.getJsniSignatureName();
- for (int i = 0; i < dims; ++i) {
- s = "[" + s;
- }
- return s;
+ return "[" + elementType.getJsniSignatureName();
}
public JType getLeafType() {
+ if (leafType == null) {
+ if (elementType instanceof JArrayType) {
+ leafType = ((JArrayType) elementType).getLeafType();
+ } else {
+ leafType = elementType;
+ }
+ }
return leafType;
}
@@ -87,7 +83,7 @@
}
public boolean isFinal() {
- return leafType.isFinal();
+ return elementType.isFinal();
}
public void traverse(JVisitor visitor, Context ctx) {
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 4945840..658fbd4 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
@@ -46,7 +46,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.TreeSet;
/**
* Root for the AST representing an entire Java program.
@@ -317,16 +316,12 @@
public final JTypeOracle typeOracle = new JTypeOracle(this);
/**
- * Sorted to avoid nondeterministic iteration.
- */
- private final Set<JArrayType> allArrayTypes = new TreeSet<JArrayType>(
- ARRAYTYPE_COMPARATOR);
-
- /**
* Special serialization treatment.
*/
private transient List<JDeclaredType> allTypes = new ArrayList<JDeclaredType>();
+ private final HashMap<JType, JArrayType> arrayTypes = new HashMap<JType, JArrayType>();
+
private final Map<JType, JClassLiteral> classLiterals = new IdentityHashMap<JType, JClassLiteral>();
/**
@@ -334,13 +329,6 @@
*/
private final CorrelationFactory correlator;
- /**
- * Each entry is a HashMap(JType => JArrayType), arranged such that the number
- * of dimensions is that index (plus one) at which the JArrayTypes having that
- * number of dimensions resides.
- */
- private final ArrayList<HashMap<JType, JArrayType>> dimensions = new ArrayList<HashMap<JType, JArrayType>>();
-
private final Map<String, JField> indexedFields = new HashMap<String, JField>();
private final Map<String, JMethod> indexedMethods = new HashMap<String, JMethod>();
@@ -775,11 +763,14 @@
}
/**
- * Returns a sorted set of array types, so the returned set can be iterated
+ * Returns a sorted list of array types, so the returned set can be iterated
* over without introducing nondeterminism.
*/
- public Set<JArrayType> getAllArrayTypes() {
- return allArrayTypes;
+ public List<JArrayType> getAllArrayTypes() {
+ ArrayList<JArrayType> result = new ArrayList<JArrayType>(
+ arrayTypes.values());
+ Collections.sort(result, ARRAYTYPE_COMPARATOR);
+ return result;
}
public List<JMethod> getAllEntryMethods() {
@@ -981,7 +972,7 @@
}
public int getQueryId(JReferenceType elementType) {
- assert (elementType == getRunTimeType(elementType));
+ assert (elementType == elementType.getUnderlyingType());
Integer integer = queryIds.get(elementType);
if (integer == null) {
return 0;
@@ -994,25 +985,6 @@
return runAsyncReplacements;
}
- /**
- * A run-time type is a type at the granularity that GWT tests at run time.
- * These include declared types, arrays of declared types, arrays of
- * primitives, and null. This is also the granularity for the notion of
- * instantiability recorded in {@link JTypeOracle}. This method returns the
- * narrowest supertype of <code>type</code> that is a run-time type.
- */
- public JReferenceType getRunTimeType(JReferenceType type) {
- type = type.getUnderlyingType();
- if (type instanceof JArrayType) {
- JArrayType typeArray = (JArrayType) type;
- if (typeArray.getLeafType() instanceof JNonNullType) {
- JNonNullType leafType = (JNonNullType) typeArray.getLeafType();
- type = getTypeArray(leafType.getUnderlyingType(), typeArray.getDims());
- }
- }
- return type;
- }
-
public List<Integer> getSplitPointInitialSequence() {
return splitPointInitialSequence;
}
@@ -1021,45 +993,26 @@
return instanceToStaticMap.get(method);
}
- public JArrayType getTypeArray(JType leafType, int dimensions) {
- assert (!(leafType instanceof JArrayType));
- HashMap<JType, JArrayType> typeToArrayType;
-
- // Create typeToArrayType maps for index slots that don't exist yet.
- //
- for (int i = this.dimensions.size(); i < dimensions; ++i) {
- typeToArrayType = new HashMap<JType, JArrayType>();
- this.dimensions.add(typeToArrayType);
- }
-
- // Get the map for array having this number of dimensions (biased by one
- // since we don't store non-arrays in there -- thus index 0 => 1 dim).
- //
- typeToArrayType = this.dimensions.get(dimensions - 1);
-
- JArrayType arrayType = typeToArrayType.get(leafType);
+ public JArrayType getTypeArray(JType elementType) {
+ JArrayType arrayType = arrayTypes.get(elementType);
if (arrayType == null) {
- JType elementType;
- if (dimensions == 1) {
- elementType = leafType;
- } else {
- elementType = getTypeArray(leafType, dimensions - 1);
- }
- arrayType = new JArrayType(elementType, leafType, dimensions);
- allArrayTypes.add(arrayType);
-
- /*
- * TODO(later): should we setup the various array types as an inheritance
- * heirarchy? Currently we're just doing all the heavy lifting in
- * JTypeOracle. If we tried to setup inheritance, we'd have to recompute
- * JTypeOracle if anything changed, so maybe this is better.
- */
- typeToArrayType.put(leafType, arrayType);
+ arrayType = new JArrayType(elementType);
+ arrayTypes.put(elementType, arrayType);
}
-
return arrayType;
}
+ public JArrayType getTypeArray(JType leafType, int dimensions) {
+ assert dimensions > 0;
+ assert (!(leafType instanceof JArrayType));
+ JArrayType result = getTypeArray(leafType);
+ while (dimensions > 1) {
+ result = getTypeArray(result);
+ --dimensions;
+ }
+ return result;
+ }
+
public JClassType getTypeClassLiteralHolder() {
return typeSpecialClassLiteralHolder;
}
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 8e4aeb3..09291fb 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
@@ -881,7 +881,7 @@
*/
private boolean isInstantiatedType(JReferenceType type,
Set<JReferenceType> instantiatedTypes) {
- type = program.getRunTimeType(type);
+ type = type.getUnderlyingType();
if (type.isExternal()) {
// TODO(tobyr) I don't know under what situations it is safe to assume
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
index 7504ea6..e023e72 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
@@ -190,7 +190,7 @@
JType elementType = type.getElementType();
int leafQueryId = -1;
if (elementType instanceof JReferenceType) {
- leafQueryId = program.getQueryId(program.getRunTimeType((JReferenceType) elementType));
+ leafQueryId = program.getQueryId(((JReferenceType) elementType).getUnderlyingType());
}
return leafQueryId;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
index c0ee478..9cbbf1a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
@@ -199,7 +199,7 @@
if (type == null || alreadyRan.contains(type)) {
return;
}
- assert (type == program.getRunTimeType(type));
+ assert (type == type.getUnderlyingType());
alreadyRan.add(type);
@@ -274,9 +274,9 @@
private void recordCast(JType targetType, JExpression rhs) {
if (targetType instanceof JReferenceType) {
- targetType = program.getRunTimeType((JReferenceType) targetType);
+ targetType = ((JReferenceType) targetType).getUnderlyingType();
// unconditional cast b/c it would've been a semantic error earlier
- JReferenceType rhsType = program.getRunTimeType((JReferenceType) rhs.getType());
+ JReferenceType rhsType = ((JReferenceType) rhs.getType()).getUnderlyingType();
// don't record a type for trivial casts that won't generate code
if (program.typeOracle.canTriviallyCast(rhsType,
(JReferenceType) targetType)) {
@@ -294,8 +294,8 @@
private void recordCastInternal(JReferenceType toType,
JReferenceType rhsType) {
- toType = program.getRunTimeType(toType);
- rhsType = program.getRunTimeType(rhsType);
+ toType = toType.getUnderlyingType();
+ rhsType = rhsType.getUnderlyingType();
Set<JReferenceType> querySet = queriedTypes.get(toType);
if (querySet == null) {
queryIds.put(toType, nextQueryId++);
@@ -420,7 +420,7 @@
replaceExpr = call;
} else if (toType instanceof JReferenceType) {
JExpression curExpr = expr;
- JReferenceType refType = program.getRunTimeType((JReferenceType) toType);
+ JReferenceType refType = ((JReferenceType) toType).getUnderlyingType();
JReferenceType argType = (JReferenceType) expr.getType();
if (program.typeOracle.canTriviallyCast(argType, refType)) {
// just remove the cast
@@ -536,7 +536,7 @@
JReferenceType argType = (JReferenceType) x.getExpr().getType();
JReferenceType toType = x.getTestType();
// Only tests on run-time types are supported
- assert (toType == program.getRunTimeType(toType));
+ assert (toType == toType.getUnderlyingType());
if (program.typeOracle.canTriviallyCast(argType, toType)) {
// trivially true if non-null; replace with a null test
JNullLiteral nullLit = program.getLiteralNull();
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 ef4c02e..de107d4 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
@@ -526,7 +526,7 @@
* initializer, of new int[0].
*/
constructorCall.setArg(1, JNewArray.createInitializers(program, info,
- program.getTypeArray(JPrimitiveType.INT, 1), intExprs));
+ 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 b67bb11..64c0a9b 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
@@ -555,7 +555,7 @@
* Track references and instantiability at the granularity of run-time
* types. For example, ignore nullness.
*/
- type = program.getRunTimeType(type);
+ type = type.getUnderlyingType();
boolean doVisit = false;
if (isInstantiated && !instantiatedTypes.contains(type)) {
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 46c1653..a346f4c 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
@@ -2904,7 +2904,7 @@
{
// $VALUES = new E[]{A,B,B};
SourceInfo fieldInfo = type.getSourceInfo().makeChild();
- JArrayType enumArrayType = program.getTypeArray(type, 1);
+ JArrayType enumArrayType = program.getTypeArray(type);
valuesField = program.createField(fieldInfo, "$VALUES", type,
enumArrayType, true, Disposition.FINAL);
fieldInfo.addCorrelation(program.getCorrelator().by(valuesField));
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 aec9b82..82531e9 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
@@ -144,7 +144,6 @@
import com.google.gwt.dev.util.collect.IdentityHashSet;
import com.google.gwt.dev.util.collect.Maps;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
@@ -262,7 +261,7 @@
* Make sure we record all of the program's array types since
* JProgram.traverse() doesn't iterate over them.
*/
- accept(new ArrayList<JArrayType>(program.getAllArrayTypes()));
+ accept(program.getAllArrayTypes());
}
@Override
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 08bc124..1bf3ea5 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
@@ -213,10 +213,8 @@
@Override
public boolean visit(JArrayType x, Context ctx) {
- accept(x.getLeafType());
- for (int i = 0, c = x.getDims(); i < c; ++i) {
- print("[]");
- }
+ accept(x.getElementType());
+ print("[]");
return false;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
index 667bc7d..784e2ff 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
@@ -16,7 +16,6 @@
package com.google.gwt.dev.jjs.impl;
import com.google.gwt.dev.jjs.InternalCompilerException;
-import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JField;
@@ -221,20 +220,11 @@
}
} else if (binding instanceof ArrayBinding) {
ArrayBinding arrayBinding = (ArrayBinding) binding;
-
- // Compute the JType for the leaf type
- JType leafType = (JType) get(arrayBinding.leafComponentType, failOnNull);
-
- if (leafType == null) {
+ JType elementType = (JType) get(arrayBinding.elementsType(), failOnNull);
+ if (elementType == null) {
return null;
}
-
- // Don't create a new JArrayType; use TypeMap to get the singleton
- // instance
- JArrayType arrayType = program.getTypeArray(leafType,
- arrayBinding.dimensions);
-
- return arrayType;
+ return program.getTypeArray(elementType);
} else if (binding instanceof BinaryTypeBinding) {
BinaryTypeBinding binaryBinding = (BinaryTypeBinding) binding;
String name = BuildTypeMap.dotify(binaryBinding.compoundName);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
index a83b59a..3be1164 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
@@ -693,7 +693,7 @@
if (elementType instanceof JReferenceType) {
JReferenceType refType = (JReferenceType) elementType;
if (!program.typeOracle.isInstantiatedType(refType)) {
- return program.getTypeArray(JNullType.INSTANCE, 1);
+ return program.getTypeArray(JNullType.INSTANCE);
} else if (elementType instanceof JArrayType) {
JArrayType newElementType = nullifyArrayType((JArrayType) elementType);
return program.getTypeArray(newElementType.getLeafType(),
diff --git a/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java b/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java
index 6d59a36..03d7460 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java
@@ -270,12 +270,12 @@
classBnn = classB.getNonNull();
classBaseNn = classBase.getNonNull();
- arrayOfA = program.getTypeArray(classA, 1);
- arrayOfB = program.getTypeArray(classB, 1);
- arrayOfBSub = program.getTypeArray(classBSub, 1);
- arrayOfC = program.getTypeArray(classC, 1);
- arrayOfObject = program.getTypeArray(classObject, 1);
- arrayOfInt = program.getTypeArray(program.getTypePrimitiveInt(), 1);
+ arrayOfA = program.getTypeArray(classA);
+ arrayOfB = program.getTypeArray(classB);
+ arrayOfBSub = program.getTypeArray(classBSub);
+ arrayOfC = program.getTypeArray(classC);
+ arrayOfObject = program.getTypeArray(classObject);
+ arrayOfInt = program.getTypeArray(program.getTypePrimitiveInt());
arrayOfArrayOfInt = program.getTypeArray(program.getTypePrimitiveInt(), 2);
arrayOfArrayOfB = program.getTypeArray(classB, 2);