Revision: 8548
Author: [email protected]
Date: Mon Aug 16 17:56:17 2010
Log: Removed use of a global table (typeIdArray) for testing castability between types. This information is now stored per class prototype as a castableMap.

Review at http://gwt-code-reviews.appspot.com/750801

http://code.google.com/p/google-web-toolkit/source/detail?r=8548

Added:
 /trunk/dev/core/src/com/google/gwt/core/ext/linker/CastableTypeMap.java
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCastableTypeMap.java
 /trunk/user/src/com/google/gwt/rpc/linker/CastableTypeDataImpl.java
 /trunk/user/src/com/google/gwt/rpc/server/CastableTypeData.java
Modified:
 /trunk/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java /trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java /trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Util.java
 /trunk/tools/api-checker/config/gwt20_21userApi.conf
 /trunk/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
 /trunk/user/src/com/google/gwt/rpc/server/ClientOracle.java
 /trunk/user/src/com/google/gwt/rpc/server/DelegatingClientOracle.java
 /trunk/user/src/com/google/gwt/rpc/server/HostedModeClientOracle.java
 /trunk/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java
 /trunk/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java
 /trunk/user/super/com/google/gwt/emul/java/lang/Object.java

=======================================
--- /dev/null
+++ /trunk/dev/core/src/com/google/gwt/core/ext/linker/CastableTypeMap.java Mon Aug 16 17:56:17 2010
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 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.core.ext.linker;
+
+import java.io.Serializable;
+
+/**
+ * An encapsulation of a JSON map containing a set of castable type ids.
+ */
+public interface CastableTypeMap extends Serializable {
+
+    /**
+     * Returns an eval-able JSON object.
+     */
+    String toJs();
+}
=======================================
--- /dev/null
+++ /trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCastableTypeMap.java Mon Aug 16 17:56:17 2010
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010 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.core.ext.linker.impl;
+
+import com.google.gwt.core.ext.linker.CastableTypeMap;
+
+/**
+ * The standard implementation of {...@link CastableTypeMap}.
+ */
+public class StandardCastableTypeMap implements CastableTypeMap {
+
+  final String jsonData;
+  public StandardCastableTypeMap(String jsonData) {
+    this.jsonData = jsonData;
+  }
+
+  public String toJs() {
+    return jsonData;
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/rpc/linker/CastableTypeDataImpl.java Mon Aug 16 17:56:17 2010
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 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.rpc.linker;
+
+import com.google.gwt.core.ext.linker.CastableTypeMap;
+import com.google.gwt.rpc.server.CastableTypeData;
+
+/**
+ * Implementation of a wrapped castableTypeMap.
+ */
+public class CastableTypeDataImpl implements CastableTypeData {
+
+  private final CastableTypeMap castableTypeMap;
+
+  public CastableTypeDataImpl(CastableTypeMap castableTypeMap) {
+    this.castableTypeMap = castableTypeMap;
+  }
+
+  public String toJs() {
+    return castableTypeMap.toJs();
+  }
+
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/rpc/server/CastableTypeData.java Mon Aug 16 17:56:17 2010
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 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.rpc.server;
+
+import java.io.Serializable;
+
+/**
+ * An encapsulation of a JSON object containing castable type information.
+ */
+public interface CastableTypeData extends Serializable {
+
+    /**
+     * Returns an eval-able JSON object.
+     */
+    String toJs();
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java Fri Jun 19 10:32:43 2009 +++ /trunk/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java Mon Aug 16 17:56:17 2010
@@ -79,6 +79,11 @@
       return o1.getJsniIdent().compareTo(o2.getJsniIdent());
     }
   }
+
+  /**
+   * Returns a JSON map of castableTypes
+   */
+  CastableTypeMap getCastableTypeMap();

   /**
* Returns the name of the type or enclosing type if the symbol is a method or
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java Fri Jun 19 10:32:43 2009 +++ /trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java Mon Aug 16 17:56:17 2010
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.core.ext.linker.impl;

+import com.google.gwt.core.ext.linker.CastableTypeMap;
 import com.google.gwt.core.ext.linker.SymbolData;

 import java.io.File;
@@ -31,15 +32,15 @@
 public class StandardSymbolData implements SymbolData {

public static StandardSymbolData forClass(String className, String uriString,
-      int lineNumber, int typeId) {
+      int lineNumber, int typeId, CastableTypeMap castableTypeMap) {
return new StandardSymbolData(className, null, null, uriString, lineNumber,
-        typeId);
+        typeId, castableTypeMap);
   }

   public static StandardSymbolData forMember(String className,
String memberName, String methodSig, String uriString, int lineNumber) { return new StandardSymbolData(className, memberName, methodSig, uriString,
-        lineNumber, 0);
+        lineNumber, 0, null);
   }

   public static String toUriString(String fileName) {
@@ -62,9 +63,11 @@
   private String sourceUri;
   private String symbolName;
   private int typeId;
+  private CastableTypeMap castableTypeMap;

   private StandardSymbolData(String className, String memberName,
-      String methodSig, String sourceUri, int sourceLine, int typeId) {
+      String methodSig, String sourceUri, int sourceLine, int typeId,
+      CastableTypeMap castableTypeMap) {
     assert className != null && className.length() > 0 : "className";
assert memberName != null || methodSig == null : "methodSig without memberName";
     assert sourceLine >= -1 : "sourceLine: " + sourceLine;
@@ -75,6 +78,11 @@
     this.sourceUri = sourceUri;
     this.sourceLine = sourceLine;
     this.typeId = typeId;
+    this.castableTypeMap = castableTypeMap;
+  }
+
+  public CastableTypeMap getCastableTypeMap() {
+    return castableTypeMap;
   }

   public String getClassName() {
@@ -152,6 +160,7 @@
     sourceUri = (String) in.readObject();
     symbolName = in.readUTF();
     typeId = in.readInt();
+    castableTypeMap = (CastableTypeMap) in.readObject();
   }

   /**
@@ -179,5 +188,6 @@
     out.writeObject(sourceUri);
     out.writeUTF(symbolName);
     out.writeInt(typeId);
+    out.writeObject(castableTypeMap);
   }
 }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java Wed Jul 28 11:12:18 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java Mon Aug 16 17:56:17 2010
@@ -318,7 +318,7 @@
    */
   private final SourceInfo intrinsic;

-  private List<JsonObject> jsonTypeTable;
+  private List<JsonObject> jsonCastableTypeMaps;

private Map<JReferenceType, JNonNullType> nonNullTypes = new IdentityHashMap<JReferenceType, JNonNullType>();

@@ -765,6 +765,20 @@
     }
     return allEntryMethods;
   }
