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
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10336 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/GeneratorContextExt.java b/dev/core/src/com/google/gwt/core/ext/GeneratorContextExt.java
index 86f818d..7153684 100644
--- a/dev/core/src/com/google/gwt/core/ext/GeneratorContextExt.java
+++ b/dev/core/src/com/google/gwt/core/ext/GeneratorContextExt.java
@@ -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;
/**
@@ -39,15 +38,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.
*/
boolean isGeneratorResultCachingEnabled();
diff --git a/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java b/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java
index 3970057..b429da3 100644
--- a/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java
+++ b/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java
@@ -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;
@@ -80,10 +79,6 @@
return baseContext.getResourcesOracle();
}
- public long getSourceLastModifiedTime(JClassType sourceType) {
- return 0L;
- }
-
public TypeOracle getTypeOracle() {
return baseContext.getTypeOracle();
}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
index e207a5f..fdee5dc 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
@@ -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();
}
diff --git a/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java b/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
index ca3f0f5..ae94764 100644
--- a/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
@@ -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;
@@ -541,39 +539,6 @@
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();
}
diff --git a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
index 0c93ee3..593c76a 100644
--- a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
+++ b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
@@ -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;
}
diff --git a/dev/core/src/com/google/gwt/dev/javac/rebind/CachedPropertyInformation.java b/dev/core/src/com/google/gwt/dev/javac/rebind/CachedPropertyInformation.java
index b18a3d9..bddb4a7 100644
--- a/dev/core/src/com/google/gwt/dev/javac/rebind/CachedPropertyInformation.java
+++ b/dev/core/src/com/google/gwt/dev/javac/rebind/CachedPropertyInformation.java
@@ -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;
}
}
diff --git a/dev/core/src/com/google/gwt/dev/javac/typemodel/JRealClassType.java b/dev/core/src/com/google/gwt/dev/javac/typemodel/JRealClassType.java
index eb4c3d8..a780b07 100644
--- a/dev/core/src/com/google/gwt/dev/javac/typemodel/JRealClassType.java
+++ b/dev/core/src/com/google/gwt/dev/javac/typemodel/JRealClassType.java
@@ -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);
}
diff --git a/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java b/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java
index 8ba1556..9429d04 100644
--- a/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java
+++ b/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java
@@ -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, "");
- }
+ assert type instanceof JRealClassType;
+ JRealClassType sourceRealType = (JRealClassType) type;
+ typeLastModifiedTimeMap.put(typeName, sourceRealType.getLastModifiedTime());
}
- return typeSignatures;
+ 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);
}
/**
diff --git a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
index 8b1d349..8446a30 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
@@ -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.
*/
@@ -344,6 +347,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,
SerializableTypeOracleBuilder typesSentToBrowserBuilder) throws UnableToCompleteException {
@@ -645,6 +654,8 @@
typeStrings = new HashMap<JType, String>(tsc.getTypeStrings());
typeStrings.put(serviceIntf, TypeNameObfuscator.SERVICE_INTERFACE_ID);
+
+ cachedTypeLastModifiedTimes = tsc.getTypeLastModifiedTimeMap();
}
protected String getProxySimpleName() {
diff --git a/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java b/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
index b84941e..c49244c 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
@@ -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) {
diff --git a/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java b/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
index 436d1c6..288b7cc 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
@@ -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;
@@ -59,6 +63,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.
*/
public static final String GWT_ELIDE_TYPE_NAMES_FROM_RPC = "gwt.elideTypeNamesFromRPC";
@@ -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);
+ @SuppressWarnings("unchecked")
+ Map<String, Long> cachedLastModifiedTimes =
+ (Map<String, Long>) lastResult.getClientData(CACHED_TYPE_INFO_KEY);
+ String sourceName = type.getQualifiedSourceName();
- if (lastModified != 0L && lastModified < lastResult.getTimeGenerated()) {
-
- // use cached version
- return ctx.reuseTypeFromCacheIfAvailable(fieldSerializerName);
- }
- } catch (RuntimeException ex) {
- // could get an exception checking modified time
+ 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);
}
- return false;
+ 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 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) + "/"
diff --git a/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java b/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java
index 4a4227a..f7dcf56 100644
--- a/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java
+++ b/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java
@@ -107,10 +107,6 @@
return null;
}
- public long getSourceLastModifiedTime(JClassType sourceType) {
- return 0;
- }
-
public TypeOracle getTypeOracle() {
return typeOracle;
}