Normalize Array.getClass()
It's kind of weird to have the magic Array class implement getClass() directly, which is normally final on Object. Since we had to special-case it in the compiler anyway, it seems better to just move the implementation there.
http://gwt-code-reviews.appspot.com/658802/show
Review by: tobyr
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8314 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index 06f21db..44414f4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -564,8 +564,7 @@
try {
// Create an override for getClass().
if (type instanceof JClassType
- && type != program.getTypeJavaLangObject()
- && type != program.getIndexedType("Array")) {
+ && type != program.getTypeJavaLangObject()) {
JMethod getClassMethod = program.createMethod(
type.getSourceInfo().makeChild(BuildDeclMapVisitor.class,
"Synthetic getClass()"), "getClass", 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 658c1cb..f5b512d 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
@@ -81,6 +81,7 @@
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JSwitchStatement;
+import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JThrowStatement;
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
@@ -450,8 +451,7 @@
// Write the body of the getClass() override.
if (currentClass instanceof JClassType
- && currentClass != program.getTypeJavaLangObject()
- && currentClass != program.getIndexedType("Array")) {
+ && currentClass != program.getTypeJavaLangObject()) {
JMethod method = currentClass.getMethods().get(2);
assert ("getClass".equals(method.getName()));
@@ -461,7 +461,15 @@
currentClass.getMethods().remove(2);
} else {
tryFindUpRefs(method);
- implementMethod(method, program.getLiteralClass(currentClass));
+ if (currentClass == program.getIndexedType("Array")) {
+ // Special implementation: return this.arrayClass
+ SourceInfo info = method.getSourceInfo();
+ implementMethod(method, new JFieldRef(info, new JThisRef(info,
+ program.getNonNullType(currentClass)),
+ program.getIndexedField("Array.arrayClass"), currentClass));
+ } else {
+ implementMethod(method, program.getLiteralClass(currentClass));
+ }
}
}
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 02ddedd..1d09a04 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
@@ -130,7 +130,7 @@
* @param seedType the primitive type of the array; 0: null; 1: zero; 2: false
* @return the new array
*/
- public static Array initDim(Class arrayClass, int typeId, int queryId,
+ public static Array initDim(Class<?> arrayClass, int typeId, int queryId,
int length, int seedType) {
Array result = createFromSeed(seedType, length);
initValues(arrayClass, typeId, queryId, result);
@@ -148,7 +148,7 @@
* @param seedType the primitive type of the array; 0: null; 1: zero; 2: false
* @return the new array
*/
- public static Array initDims(Class arrayClasses[], int[] typeIdExprs,
+ public static Array initDims(Class<?> arrayClasses[], int[] typeIdExprs,
int[] queryIdExprs, int[] dimExprs, int count, int seedType) {
return initDims(arrayClasses, typeIdExprs, queryIdExprs, dimExprs, 0,
count, seedType);
@@ -164,7 +164,7 @@
* @param array the JSON array that will be transformed into a GWT array
* @return values; having wrapped it for GWT
*/
- public static Array initValues(Class arrayClass, int typeId, int queryId,
+ public static Array initValues(Class<?> arrayClass, int typeId, int queryId,
Array array) {
ExpandoWrapper.wrapArray(array);
array.arrayClass = arrayClass;
@@ -235,7 +235,7 @@
return array;
}-*/;
- private static Array initDims(Class arrayClasses[], int[] typeIdExprs,
+ private static Array initDims(Class<?> arrayClasses[], int[] typeIdExprs,
int[] queryIdExprs, int[] dimExprs, int index, int count, int seedType) {
int length = dimExprs[index];
boolean isLastDim = (index == (count - 1));
@@ -265,12 +265,24 @@
* Explicitly initialize all fields to JS false values; see comment in
* ExpandoWrapper.initExpandos().
*/
+
+ /**
+ * Represents the array length. References to this field are magically
+ * translated.
+ */
public volatile int length = 0;
- protected Class arrayClass = null;
- protected int queryId = 0;
- @Override
- public Class getClass() {
- return arrayClass;
- }
+ /**
+ * 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;
+
+ /**
+ * The necessary cast target for objects stored into this array. Attempting to
+ * store an object that cannot satisfy the query id throws and
+ * {@link ArrayStoreException}.
+ */
+ protected int queryId = 0;
}
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 544dc2d..a5b5e96 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
@@ -57,7 +57,8 @@
StringBuffer code = new StringBuffer();
code.append("package com.google.gwt.lang;\n");
code.append("public final class Array {\n");
- code.append(" public int length;\n");
+ code.append(" public int length = 0;\n");
+ code.append(" protected Class<?> arrayClass = null;\n");
code.append("}\n");
return code;
}
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 fe8ead0..1a4d726 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
@@ -16,7 +16,6 @@
package com.google.gwt.dev.jjs.impl;
import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.javac.impl.MockJavaResource;
import com.google.gwt.dev.jjs.ast.JProgram;
/**
@@ -28,19 +27,6 @@
* live.
*/
public void testArrayIsInitial() throws UnableToCompleteException {
- sourceOracle.addOrReplace(new MockJavaResource("com.google.gwt.lang.Array") {
- @Override
- protected CharSequence getContent() {
- StringBuffer code = new StringBuffer();
- code.append("package com.google.gwt.lang;\n");
- code.append("public class Array {\n");
- code.append(" private Class type;\n");
- code.append(" public Class getClass() { return type; }\n");
- code.append("}\n");
- return code;
- }
- });
-
JProgram program = compileSnippet("void", "");
ControlFlowAnalyzer cfa = CodeSplitter.computeInitiallyLive(program);
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 c93e2ae..4979a83 100644
--- a/user/super/com/google/gwt/emul/java/lang/Object.java
+++ b/user/super/com/google/gwt/emul/java/lang/Object.java
@@ -58,6 +58,8 @@
* Magic; unlike the real JRE, we don't spec this method as final. The
* compiler will generate a polymorphic override on every other class which
* will return the correct class object.
+ *
+ * TODO(scottb): declare this final, but have the compiler fix it up.
*/
public Class<? extends Object> getClass() {
return Object.class;