+
+  public JsonObject getCastableTypeMap(int typeId) {
+    // ensure jsonCastableTypeMaps has been initialized
+    // it might not have been if the CastNormalizer has not been run
+    if (jsonCastableTypeMaps == null) {
+      jsonCastableTypeMaps = new ArrayList<JsonObject>();
+      // ensure the always-false (typeId == 0) entry is present
+      jsonCastableTypeMaps.add(new JsonObject(createSourceInfoSynthetic(
+          JProgram.class, "always-false typeinfo entry"),
+          getJavaScriptObject()));
+    }
+
+    return jsonCastableTypeMaps.get(typeId);
+  }

   public CorrelationFactory getCorrelator() {
     return correlator;
@@ -826,10 +840,6 @@
   public JClassType getJavaScriptObject() {
     return typeSpecialJavaScriptObject;
   }
-
-  public List<JsonObject> getJsonTypeTable() {
-    return jsonTypeTable;
-  }

   public JExpression getLiteralAbsentArrayDimension() {
     return JAbsentArrayDimension.INSTANCE;
@@ -1161,7 +1171,7 @@
     for (int i = 0, c = types.size(); i < c; ++i) {
       typeIdMap.put(types.get(i), Integer.valueOf(i));
     }
-    this.jsonTypeTable = jsonObjects;
+    this.jsonCastableTypeMaps = jsonObjects;
   }

   public boolean isJavaLangString(JType type) {
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java Wed Dec 9 09:10:40 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java Mon Aug 16 17:56:17 2010
@@ -35,6 +35,7 @@
 import com.google.gwt.dev.jjs.ast.JReferenceType;
 import com.google.gwt.dev.jjs.ast.JType;
 import com.google.gwt.dev.jjs.ast.js.JsonArray;
+import com.google.gwt.dev.jjs.ast.js.JsonObject;

 /**
  * Replace array accesses and instantiations with calls to the Array class.
@@ -123,11 +124,15 @@
       JMethodCall call = new JMethodCall(x.getSourceInfo(), null, initDim,
           arrayType);
       JLiteral classLit = x.getClassLiteral();
- JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(arrayType));
+
+      int typeId = program.getTypeId(arrayType);
+      JLiteral typeIdLit = program.getLiteralInt(typeId);
+      JsonObject castableTypeMap = program.getCastableTypeMap(typeId);
+
JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType));
       JExpression dim = x.dims.get(0);
       JType elementType = arrayType.getElementType();
-      call.addArgs(classLit, typeIdLit, queryIdLit, dim,
+      call.addArgs(classLit, typeIdLit, castableTypeMap, queryIdLit, dim,
           getSeedTypeLiteralFor(elementType));
       ctx.replaceMe(call);
     }
@@ -142,6 +147,8 @@
           program.getJavaScriptObject());
       JsonArray typeIdList = new JsonArray(sourceInfo,
           program.getJavaScriptObject());
+      JsonArray castableTypeMapList = new JsonArray(sourceInfo,
+          program.getJavaScriptObject());
       JsonArray queryIdList = new JsonArray(sourceInfo,
           program.getJavaScriptObject());
       JsonArray dimList = new JsonArray(sourceInfo,
@@ -154,8 +161,12 @@
         JLiteral classLit = x.getClassLiterals().get(i);
         classLitList.exprs.add(classLit);

- JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(curArrayType));
+        int typeId = program.getTypeId(curArrayType);
+        JLiteral typeIdLit = program.getLiteralInt(typeId);
         typeIdList.exprs.add(typeIdLit);
+
+        JsonObject castableTypeMap = program.getCastableTypeMap(typeId);
+        castableTypeMapList.exprs.add(castableTypeMap);

JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(curArrayType));
         queryIdList.exprs.add(queryIdLit);
@@ -163,8 +174,8 @@
         dimList.exprs.add(x.dims.get(i));
         cur = curArrayType.getElementType();
       }
-      call.addArgs(classLitList, typeIdList, queryIdList, dimList,
-          program.getLiteralInt(dims), getSeedTypeLiteralFor(cur));
+ call.addArgs(classLitList, typeIdList, castableTypeMapList, queryIdList, + dimList, program.getLiteralInt(dims), getSeedTypeLiteralFor(cur));
       ctx.replaceMe(call);
     }

@@ -176,14 +187,18 @@
       JMethodCall call = new JMethodCall(sourceInfo, null, initValues,
           arrayType);
       JLiteral classLit = x.getClassLiteral();
- JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(arrayType));
+
+      int typeId = program.getTypeId(arrayType);
+      JLiteral typeIdLit = program.getLiteralInt(typeId);
+      JsonObject castableTypeMap = program.getCastableTypeMap(typeId);
+
JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType));
       JsonArray initList = new JsonArray(sourceInfo,
           program.getJavaScriptObject());
       for (int i = 0; i < x.initializers.size(); ++i) {
         initList.exprs.add(x.initializers.get(i));
       }
-      call.addArgs(classLit, typeIdLit, queryIdLit, initList);
+ call.addArgs(classLit, typeIdLit, castableTypeMap, queryIdLit, initList);
       ctx.replaceMe(call);
     }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java Wed Aug 11 09:22:23 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java Mon Aug 16 17:56:17 2010
@@ -16,6 +16,8 @@
 package com.google.gwt.dev.jjs.impl;

 import com.google.gwt.core.ext.PropertyOracle;
+import com.google.gwt.core.ext.linker.CastableTypeMap;
+import com.google.gwt.core.ext.linker.impl.StandardCastableTypeMap;
 import com.google.gwt.core.ext.linker.impl.StandardSymbolData;
 import com.google.gwt.dev.jjs.HasSourceInfo;
 import com.google.gwt.dev.jjs.InternalCompilerException;
@@ -444,9 +446,13 @@

     private void recordSymbol(JReferenceType x, JsName jsName) {
       int typeId = program.getTypeId(x);
+
+      JsonObject castableTypeMapObj = program.getCastableTypeMap(typeId);
+ CastableTypeMap castableTypeMap = new StandardCastableTypeMap(castableTypeMapObj.toString());
+
StandardSymbolData symbolData = StandardSymbolData.forClass(x.getName(), x.getSourceInfo().getFileName(), x.getSourceInfo().getStartLine(),
-          typeId);
+          typeId, castableTypeMap);
       assert !symbolTable.containsKey(symbolData);
       symbolTable.put(symbolData, jsName);
     }
@@ -766,9 +772,6 @@
       if (x.getLiteralInitializer() != null) {
         // setup the constant value
         accept(x.getLiteralInitializer());
-      } else if (x == program.getIndexedField("Cast.typeIdArray")) {
-        // magic: setup the type id table
-        push(generateTypeTable());
       } else if (!x.hasInitializer()
           && x.getEnclosingType() != program.getTypeJavaLangObject()) {
         // setup a default value
@@ -1496,7 +1499,36 @@
return new JsBinaryOperation(lhs.getSourceInfo(), JsBinaryOperator.COMMA,
           lhs, rhs);
     }
-
+
+ private void generateCastableTypeIds(JClassType x, List<JsStatement> globalStmts) {
+      int typeId = program.getTypeId(x);
+      if (typeId >= 0) {
+ JField castableTypeMapField = program.getIndexedField("Object.castableTypeMap");
+        JsName castableTypeMapName = names.get(castableTypeMapField);
+        if (castableTypeMapName == null) {
+          // Was pruned; this compilation must have no dynamic casts.
+          return;
+        }
+
+        SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic(
+              GenerateJavaScriptAST.class, "Castable type map");
+
+        JsonObject jsonObject = program.getCastableTypeMap(typeId);
+        accept(jsonObject);
+        JsExpression objExpr = pop();
+
+        // Generate castableTypeMap for each type prototype
+        // _.castableTypeMap$ = {2:1, 4:1, 12:1};
+        JsNameRef fieldRef = castableTypeMapName.makeRef(sourceInfo);
+        fieldRef.setQualifier(globalTemp.makeRef(sourceInfo));
+        JsExpression asg = createAssignment(fieldRef, objExpr);
+
+        JsExprStmt asgStmt = asg.makeStmt();
+        globalStmts.add(asgStmt);
+        typeForStatMap.put(asgStmt, x);
+      }
+    }
+
private void generateClassLiteral(JDeclarationStatement decl, JsVars vars) {
       JField field = (JField) decl.getVariableRef().getTarget();
       JsName jsName = names.get(field);
@@ -1533,6 +1565,7 @@
       }

       generateTypeId(x, globalStmts);
+      generateCastableTypeIds(x, globalStmts);
     }

     private void generateGwtOnLoad(List<JsFunction> entryFuncs,
@@ -1793,19 +1826,7 @@
       globalStmts.add(stmt);
       typeForStatMap.put(stmt, program.getTypeJavaLangObject());
     }
-
-    private JsExpression generateTypeTable() {
-      JsArrayLiteral arrayLit = new JsArrayLiteral(
-          jsProgram.createSourceInfoSynthetic(GenerateJavaScriptAST.class,
-              "Type table"));
-      for (int i = 0; i < program.getJsonTypeTable().size(); ++i) {
-        JsonObject jsonObject = program.getJsonTypeTable().get(i);
-        accept(jsonObject);
-        arrayLit.getExpressions().add((JsExpression) pop());
-      }
-      return arrayLit;
-    }
-
+
private void generateVTables(JClassType x, List<JsStatement> globalStmts) {
       for (JMethod method : x.getMethods()) {
         SourceInfo sourceInfo = method.getSourceInfo().makeChild(
@@ -2137,6 +2158,7 @@
     specialObfuscatedIdents.put("expando", "eX");
     specialObfuscatedIdents.put("typeId", "tI");
     specialObfuscatedIdents.put("typeMarker", "tM");
+    specialObfuscatedIdents.put("castableTypeMap", "cM");

     // String polymorphic
     specialObfuscatedIdents.put("charAt", "cA");
=======================================
--- /trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java Wed Jul 21 05:01:19 2010 +++ /trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java Mon Aug 16 17:56:17 2010
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.lang;

+import com.google.gwt.core.client.JavaScriptObject;
+
 /**
* This is a magic class the compiler uses as a base class for injected array
  * classes.
@@ -95,7 +97,8 @@
public static <T> T[] cloneSubrange(T[] array, int fromIndex, int toIndex) {
     Array a = asArrayType(array);
     Array result = arraySlice(a, fromIndex, toIndex);
-    initValues(a.getClass(), Util.getTypeId(a), a.queryId, result);
+    initValues(a.getClass(), Util.getTypeId(a),
+        Util.getCastableTypeMap(a), a.queryId, result);
     // implicit type arg not inferred (as of JDK 1.5.0_07)
     return Array.<T> asArray(result);
   }
@@ -114,7 +117,8 @@
   public static <T> T[] createFrom(T[] array, int length) {
     Array a = asArrayType(array);
     Array result = createFromSeed(NULL_SEED_TYPE, length);
-    initValues(a.getClass(), Util.getTypeId(a), a.queryId, result);
+    initValues(a.getClass(), Util.getTypeId(a),
+        Util.getCastableTypeMap(a), a.queryId, result);
     // implicit type arg not inferred (as of JDK 1.5.0_07)
     return Array.<T> asArray(result);
   }
@@ -125,15 +129,17 @@
    *
    * @param arrayClass the class of the array
    * @param typeId the typeId of the array
+ * @param castableTypeMap the map of types to which this array can be casted,
+   *          in the form of a JSON map object
    * @param queryId the queryId of the array
    * @param length the length of the array
* @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,
-      int length, int seedType) {
+  public static Array initDim(Class<?> arrayClass, int typeId,
+ JavaScriptObject castableTypeMap, int queryId, int length, int seedType) {
     Array result = createFromSeed(seedType, length);
-    initValues(arrayClass, typeId, queryId, result);
+    initValues(arrayClass, typeId, castableTypeMap, queryId, result);
     return result;
   }

@@ -142,16 +148,19 @@
    * array, [a, b, c].
    *
    * @param arrayClasses the class of each dimension of the array
- * @param typeIdExprs the typeId at each dimension, from highest to lowest - * @param queryIdExprs the queryId at each dimension, from highest to lowest
-   * @param dimExprs the length at each dimension, from highest to lower
+ * @param typeIdExprs the typeId of each dimension, from highest to lowest + * @param castableTypeMapExprs the JSON castableTypeMap of each dimension,
+   *          from highest to lowest
+ * @param queryIdExprs the queryId of each dimension, from highest to lowest
+   * @param dimExprs the length of each dimension, from highest to lower
* @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,
-      int[] queryIdExprs, int[] dimExprs, int count, int seedType) {
-    return initDims(arrayClasses, typeIdExprs, queryIdExprs, dimExprs, 0,
-        count, seedType);
+ JavaScriptObject[] castableTypeMapExprs, int[] queryIdExprs, int[] dimExprs,
+      int count, int seedType) {
+ return initDims(arrayClasses, typeIdExprs, castableTypeMapExprs, queryIdExprs,
+        dimExprs, 0, count, seedType);
   }

   /**
@@ -160,15 +169,18 @@
    *
    * @param arrayClass the class of the array
    * @param typeId the typeId of the array
+ * @param castableTypeMap the map of types to which this array can be casted,
+   *          in the form of a JSON map object
    * @param queryId the queryId of the array
    * @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,
-      Array array) {
+  public static Array initValues(Class<?> arrayClass, int typeId,
+      JavaScriptObject castableTypeMap, int queryId, Array array) {
     ExpandoWrapper.wrapArray(array);
     array.arrayClass = arrayClass;
     Util.setTypeId(array, typeId);
+    Util.setCastableTypeMap(array, castableTypeMap);
     array.queryId = queryId;
     return array;
   }
@@ -178,7 +190,7 @@
    */
   public static Object setCheck(Array array, int index, Object value) {
     if (value != null) {
- if (array.queryId > 0 && !Cast.canCastUnsafe(Util.getTypeId(value), array.queryId)) {
+      if (array.queryId > 0 && !Cast.canCastUnsafe(value, array.queryId)) {
         throw new ArrayStoreException();
       }
       if (array.queryId < 0 && Cast.isJavaObject(value)) {
@@ -236,19 +248,22 @@
   }-*/;

   private static Array initDims(Class<?> arrayClasses[], int[] typeIdExprs,
- int[] queryIdExprs, int[] dimExprs, int index, int count, int seedType) { + JavaScriptObject[] castableTypeMapExprs, int[] queryIdExprs, int[] dimExprs,
+      int index, int count, int seedType) {
+
     int length = dimExprs[index];
     boolean isLastDim = (index == (count - 1));

Array result = createFromSeed(isLastDim ? seedType : NULL_SEED_TYPE, length); - initValues(arrayClasses[index], typeIdExprs[index], queryIdExprs[index], result);
+    initValues(arrayClasses[index], typeIdExprs[index],
+        castableTypeMapExprs[index], queryIdExprs[index], result);

     if (!isLastDim) {
       // Recurse to next dimension.
       ++index;
       for (int i = 0; i < length; ++i) {
- set(result, i, initDims(arrayClasses, typeIdExprs, queryIdExprs, dimExprs,
-            index, count, seedType));
+ set(result, i, initDims(arrayClasses, typeIdExprs, castableTypeMapExprs,
+            queryIdExprs, dimExprs, index, count, seedType));
       }
     }
     return result;
=======================================
--- /trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java Tue Feb 10 16:28:41 2009 +++ /trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java Mon Aug 16 17:56:17 2010
@@ -25,19 +25,18 @@
  */
 final class Cast {

-  // magic magic magic
-  protected static Object typeIdArray;
-
-  static native boolean canCast(int srcId, int dstId) /*-{
-    return srcId && [email protected]::typeIdArray[srcId][dstId];
+  static native boolean canCast(Object src, int dstId) /*-{
+    return [email protected]::typeId &&
+          [email protected]::castableTypeMap[dstId];
   }-*/;

   /**
    * Danger: value not coerced to boolean; use the result only in a boolean
    * context.
    */
-  static native boolean canCastUnsafe(int srcId, int dstId) /*-{
-    return srcId && @com.google.gwt.lang.Cast::typeIdArray[srcId][dstId];
+  static native boolean canCastUnsafe(Object src, int dstId) /*-{
+    return [email protected]::typeId &&
+          [email protected]::castableTypeMap[dstId];
   }-*/;

   static native String charToString(char x) /*-{
@@ -45,7 +44,7 @@
   }-*/;

   static Object dynamicCast(Object src, int dstId) {
-    if (src != null && !canCastUnsafe(Util.getTypeId(src), dstId)) {
+    if (src != null && !canCastUnsafe(src, dstId)) {
       throw new ClassCastException();
     }
     return src;
@@ -56,7 +55,7 @@
    */
   static Object dynamicCastAllowJso(Object src, int dstId) {
     if (src != null && !isJavaScriptObject(src) &&
-        !canCastUnsafe(Util.getTypeId(src), dstId)) {
+        !canCastUnsafe(src, dstId)) {
       throw new ClassCastException();
     }
     return src;
@@ -73,7 +72,7 @@
   }

   static boolean instanceOf(Object src, int dstId) {
-    return (src != null) && canCast(Util.getTypeId(src), dstId);
+    return (src != null) && canCast(src, dstId);
   }

   /**
@@ -89,7 +88,7 @@
    */
   static boolean instanceOfOrJso(Object src, int dstId) {
     return (src != null) &&
-        (isJavaScriptObject(src) || canCast(Util.getTypeId(src), dstId));
+        (isJavaScriptObject(src) || canCast(src, dstId));
   }

   static boolean isJavaObject(Object src) {
=======================================
--- /trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Util.java Thu Apr 22 13:36:50 2010 +++ /trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Util.java Mon Aug 16 17:56:17 2010
@@ -22,6 +22,10 @@
  * fields.
  */
 final class Util {
+
+  static native JavaScriptObject getCastableTypeMap(Object o) /*-{
+    return [email protected]::castableTypeMap;
+  }-*/;

   static native int getTypeId(Object o) /*-{
     return [email protected]::typeId;
@@ -31,6 +35,10 @@
     return [email protected]::typeMarker;
   }-*/;

+ static native void setCastableTypeMap(Object o, JavaScriptObject castableTypeMap) /*-{
+    [email protected]::castableTypeMap = castableTypeMap;
+  }-*/;
+
   static native void setTypeId(Object o, int typeId) /*-{
     [email protected]::typeId = typeId;
   }-*/;
=======================================
--- /trunk/tools/api-checker/config/gwt20_21userApi.conf Thu Aug 5 13:48:12 2010 +++ /trunk/tools/api-checker/config/gwt20_21userApi.conf Mon Aug 16 17:56:17 2010
@@ -142,6 +142,11 @@
 # Array.length is now intrinsic to the compiler
 com.google.gwt.lang.Array::length MISSING

+# Array initialization modified to include castableTypeMap arg
+com.google.gwt.lang.Array::initDim(Ljava/lang/Class;IIII) MISSING
+com.google.gwt.lang.Array::initDims([Ljava/lang/Class;[I[I[III) MISSING
+com.google.gwt.lang.Array::initValues(Ljava/lang/Class;IILcom/google/gwt/lang/Array;) MISSING
+
 # Add DateTimeFormatInfo, PredefinedFormat overrides
com.google.gwt.i18n.client.DateTimeFormat::DateTimeFormat(Ljava/lang/String;Lcom/google/gwt/i18n/client/constants/DateTimeConstants;) OVERLOADED_METHOD_CALL com.google.gwt.i18n.client.DateTimeFormat::getFormat(Ljava/lang/String;) OVERLOADED_METHOD_CALL
=======================================
--- /trunk/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java Wed Mar 3 09:01:30 2010 +++ /trunk/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java Mon Aug 16 17:56:17 2010
@@ -71,7 +71,8 @@
         for (SymbolData symbolData : result.getSymbolMap()) {
builder.add(symbolData.getSymbolName(), symbolData.getJsniIdent(),
               symbolData.getClassName(), symbolData.getMemberName(),
-              symbolData.getTypeId());
+              symbolData.getTypeId(),
+              new CastableTypeDataImpl(symbolData.getCastableTypeMap()));
         }

         ByteArrayOutputStream out = new ByteArrayOutputStream();
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/ClientOracle.java Mon Dec 7 15:48:32 2009 +++ /trunk/user/src/com/google/gwt/rpc/server/ClientOracle.java Mon Aug 16 17:56:17 2010
@@ -50,6 +50,11 @@
    */
   public abstract String createUnusedIdent(String ident);

+  /**
+   * Returns the Json castableType data for a given type.
+   */
+  public abstract CastableTypeData getCastableTypeData(Class<?> clazz);
+
   /**
* Given a base type and the unobfuscated field name, find the obfuscated name * for the field in the client. This will search superclasses as well for the
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/DelegatingClientOracle.java Wed Oct 28 09:10:53 2009 +++ /trunk/user/src/com/google/gwt/rpc/server/DelegatingClientOracle.java Mon Aug 16 17:56:17 2010
@@ -43,6 +43,11 @@
     return delegate.createUnusedIdent(ident);
   }

+  @Override
+  public CastableTypeData getCastableTypeData(Class<?> clazz) {
+    return delegate.getCastableTypeData(clazz);
+  }
+
   @Override
   public String getFieldId(Class<?> clazz, String fieldName) {
     return delegate.getFieldId(clazz, fieldName);
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/HostedModeClientOracle.java Wed Oct 28 09:10:53 2009 +++ /trunk/user/src/com/google/gwt/rpc/server/HostedModeClientOracle.java Mon Aug 16 17:56:17 2010
@@ -57,6 +57,11 @@
   public String createUnusedIdent(String ident) {
     return unimplemented();
   }
+
+  @Override
+  public CastableTypeData getCastableTypeData(Class<?> clazz) {
+    return unimplemented();
+  }

   /**
    * Unimplemented.
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java Wed Oct 28 09:10:53 2009 +++ /trunk/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java Mon Aug 16 17:56:17 2010
@@ -52,10 +52,11 @@
     private WebModeClientOracle oracle = new WebModeClientOracle();

     public void add(String jsIdent, String jsniIdent, String className,
-        String memberName, int typeId) {
+        String memberName, int typeId, CastableTypeData castableTypeData) {
       oracle.idents.add(jsIdent);
       ClassData data = oracle.getClassData(className);
       data.typeId = typeId;
+      data.castableTypeData = castableTypeData;
       if (jsniIdent == null || jsniIdent.length() == 0) {
         data.typeName = className;
         data.seedName = jsIdent;
@@ -108,15 +109,16 @@
   }

   private static class ClassData implements Serializable {
-    private static final long serialVersionUID = 3L;
-
+    private static final long serialVersionUID = 4L;
+
+    public CastableTypeData castableTypeData;
public final Map<String, String> fieldIdentsToNames = new HashMap<String, String>(); public final Map<String, String> fieldNamesToIdents = new HashMap<String, String>(); public final Map<String, String> methodJsniNamesToIdents = new HashMap<String, String>();
     public String seedName;
     public List<String> serializableFields = Collections.emptyList();
-    public String typeName;
     public int typeId;
+    public String typeName;
   }

   /**
@@ -230,6 +232,18 @@
     }
     return ident;
   }
+
+  @Override
+  public CastableTypeData getCastableTypeData(Class<?> clazz) {
+    while (clazz != null) {
+ CastableTypeData toReturn = getCastableTypeData(canonicalName(clazz));
+      if (toReturn != null) {
+        return toReturn;
+      }
+      clazz = clazz.getSuperclass();
+    }
+    return null;
+  }

   @Override
   public String getFieldId(Class<?> clazz, String fieldName) {
@@ -395,6 +409,11 @@
       return clazz.getName();
     }
   }
+
+  private CastableTypeData getCastableTypeData(String className) {
+    ClassData data = getClassData(className);
+    return data.castableTypeData;
+  }

   private ClassData getClassData(String className) {
     ClassData toReturn = classData.get(className);
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java Thu Jul 22 12:08:40 2010 +++ /trunk/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java Mon Aug 16 17:56:17 2010
@@ -533,7 +533,8 @@

       String initValuesId = clientOracle.getMethodId(
           "com.google.gwt.lang.Array", "initValues", "Ljava/lang/Class;", "I",
-          "I", "Lcom/google/gwt/lang/Array;");
+          "Lcom/google/gwt/core/client/JavaScriptObject;", "I",
+          "Lcom/google/gwt/lang/Array;");
       assert initValuesId != null : "Could not find initValues";

       String classLitId = clientOracle.getFieldId(
@@ -546,12 +547,16 @@
       constructorFunctions.put(targetClass, functionName);

       /*
- * Set the typeIds and queryIds to exact values, or fall back to acting
-       * like a plain Object[] array.
+       * Set the typeIds, castableTypeData, and queryIds to exact values,
+       * or fall back to acting like a plain Object[] array.
        */
+      CastableTypeData castableTypeData;
       int typeId = clientOracle.getTypeId(targetClass);
-      if (typeId == 0) {
+      if (typeId != 0) {
+        castableTypeData = clientOracle.getCastableTypeData(targetClass);
+      } else {
         typeId = clientOracle.getTypeId(Object[].class);
+ castableTypeData = clientOracle.getCastableTypeData(Object[].class);
       }

       int queryId = clientOracle.getTypeId(x.getComponentType());
@@ -575,6 +580,8 @@
       comma();
       push(String.valueOf(typeId));
       comma();
+      push(castableTypeData.toJs());
+      comma();
       push(String.valueOf(queryId));
       comma();
       push(ident);
=======================================
--- /trunk/user/super/com/google/gwt/emul/java/lang/Object.java Thu Jun 24 15:39:22 2010 +++ /trunk/user/super/com/google/gwt/emul/java/lang/Object.java Mon Aug 16 17:56:17 2010
@@ -41,6 +41,14 @@
    */
   @SuppressWarnings("unused")
   private transient int typeId;
+
+  /**
+   * A JavaScript Json map for looking up castability between types.
+   *
+   * @skip
+   */
+  @SuppressWarnings("unused")
+  private transient JavaScriptObject castableTypeMap;

   /**
    * magic magic magic.
@@ -48,7 +56,7 @@
    * @skip
    */
   @SuppressWarnings("unused")
-  private transient Object typeMarker;
+  private transient JavaScriptObject typeMarker;

   public boolean equals(Object other) {
     return this == other;

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to