Revision: 10336
Author:   jbrosenb...@google.com
Date:     Tue Jun 14 12:19:31 2011
Log: Updated generator result caching to use lastModifiedTime from CompilationUnit.lastModified().
Removed GeneratorContextExt.getSourceLastModifiedTime().
Removed JRealClassType.getTypeStrongHash().
Added JRealClassType.getLastModifiedTime()

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

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

Modified:
 /trunk/dev/core/src/com/google/gwt/core/ext/GeneratorContextExt.java
 /trunk/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java
 /trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
 /trunk/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
 /trunk/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
/trunk/dev/core/src/com/google/gwt/dev/javac/rebind/CachedPropertyInformation.java
 /trunk/dev/core/src/com/google/gwt/dev/javac/typemodel/JRealClassType.java
/trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java
 /trunk/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
/trunk/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
 /trunk/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
/trunk/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java

=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/GeneratorContextExt.java Fri Feb 4 09:24:25 2011 +++ /trunk/dev/core/src/com/google/gwt/core/ext/GeneratorContextExt.java Tue Jun 14 12:19:31 2011
@@ -15,7 +15,6 @@
  */
 package com.google.gwt.core.ext;

-import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.dev.javac.rebind.CachedRebindResult;

 /**
@@ -38,15 +37,6 @@
    */
   CachedRebindResult getCachedGeneratorResult();

-  /**
-   * Get source last modified time.
-   * <p>
-   * TODO(jbrosenberg): Implement in terms of a getVersion method yet to be
-   * added to TypeOracle, instead of looking for age of a java source file.
-   * This will soon be removed.
-   */
-  long getSourceLastModifiedTime(JClassType sourceType);
-
   /**
    * Check whether generator result caching is currently enabled.
    */
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java Wed Jun 1 13:28:28 2011 +++ /trunk/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java Tue Jun 14 12:19:31 2011
@@ -17,7 +17,6 @@

 import com.google.gwt.core.ext.linker.Artifact;
 import com.google.gwt.core.ext.linker.GeneratedResource;
-import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.dev.javac.rebind.CachedRebindResult;
 import com.google.gwt.dev.resource.ResourceOracle;
@@ -79,10 +78,6 @@
   public ResourceOracle getResourcesOracle() {
     return baseContext.getResourcesOracle();
   }
-
-  public long getSourceLastModifiedTime(JClassType sourceType) {
-    return 0L;
-  }

   public TypeOracle getTypeOracle() {
     return baseContext.getTypeOracle();
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java Wed Feb 9 07:49:06 2011 +++ /trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java Tue Jun 14 12:19:31 2011
@@ -23,8 +23,7 @@
   /**
* EXPERIMENTAL and subject to change. Do not use this in production code.
    *
- * Generate a hash to be used as a signature for comparing versions of the
-   * structure of a type.
+   * Retrieve last modified time for this type.
    */
-  String getTypeStrongHash();
-}
+  long getLastModifiedTime();
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java Wed Jun 1 13:28:28 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java Tue Jun 14 12:19:31 2011
@@ -27,7 +27,6 @@
 import com.google.gwt.core.ext.linker.ArtifactSet;
 import com.google.gwt.core.ext.linker.GeneratedResource;
 import com.google.gwt.core.ext.linker.impl.StandardGeneratedResource;
-import com.google.gwt.core.ext.typeinfo.JArrayType;
 import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.dev.cfg.ModuleDef;
@@ -35,7 +34,6 @@
 import com.google.gwt.dev.javac.rebind.RebindResult;
 import com.google.gwt.dev.javac.rebind.RebindRuleResolver;
 import com.google.gwt.dev.javac.rebind.RebindStatus;
-import com.google.gwt.dev.resource.Resource;
 import com.google.gwt.dev.resource.ResourceOracle;
 import com.google.gwt.dev.util.DiskCache;
 import com.google.gwt.dev.util.Util;
