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);