@@ -540,39 +538,6 @@
   public ResourceOracle getResourcesOracle() {
     return module.getResourcesOracle();
   }
-
-  /**
- * EXPERIMENTAL and subject to change. Do not use this in production code.
-   *
- * Temporary solution to get last modified time for a sourceType. Finds the - * the source file, if possible. Note, this won't work for sources contained
-   * in jar files, or for recently generated source files.
-   *
- * TODO(jbrosenberg): Replace this method by using a getVersion() method from
-   * TypeOracle (still under development).
-   */
-  public long getSourceLastModifiedTime(JClassType sourceType) {
-
-    while (sourceType instanceof JArrayType) {
- sourceType = (JClassType) ((JArrayType) sourceType).getComponentType();
-    }
-
-    JClassType enclosingType;
-    while ((enclosingType = sourceType.getEnclosingType()) != null) {
-      sourceType = enclosingType;
-    }
-
-    String sourceName = sourceType.getQualifiedSourceName();
-    String sourcePath = sourceName.replace('.', '/') + ".java";
-
-    Resource sourceResource = module.findSourceFile(sourcePath);
-
-    if (sourceResource == null) {
-      return 0L;
-    }
-
-    return sourceResource.getLastModified();
-  }

   public final TypeOracle getTypeOracle() {
     return compilationState.getTypeOracle();
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java Wed Apr 27 09:34:06 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java Tue Jun 14 12:19:31 2011
@@ -539,11 +539,11 @@
       // Always add implicit modifiers on interfaces.
       resultType.addModifierBits(Shared.MOD_STATIC | Shared.MOD_ABSTRACT);
     }
-
+
     /*
-     * Add a reference to the byteCode
+     * Add lastModified time from compilation unit
      */
-    resultType.addByteCode(typeData.byteCode);
+    resultType.addLastModifiedTime(typeData.lastModifiedTime);

     return resultType;
   }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/rebind/CachedPropertyInformation.java Wed Feb 9 07:49:06 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/javac/rebind/CachedPropertyInformation.java Tue Jun 14 12:19:31 2011
@@ -85,10 +85,12 @@
           SelectionProperty currProp =
             oracle.getSelectionProperty(logger, selProp.getName());
if (!currProp.getCurrentValue().equals(selProp.getCurrentValue())) { + logger.log(TreeLogger.TRACE, "Found changed property: " + selProp.getName());
             return false;
           }
         }
       } catch (BadPropertyValueException e) {
+        logger.log(TreeLogger.TRACE, "Found problem checking property", e);
         return false;
       }
     }
@@ -99,10 +101,14 @@
           ConfigurationProperty currProp =
             oracle.getConfigurationProperty(configProp.getName());
           if (!currProp.equals(configProp)) {
+            logger.log(TreeLogger.TRACE,
+ "Found changed configuration property: " + configProp.getName());
             return false;
           }
         }
       } catch (BadPropertyValueException e) {
+        logger.log(TreeLogger.TRACE,
+            "Found problem checking configuration property", e);
         return false;
       }
     }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/typemodel/JRealClassType.java Wed Feb 9 13:08:24 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/javac/typemodel/JRealClassType.java Tue Jun 14 12:19:31 2011
@@ -19,7 +19,6 @@
 import com.google.gwt.core.ext.typeinfo.JType;
 import com.google.gwt.core.ext.typeinfo.NotFoundException;
 import com.google.gwt.dev.util.StringInterner;
-import com.google.gwt.dev.util.Util;
 import com.google.gwt.dev.util.collect.IdentitySets;
 import com.google.gwt.dev.util.collect.Lists;

@@ -52,8 +51,6 @@
   private String lazyQualifiedBinaryName;

   private String lazyQualifiedName;
-
-  private String lazyTypeStrongHash;

   private final Members members = new Members(this);

@@ -66,8 +63,8 @@
   private final TypeOracle oracle;

   private JClassType superclass;
-
-  private byte[] byteCode;
+
+  private long lastModifiedTime;

   /**
    * Create a class type that reflects an actual type.
@@ -80,8 +77,8 @@
    * @param name
    * @param isInterface
    */
-  JRealClassType(TypeOracle oracle, JPackage declaringPackage,
-      String enclosingTypeName, String name, boolean isInterface) {
+ JRealClassType(TypeOracle oracle, JPackage declaringPackage, String enclosingTypeName,
+      String name, boolean isInterface) {
     this.oracle = oracle;
     this.declaringPackage = declaringPackage;
     this.name = StringInterner.get().intern(name);
@@ -103,9 +100,9 @@
     }
     oracle.addNewType(this);
   }
-
-  public void addByteCode(byte[] byteCode) {
-    this.byteCode = byteCode;
+
+  public void addLastModifiedTime(long lastModifiedTime) {
+    this.lastModifiedTime = lastModifiedTime;
   }

   @Override
@@ -144,8 +141,7 @@
   }

   @Override
-  public JConstructor getConstructor(JType[] paramTypes)
-      throws NotFoundException {
+ public JConstructor getConstructor(JType[] paramTypes) throws NotFoundException {
     return members.getConstructor(paramTypes);
   }

@@ -200,8 +196,12 @@
   }

   @Override
-  public JMethod getMethod(String name, JType[] paramTypes)
-      throws NotFoundException {
+  public long getLastModifiedTime() {
+    return lastModifiedTime;
+  }
+
+  @Override
+ public JMethod getMethod(String name, JType[] paramTypes) throws NotFoundException {
     return members.getMethod(name, paramTypes);
   }

@@ -286,27 +286,6 @@
   public JClassType getSuperclass() {
     return superclass;
   }
-
-  /**
- * EXPERIMENTAL and subject to change. Do not use this in production code.
-   *
- * Generate a hash to be used as a signature for comparing versions of the
-   * structure of a type.
-   *
- * TODO(jbrosenberg): Note, this implementation is based on the entire byte - * code for a class, which is probably overkill, since we only need a hash - * based on the type's structure (but not all of its code). Need to come up - * with an efficient way to compute a hash of a type's structure. For now, - * using the raw bytes directly is quick relative to making multiple api calls
-   * into type oracle to determine the type's structure.
-   */
-  public String getTypeStrongHash() {
-    if (lazyTypeStrongHash != null) {
-      return lazyTypeStrongHash;
-    }
-    lazyTypeStrongHash = Util.computeStrongName(byteCode);
-    return lazyTypeStrongHash;
-  }

   @Override
   public boolean isAbstract() {
@@ -528,8 +507,7 @@
     }
   }

-  void addAnnotations(
-      Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
+ void addAnnotations(Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
     annotations.addAnnotations(declaredAnnotations);
   }

=======================================
--- /trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java Thu Mar 3 11:31:39 2011 +++ /trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java Tue Jun 14 12:19:31 2011
@@ -122,9 +122,9 @@

   private static final String FILE_PROTOCOL = "file";
   private static final String JAR_PROTOCOL = "jar";
-  private static final String CACHED_PROPERTY_INFORMATION = "cpi";
-  private static final String CACHED_RESOURCE_INFORMATION = "cri";
-  private static final String CACHED_TYPE_INFORMATION = "cti";
+ private static final String CACHED_PROPERTY_INFORMATION = "cached-property-info"; + private static final String CACHED_RESOURCE_INFORMATION = "cached-resource-info";
+  private static final String CACHED_TYPE_INFORMATION = "cached-type-info";
   private static final String INSTANCE_NAME = "_instance0";

   /**
@@ -302,22 +302,18 @@
       return resolvedResources;
     }

-    public Map<String, String> getTypeSignatures() {
+    public Map<String, Long> getTypeLastModifiedTimes() {
       if (!canBeCacheable) {
         return null;
       }
-      Map<String, String> typeSignatures = new HashMap<String, String>();
+ Map<String, Long> typeLastModifiedTimeMap = new HashMap<String, Long>();
       for (JClassType type : types) {
         String typeName = type.getQualifiedSourceName();
-        if (type instanceof JRealClassType) {
-          JRealClassType sourceRealType = (JRealClassType) type;
-          String typeSignature = sourceRealType.getTypeStrongHash();
-          typeSignatures.put(typeName, typeSignature);
-        } else {
-          typeSignatures.put(typeName, "");
-        }
-      }
-      return typeSignatures;
+        assert type instanceof JRealClassType;
+        JRealClassType sourceRealType = (JRealClassType) type;
+ typeLastModifiedTimeMap.put(typeName, sourceRealType.getLastModifiedTime());
+      }
+      return typeLastModifiedTimeMap;
     }

     /*
@@ -337,9 +333,26 @@
* Do a series of checks to see if we can use a previously cached result,
      * and if so, we can skip further execution and return immediately.
      */
+    boolean useCache = false;
     if (checkPropertyCacheability(logger, generatorContext)
-        && checkSourceTypeCacheability(generatorContext)
+        && checkSourceTypeCacheability(logger, generatorContext)
&& checkDependentResourceCacheability(logger, generatorContext, null)) {
+      useCache = true;
+    }
+
+    if (logger.isLoggable(TreeLogger.TRACE)) {
+      if (generatorContext.isGeneratorResultCachingEnabled()) {
+        String msg;
+        if (useCache) {
+          msg = "Reusing cached client bundle for " + typeName;
+        } else {
+          msg = "Can't use cached client bundle for " + typeName;
+        }
+        logger.log(TreeLogger.TRACE, msg);
+      }
+    }
+
+    if (useCache) {
       return new RebindResult(RebindStatus.USE_ALL_CACHED, typeName);
     }

@@ -470,8 +483,8 @@
           requirements.getPermutationAxes(),
           requirements.getConfigurationPropertyNames());

-      // remember the type signatures for required source types
-      Map<String, String> cti = requirements.getTypeSignatures();
+      // remember the last modified times for required source types
+      Map<String, Long> cti = requirements.getTypeLastModifiedTimes();

       // remember the required resources
       Map<String, URL> cri = requirements.getResolvedResources();
@@ -543,23 +556,26 @@
   }

   /**
- * Check that the map of cached type signatures matches those from the current
+   * Check that the cached last modified times match those from the current
    * typeOracle.
    */
-  private boolean checkCachedTypeSignatures(
- GeneratorContextExt generatorContext, Map<String, String> typeSignatures) {
+  private boolean checkCachedTypeLastModifiedTimes(TreeLogger logger,
+ GeneratorContextExt generatorContext, Map<String, Long> typeLastModifiedTimes) {

     TypeOracle oracle = generatorContext.getTypeOracle();

-    for (String sourceTypeName : typeSignatures.keySet()) {
+    for (String sourceTypeName : typeLastModifiedTimes.keySet()) {
       JClassType sourceType = oracle.findType(sourceTypeName);
-      if (sourceType == null || !(sourceType instanceof JRealClassType)) {
+      if (sourceType == null) {
+        logger.log(TreeLogger.TRACE,
+ "Found previously dependent type that's no longer present: " + sourceTypeName);
         return false;
       }
+      assert sourceType instanceof JRealClassType;
       JRealClassType sourceRealType = (JRealClassType) sourceType;

-      String signature = sourceRealType.getTypeStrongHash();
-      if (!signature.equals(typeSignatures.get(sourceTypeName))) {
+ if (sourceRealType.getLastModifiedTime() != typeLastModifiedTimes.get(sourceTypeName)) { + logger.log(TreeLogger.TRACE, "Found dependent type that has changed: " + sourceTypeName);
         return false;
       }
     }
@@ -597,10 +613,13 @@
           resourceContext, resourceName);
       if (currentUrl == null || resolvedUrl == null
| | !resolvedUrl.toExternalForm().equals(currentUrl.toExternalForm())) {
+        logger.log(TreeLogger.TRACE,
+ "Found dependent resource that has moved or no longer exists: " + resourceName);
         return false;
       }

if (!checkDependentResourceUpToDate(lastTimeGenerated, resolvedUrl)) { + logger.log(TreeLogger.TRACE, "Found dependent resource that has changed: " + resourceName);
         return false;
       }
     }
@@ -714,7 +733,7 @@
   /*
    * Check source types for cacheability
    */
- private boolean checkSourceTypeCacheability(GeneratorContextExt genContext) { + private boolean checkSourceTypeCacheability(TreeLogger logger, GeneratorContextExt genContext) {

CachedRebindResult lastRebindResult = genContext.getCachedGeneratorResult();

@@ -729,11 +748,11 @@
      * since the previous cached result was generated.
      */
     @SuppressWarnings("unchecked")
-    Map<String, String> cachedTypeSignatures = (Map<String, String>)
+    Map<String, Long> cachedTypeLastModifiedTimes = (Map<String, Long>)
       lastRebindResult.getClientData(CACHED_TYPE_INFORMATION);

-    return cachedTypeSignatures != null
-      && checkCachedTypeSignatures(genContext, cachedTypeSignatures);
+    return cachedTypeLastModifiedTimes != null
+ && checkCachedTypeLastModifiedTimes(logger, genContext, cachedTypeLastModifiedTimes);
   }

   /**
=======================================
--- /trunk/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java Wed Jun 8 11:10:51 2011 +++ /trunk/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java Tue Jun 14 12:19:31 2011
@@ -36,6 +36,7 @@
 import com.google.gwt.core.ext.typeinfo.NotFoundException;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.dev.generator.NameFactory;
+import com.google.gwt.dev.javac.rebind.CachedClientDataMap;
 import com.google.gwt.dev.util.Util;
 import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
 import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
@@ -204,6 +205,8 @@

   private boolean elideTypeNames;

+  private Map<String, Long> cachedTypeLastModifiedTimes = null;
+
   /**
    * The possibly obfuscated type signatures used to represent a type.
    */
@@ -343,6 +346,12 @@

     return getProxyQualifiedName();
   }
+
+  public void updateResultCacheData(CachedClientDataMap clientData) {
+    if (cachedTypeLastModifiedTimes != null) {
+ clientData.put(TypeSerializerCreator.CACHED_TYPE_INFO_KEY, cachedTypeLastModifiedTimes);
+    }
+  }

   protected void addRoots(TreeLogger logger, TypeOracle typeOracle,
       SerializableTypeOracleBuilder typesSentFromBrowserBuilder,
@@ -645,6 +654,8 @@

     typeStrings = new HashMap<JType, String>(tsc.getTypeStrings());
     typeStrings.put(serviceIntf, TypeNameObfuscator.SERVICE_INTERFACE_ID);
+
+    cachedTypeLastModifiedTimes = tsc.getTypeLastModifiedTimeMap();
   }

   protected String getProxySimpleName() {
=======================================
--- /trunk/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java Wed Jun 8 11:10:51 2011 +++ /trunk/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java Tue Jun 14 12:19:31 2011
@@ -21,6 +21,7 @@
 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.javac.rebind.CachedClientDataMap;
 import com.google.gwt.dev.javac.rebind.RebindResult;
 import com.google.gwt.dev.javac.rebind.RebindStatus;

@@ -58,14 +59,21 @@

     String returnTypeName = proxyCreator.create(proxyLogger, ctx);

-    /*
- * Return with RebindStatus.USE_PARTIAL_CACHED, since we are implementing an - * incremental scheme, which allows us to use a mixture of previously cached - * and newly generated compilation units and artifacts. For example, the - * field serializers only need to be generated fresh if their source type
-     * has changed (or if no previously cached version exists).
-     */
- return new RebindResult(RebindStatus.USE_PARTIAL_CACHED, returnTypeName);
+    if (ctx.isGeneratorResultCachingEnabled()) {
+ // Remember the type info that we care about for cacheability testing.
+      CachedClientDataMap clientData = new CachedClientDataMap();
+      proxyCreator.updateResultCacheData(clientData);
+
+      /*
+       * Return with RebindStatus.USE_PARTIAL_CACHED, since we are allowing
+ * generator result caching for field serializers, but other generated
+       * types cannot be cached effectively.
+       */
+ return new RebindResult(RebindStatus.USE_PARTIAL_CACHED, returnTypeName, clientData);
+    } else {
+      // If we can't be cacheable, don't return a cacheable result
+ return new RebindResult(RebindStatus.USE_ALL_NEW_WITH_NO_CACHING, returnTypeName);
+    }
   }

   protected ProxyCreator createProxyCreator(JClassType remoteService) {
=======================================
--- /trunk/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java Wed Jun 8 11:10:51 2011 +++ /trunk/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java Tue Jun 14 12:19:31 2011
@@ -24,9 +24,13 @@
 import com.google.gwt.core.ext.GeneratorContextExt;
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JArrayType;
 import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.JMethod;
 import com.google.gwt.core.ext.typeinfo.JParameterizedType;
+import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
+import com.google.gwt.core.ext.typeinfo.JRawType;
+import com.google.gwt.core.ext.typeinfo.JRealClassType;
 import com.google.gwt.core.ext.typeinfo.JType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.dev.javac.rebind.CachedRebindResult;
@@ -58,6 +62,12 @@
  */
 public class TypeSerializerCreator {

+  /**
+ * A key for storing cached type information for use with generator result
+   * caching.
+   */
+  public static final String CACHED_TYPE_INFO_KEY = "cached-type-info";
+
   /**
    * Configuration property to use type indices instead of type signatures.
    */
@@ -117,6 +127,8 @@

   private final String typeSerializerSimpleName;

+  private final Map<String, Long> typeLastModifiedTimeMap;
+
private final Map<JType, String> typeStrings = new IdentityHashMap<JType, String>();

public TypeSerializerCreator(TreeLogger logger, SerializableTypeOracle serializationOracle,
@@ -155,6 +167,16 @@
           + " was not defined. Is RemoteService.gwt.xml inherited?");
       throw new UnableToCompleteException();
     }
+
+    if (context.isGeneratorResultCachingEnabled()) {
+      typeLastModifiedTimeMap = new HashMap<String, Long>();
+    } else {
+      typeLastModifiedTimeMap = null;
+    }
+  }
+
+  public Map<String, Long> getTypeLastModifiedTimeMap() {
+    return typeLastModifiedTimeMap;
   }

   public Map<JType, String> getTypeStrings() {
@@ -224,11 +246,19 @@
        */
       assert (type.isClass() != null || type.isArray() != null);

- if (findCacheableFieldSerializerAndMarkForReuseIfAvailable(ctx, type)) {
-        // skip generation of field serializer
-        return;
+      if (ctx.isGeneratorResultCachingEnabled()) {
+        // get the last modified time for our type, and remember it
+ typeLastModifiedTimeMap.put(type.getQualifiedSourceName(), getLastModifiedTime(type));
+
+ // check the cache for a valid field serializer for the current type + if (findCacheableFieldSerializerAndMarkForReuseIfAvailable(logger, ctx, type)) { + // we can skip re-generation of the field serializer for the current
+          // type
+          return;
+        }
       }

+      // generate a new field serializer
       JClassType customFieldSerializer =
SerializableTypeOracleBuilder.findCustomFieldSerializer(typeOracle, type);
       FieldSerializerCreator creator =
@@ -259,8 +289,8 @@
    * FieldSerializer. If so, mark it for reuse, and return true. Otherwise
    * return false.
    */
- private boolean findCacheableFieldSerializerAndMarkForReuseIfAvailable(GeneratorContextExt ctx,
-      JType type) {
+ private boolean findCacheableFieldSerializerAndMarkForReuseIfAvailable(TreeLogger logger,
+      GeneratorContextExt ctx, JType type) {

     CachedRebindResult lastResult = ctx.getCachedGeneratorResult();
     if (lastResult == null || !ctx.isGeneratorResultCachingEnabled()) {
@@ -278,23 +308,53 @@
       return false;
     }

-    try {
-      /*
-       * TODO(jbrosenberg): Change this check to use getVersion() from
-       * TypeOracle, once that is available.
-       */
-      long lastModified = ctx.getSourceLastModifiedTime((JClassType) type);
-
- if (lastModified != 0L && lastModified < lastResult.getTimeGenerated()) {
-
-        // use cached version
-        return ctx.reuseTypeFromCacheIfAvailable(fieldSerializerName);
-      }
-    } catch (RuntimeException ex) {
-      // could get an exception checking modified time
+    @SuppressWarnings("unchecked")
+    Map<String, Long> cachedLastModifiedTimes =
+        (Map<String, Long>) lastResult.getClientData(CACHED_TYPE_INFO_KEY);
+    String sourceName = type.getQualifiedSourceName();
+
+    assert cachedLastModifiedTimes != null;
+    assert typeLastModifiedTimeMap.get(sourceName) != null;
+    boolean foundMatch = false;
+ if (typeLastModifiedTimeMap.get(sourceName).equals(cachedLastModifiedTimes.get(sourceName))) {
+      // use cached version, if available
+      foundMatch = ctx.reuseTypeFromCacheIfAvailable(fieldSerializerName);
+    }
+
+    if (logger.isLoggable(TreeLogger.TRACE)) {
+      String msg;
+      if (foundMatch) {
+ msg = "Reusing cached field serializer for " + type.getQualifiedSourceName();
+      } else {
+ msg = "Can't reuse cached field serializer for " + type.getQualifiedSourceName();
+      }
+      logger.log(TreeLogger.TRACE, msg);
     }

-    return false;
+    return foundMatch;
+  }
+
+  private long getLastModifiedTime(JType type) {
+    JType typeToCheck;
+    if (type instanceof JArrayType) {
+      typeToCheck = ((JArrayType) type).getLeafType();
+    } else if (type instanceof JRawType) {
+      typeToCheck = ((JRawType) type).getGenericType();
+    } else {
+      assert type instanceof JRealClassType;
+      typeToCheck = type;
+    }
+
+    long lastModifiedTime;
+    if (typeToCheck instanceof JRealClassType) {
+ lastModifiedTime = ((JRealClassType) typeToCheck).getLastModifiedTime();
+    } else {
+      // we have a type that is an array with a primitive leafType
+      assert typeToCheck instanceof JPrimitiveType;
+      lastModifiedTime = Long.MAX_VALUE;
+    }
+
+    return lastModifiedTime;
   }

   private String[] getPackageAndClassName(String fullClassName) {
@@ -335,10 +395,6 @@
     return composerFactory.createSourceWriter(ctx, printWriter);
   }

-  /**
-   * @param type
-   * @return
-   */
   private String getTypeString(JType type) {
     String typeString =
         SerializationUtils.getRpcTypeName(type) + "/"
=======================================
--- /trunk/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java Wed Jun 1 13:28:28 2011 +++ /trunk/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java Tue Jun 14 12:19:31 2011
@@ -106,10 +106,6 @@
     public ResourceOracle getResourcesOracle() {
       return null;
     }
-
-    public long getSourceLastModifiedTime(JClassType sourceType) {
-      return 0;
-    }

     public TypeOracle getTypeOracle() {
       return typeOracle;

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

Reply via email to