Generator Result Caching for RPC, with some refinements to the underlying framework
Review at http://gwt-code-reviews.appspot.com/1243801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9481 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java b/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java
new file mode 100644
index 0000000..9eed7ac
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/GeneratorContextExtWrapper.java
@@ -0,0 +1,104 @@
+/*
+ * 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;
+
+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;
+
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+/**
+ * EXPERIMENTAL and subject to change. Do not use this in production code.
+ * <p>
+ * A wrapper to access a base {@link GeneratorContext} instance as a
+ * {@link GeneratorContextExt} instance. Methods from the
+ * {@link GeneratorContext} interface are passed through to the baseContext,
+ * while methods from the {@link GeneratorContextExt} interface are given
+ * default stub implementations.
+ */
+public class GeneratorContextExtWrapper implements GeneratorContextExt {
+
+ /**
+ * Get a new instance wrapped from a base {@link GeneratorContext}
+ * implementation.
+ */
+ public static GeneratorContextExt newInstance(GeneratorContext baseContext) {
+ return new GeneratorContextExtWrapper(baseContext);
+ }
+
+ private final GeneratorContext baseContext;
+
+ public GeneratorContextExtWrapper(GeneratorContext baseContext) {
+ this.baseContext = baseContext;
+ }
+
+ public void commit(TreeLogger logger, PrintWriter pw) {
+ baseContext.commit(logger, pw);
+ }
+
+ public void commitArtifact(TreeLogger logger, Artifact<?> artifact)
+ throws UnableToCompleteException {
+ baseContext.commitArtifact(logger, artifact);
+ }
+
+ public GeneratedResource commitResource(TreeLogger logger, OutputStream os)
+ throws UnableToCompleteException {
+ return baseContext.commitResource(logger, os);
+ }
+
+ public CachedRebindResult getCachedGeneratorResult() {
+ return null;
+ }
+
+ public PropertyOracle getPropertyOracle() {
+ return baseContext.getPropertyOracle();
+ }
+
+ public ResourceOracle getResourcesOracle() {
+ return baseContext.getResourcesOracle();
+ }
+
+ public long getSourceLastModifiedTime(JClassType sourceType) {
+ return 0L;
+ }
+
+ public TypeOracle getTypeOracle() {
+ return baseContext.getTypeOracle();
+ }
+
+ public boolean isGeneratorResultCachingEnabled() {
+ return false;
+ }
+
+ public boolean reuseTypeFromCacheIfAvailable(String typeName) {
+ return false;
+ }
+
+ public PrintWriter tryCreate(
+ TreeLogger logger, String packageName, String simpleName) {
+ return baseContext.tryCreate(logger, packageName, simpleName);
+ }
+
+ public OutputStream tryCreateResource(TreeLogger logger, String partialPath)
+ throws UnableToCompleteException {
+ return baseContext.tryCreateResource(logger, partialPath);
+ }
+}
diff --git a/dev/core/src/com/google/gwt/core/ext/GeneratorExt.java b/dev/core/src/com/google/gwt/core/ext/GeneratorExt.java
index 2a1313c..ed8c976 100644
--- a/dev/core/src/com/google/gwt/core/ext/GeneratorExt.java
+++ b/dev/core/src/com/google/gwt/core/ext/GeneratorExt.java
@@ -16,49 +16,25 @@
package com.google.gwt.core.ext;
import com.google.gwt.dev.javac.rebind.RebindResult;
-import com.google.gwt.dev.javac.rebind.RebindStatus;
/**
* EXPERIMENTAL and subject to change. Do not use this in production code.
* <p>
- * Adds a new {@link #generateIfNecessary} method.
+ * Adds a new {@link #generateIncrementally} method.
* <p>
* TODO(jbrosenberg): Merge this into {@link Generator} directly, once the api
* has stabilized and we can remove the "experimental" moniker.
*/
public abstract class GeneratorExt extends Generator {
-
+
/**
- * A wrapper class for using old style {@link Generator} implementations where
- * a GeneratorExt instance is needed.
- */
- private static class BaseGeneratorWrapper extends GeneratorExt {
- final Generator baseGenerator;
-
- public BaseGeneratorWrapper(Generator baseGenerator) {
- this.baseGenerator = baseGenerator;
- }
-
- @Override
- public String generate(TreeLogger logger, GeneratorContext context,
- String typeName) throws UnableToCompleteException {
- return this.baseGenerator.generate(logger, context, typeName);
- }
- }
-
- /**
- * Get a new instance wrapped from an old style {@link Generator}
- * implementation.
- */
- public static GeneratorExt getWrappedInstance(Generator baseGenerator) {
- return new BaseGeneratorWrapper(baseGenerator);
- }
-
- /**
- * A default implementation of the abstract method defined in the old style
- * {@link Generator}.
+ * A default implementation of the abstract method defined in the base
+ * {@link Generator} class. This will wrap a call to
+ * {@link #generateIncrementally}, and attempt no caching. This supports
+ * backwards compatibility for applications or other generators which call
+ * this generator directly, as outside of the normal internal rebind process.
* <p>
- * Note, it is recommended that {@link #generateIncrementally} be used instead.
+ * It is recommended that {@link #generateIncrementally} be used instead.
*
* @return the name of a subclass to substitute for the requested class, or
* return <code>null</code> to cause the requested type itself to be
@@ -67,8 +43,13 @@
@Override
public String generate(TreeLogger logger, GeneratorContext context,
String typeName) throws UnableToCompleteException {
- // to override (implementing generateIncrementally instead is recommended)
- return null;
+
+ // wrap the passed in context
+ GeneratorContextExt contextExt =
+ GeneratorContextExtWrapper.newInstance(context);
+
+ RebindResult result = generateIncrementally(logger, contextExt, typeName);
+ return result.getReturnedTypeName();
}
/**
@@ -76,37 +57,21 @@
* type. The generator can use information from the context to determine
* whether it needs to regenerate everything, or whether it can selectively
* regenerate a subset of its output, or whether it can return quickly to
- * allow use of all previously cached objects. It will return a
- * {@link RebindResult}, which contains a {@link RebindStatus} field
- * indicating whether to use previously cached artifacts, newly generated
- * ones, or a partial mixture of both cached and newly generated objects.
+ * allow reuse of all previously cached objects. It will return a
+ * {@link RebindResult}, which contains a
+ * {@link com.google.gwt.dev.javac.rebind.RebindStatus} field indicating
+ * whether to use previously cached artifacts, newly generated ones, or a
+ * partial mixture of both cached and newly generated objects.
* <p>
* The result also includes a field for the name of the subclass to
* substitute for the requested class.
* <p>
- * For backwards compatibility, the default implementation calls the old-style
- * generate() method, and doesn't attempt any generator result caching.
- * <p>
* The generator throws an <code>UnableToCompleteException</code> if for
* any reason it cannot complete successfully.
*
- * @return a GeneratorResult
+ * @return a RebindResult
*/
- public RebindResult generateIncrementally(TreeLogger logger,
+ public abstract RebindResult generateIncrementally(TreeLogger logger,
GeneratorContextExt context, String typeName)
- throws UnableToCompleteException {
-
- // to override (default implementation calls unconditional generate() method)
-
- RebindStatus status;
- String resultTypeName = generate(logger, context, typeName);
- if (resultTypeName == null) {
- status = RebindStatus.USE_EXISTING;
- resultTypeName = typeName;
- } else {
- status = RebindStatus.USE_ALL_NEW_WITH_NO_CACHING;
- }
-
- return new RebindResult(status, resultTypeName);
- }
+ throws UnableToCompleteException;
}
diff --git a/dev/core/src/com/google/gwt/core/ext/GeneratorExtWrapper.java b/dev/core/src/com/google/gwt/core/ext/GeneratorExtWrapper.java
new file mode 100644
index 0000000..bc8a250
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/GeneratorExtWrapper.java
@@ -0,0 +1,70 @@
+/*
+ * 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;
+
+import com.google.gwt.dev.javac.rebind.RebindResult;
+import com.google.gwt.dev.javac.rebind.RebindStatus;
+
+/**
+ * EXPERIMENTAL and subject to change. Do not use this in production code.
+ * <p>
+ * A wrapper class for using base {@link Generator} implementations where
+ * a {@link GeneratorExt} instance is needed.
+ */
+public class GeneratorExtWrapper extends GeneratorExt {
+
+ /**
+ * Get a new instance wrapped from a base {@link Generator} implementation.
+ */
+ public static GeneratorExt newInstance(Generator baseGenerator) {
+ return new GeneratorExtWrapper(baseGenerator);
+ }
+
+ private final Generator baseGenerator;
+
+ public GeneratorExtWrapper(Generator baseGenerator) {
+ this.baseGenerator = baseGenerator;
+ }
+
+ /**
+ * Pass through to the base generator's generate method.
+ */
+ @Override
+ public String generate(TreeLogger logger, GeneratorContext context,
+ String typeName) throws UnableToCompleteException {
+ return this.baseGenerator.generate(logger, context, typeName);
+ }
+
+ /**
+ * Call base generator's generate method, and don't attempt any caching.
+ */
+ @Override
+ public RebindResult generateIncrementally(TreeLogger logger,
+ GeneratorContextExt context, String typeName)
+ throws UnableToCompleteException {
+
+ RebindStatus status;
+ String resultTypeName = generate(logger, context, typeName);
+ if (resultTypeName == null) {
+ status = RebindStatus.USE_EXISTING;
+ resultTypeName = typeName;
+ } else {
+ status = RebindStatus.USE_ALL_NEW_WITH_NO_CACHING;
+ }
+
+ return new RebindResult(status, resultTypeName);
+ }
+}
\ No newline at end of file
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 bc7d51c..1b3e4b7 100644
--- a/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
@@ -19,6 +19,7 @@
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.GeneratorContextExt;
import com.google.gwt.core.ext.GeneratorExt;
+import com.google.gwt.core.ext.GeneratorExtWrapper;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
@@ -332,7 +333,7 @@
* Adds all available cached generated units to the context. Existing units
* for a given type will not be overwritten.
*/
- public void addGeneratedUnitsFromCachedRebindResult() {
+ public void addGeneratedUnitsFromCache() {
if (cachedRebindResult != null
&& cachedRebindResult.getGeneratedUnits() != null) {
addGeneratedUnits(cachedRebindResult.getGeneratedUnits());
@@ -392,7 +393,7 @@
/**
* Commits all available cached Artifacts to the context.
*/
- public void commitArtifactsFromCachedRebindResult(TreeLogger logger) {
+ public void commitArtifactsFromCache(TreeLogger logger) {
if (cachedRebindResult != null
&& cachedRebindResult.getArtifacts() != null) {
for (Artifact<?> art : cachedRebindResult.getArtifacts()) {
@@ -654,7 +655,7 @@
if (generator instanceof GeneratorExt) {
generatorExt = (GeneratorExt) generator;
} else {
- generatorExt = GeneratorExt.getWrappedInstance(generator);
+ generatorExt = GeneratorExtWrapper.newInstance(generator);
}
RebindResult result;
@@ -686,7 +687,7 @@
/**
* Set previously cached rebind result for currently active generator.
*/
- public void setCachedRebindResult(CachedRebindResult cachedRebindResult) {
+ public void setCachedGeneratorResult(CachedRebindResult cachedRebindResult) {
this.cachedRebindResult = cachedRebindResult;
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java b/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
index 5736eb5..50bb0c2 100644
--- a/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
+++ b/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
@@ -67,7 +67,7 @@
CachedRebindResult cachedResult = rebindCacheGet(rule, typeName);
if (cachedResult != null) {
- genCtx.setCachedRebindResult(cachedResult);
+ genCtx.setCachedGeneratorResult(cachedResult);
}
// realize the rule (call a generator, or do type replacement, etc.)
@@ -189,8 +189,8 @@
// use all cached results
assert (cachedResult != null);
- genCtx.commitArtifactsFromCachedRebindResult(logger);
- genCtx.addGeneratedUnitsFromCachedRebindResult();
+ genCtx.commitArtifactsFromCache(logger);
+ genCtx.addGeneratedUnitsFromCache();
// use cached type name
resultTypeName = cachedResult.getReturnedTypeName();
diff --git a/user/src/com/google/gwt/rpc/rebind/RpcProxyCreator.java b/user/src/com/google/gwt/rpc/rebind/RpcProxyCreator.java
index 644501d..19e33bc 100644
--- a/user/src/com/google/gwt/rpc/rebind/RpcProxyCreator.java
+++ b/user/src/com/google/gwt/rpc/rebind/RpcProxyCreator.java
@@ -19,7 +19,7 @@
import com.google.gwt.core.client.impl.ArtificialRescue;
import com.google.gwt.core.client.impl.Impl;
import com.google.gwt.core.client.impl.ArtificialRescue.Rescue;
-import com.google.gwt.core.ext.GeneratorContext;
+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;
@@ -118,7 +118,7 @@
}
@Override
- protected void generateTypeHandlers(TreeLogger logger, GeneratorContext ctx,
+ protected void generateTypeHandlers(TreeLogger logger, GeneratorContextExt ctx,
SerializableTypeOracle serializationSto,
SerializableTypeOracle deserializationSto)
throws UnableToCompleteException {
@@ -271,7 +271,7 @@
@Override
protected String writeSerializationPolicyFile(TreeLogger logger,
- GeneratorContext ctx, SerializableTypeOracle serializationSto,
+ GeneratorContextExt ctx, SerializableTypeOracle serializationSto,
SerializableTypeOracle deserializationSto)
throws UnableToCompleteException {
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 4921dd4..da4e52e 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
@@ -19,7 +19,7 @@
import com.google.gwt.core.client.impl.Impl;
import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.ConfigurationProperty;
-import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.GeneratorContextExt;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
@@ -248,7 +248,7 @@
*
* @throws UnableToCompleteException
*/
- public String create(TreeLogger logger, GeneratorContext context)
+ public String create(TreeLogger logger, GeneratorContextExt context)
throws UnableToCompleteException {
TypeOracle typeOracle = context.getTypeOracle();
@@ -690,7 +690,7 @@
}
protected void generateTypeHandlers(TreeLogger logger,
- GeneratorContext context, SerializableTypeOracle typesSentFromBrowser,
+ GeneratorContextExt context, SerializableTypeOracle typesSentFromBrowser,
SerializableTypeOracle typesSentToBrowser)
throws UnableToCompleteException {
Event event = SpeedTracerLogger.start(CompilerEventType.GENERATOR_RPC_TYPE_SERIALIZER);
@@ -729,7 +729,7 @@
}
protected String writeSerializationPolicyFile(TreeLogger logger,
- GeneratorContext ctx, SerializableTypeOracle serializationSto,
+ GeneratorContextExt ctx, SerializableTypeOracle serializationSto,
SerializableTypeOracle deserializationSto)
throws UnableToCompleteException {
try {
@@ -830,7 +830,7 @@
}
private void emitPolicyFileArtifact(TreeLogger logger,
- GeneratorContext context, String partialPath)
+ GeneratorContextExt context, String partialPath)
throws UnableToCompleteException {
try {
String qualifiedSourceName = serviceIntf.getQualifiedSourceName();
@@ -881,7 +881,7 @@
return ResponseReader.OBJECT;
}
- private SourceWriter getSourceWriter(TreeLogger logger, GeneratorContext ctx,
+ private SourceWriter getSourceWriter(TreeLogger logger, GeneratorContextExt ctx,
JClassType serviceAsync) {
JPackage serviceIntfPkg = serviceAsync.getPackage();
String packageName = serviceIntfPkg == null ? "" : serviceIntfPkg.getName();
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 ded7cda..67b0c31 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
@@ -15,23 +15,25 @@
*/
package com.google.gwt.user.rebind.rpc;
-import com.google.gwt.core.ext.Generator;
-import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.GeneratorContextExt;
+import com.google.gwt.core.ext.GeneratorExt;
import com.google.gwt.core.ext.TreeLogger;
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.RebindResult;
+import com.google.gwt.dev.javac.rebind.RebindStatus;
/**
* Generator for producing the asynchronous version of a
* {@link com.google.gwt.user.client.rpc.RemoteService RemoteService} interface.
*/
-public class ServiceInterfaceProxyGenerator extends Generator {
-
+public class ServiceInterfaceProxyGenerator extends GeneratorExt {
+
@Override
- public String generate(TreeLogger logger, GeneratorContext ctx,
+ public RebindResult generateIncrementally(TreeLogger logger, GeneratorContextExt ctx,
String requestedClass) throws UnableToCompleteException {
-
+
TypeOracle typeOracle = ctx.getTypeOracle();
assert (typeOracle != null);
@@ -54,7 +56,16 @@
"Generating client proxy for remote service interface '"
+ remoteService.getQualifiedSourceName() + "'", null);
- return proxyCreator.create(proxyLogger, ctx);
+ 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);
}
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 ebb31d8..0f7726a 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
@@ -21,7 +21,7 @@
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.ConfigurationProperty;
-import com.google.gwt.core.ext.GeneratorContext;
+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.JClassType;
@@ -29,6 +29,7 @@
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.javac.rebind.CachedRebindResult;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
@@ -99,7 +100,7 @@
}
}
- private final GeneratorContext context;
+ private final GeneratorContextExt context;
private final SerializableTypeOracle deserializationOracle;
@@ -121,7 +122,7 @@
public TypeSerializerCreator(TreeLogger logger,
SerializableTypeOracle serializationOracle,
- SerializableTypeOracle deserializationOracle, GeneratorContext context,
+ SerializableTypeOracle deserializationOracle, GeneratorContextExt context,
String typeSerializerClassName, String typeSerializerSimpleName)
throws UnableToCompleteException {
this.context = context;
@@ -202,44 +203,52 @@
return typeSerializerClassName;
}
-
+
/*
* Create a field serializer for a type if it does not have a custom
* serializer.
*/
- private void createFieldSerializer(TreeLogger logger, GeneratorContext ctx,
+ private void createFieldSerializer(TreeLogger logger, GeneratorContextExt ctx,
JType type) {
Event event = SpeedTracerLogger.start(CompilerEventType.GENERATOR_RPC_FIELD_SERIALIZER);
- assert (type != null);
- assert (serializationOracle.isSerializable(type) || deserializationOracle.isSerializable(type));
-
- JParameterizedType parameterizedType = type.isParameterized();
- if (parameterizedType != null) {
- createFieldSerializer(logger, ctx, parameterizedType.getRawType());
- return;
+ try {
+ assert (type != null);
+ assert (serializationOracle.isSerializable(type) || deserializationOracle.isSerializable(type));
+
+ JParameterizedType parameterizedType = type.isParameterized();
+ if (parameterizedType != null) {
+ createFieldSerializer(logger, ctx, parameterizedType.getRawType());
+ return;
+ }
+
+ /*
+ * Only a JClassType can reach this point in the code. JPrimitives have been
+ * removed because their serialization is built in, interfaces have been
+ * removed because they are not an instantiable type and parameterized types
+ * have been broken down into their raw types.
+ */
+ assert (type.isClass() != null || type.isArray() != null);
+
+ if (findCacheableFieldSerializerAndMarkForReuseIfAvailable(ctx, type)) {
+ // skip generation of field serializer
+ return;
+ }
+
+ JClassType customFieldSerializer = SerializableTypeOracleBuilder.findCustomFieldSerializer(
+ typeOracle, type);
+ FieldSerializerCreator creator = new FieldSerializerCreator(typeOracle,
+ serializationOracle, deserializationOracle, (JClassType) type,
+ customFieldSerializer);
+ creator.realize(logger, ctx);
+ } finally {
+ event.end();
}
-
- /*
- * Only a JClassType can reach this point in the code. JPrimitives have been
- * removed because their serialization is built in, interfaces have been
- * removed because they are not an instantiable type and parameterized types
- * have been broken down into their raw types.
- */
- assert (type.isClass() != null || type.isArray() != null);
-
- JClassType customFieldSerializer = SerializableTypeOracleBuilder.findCustomFieldSerializer(
- typeOracle, type);
- FieldSerializerCreator creator = new FieldSerializerCreator(typeOracle,
- serializationOracle, deserializationOracle, (JClassType) type,
- customFieldSerializer);
- creator.realize(logger, ctx);
- event.end();
}
/*
* Create all of the necessary field serializers.
*/
- private void createFieldSerializers(TreeLogger logger, GeneratorContext ctx) {
+ private void createFieldSerializers(TreeLogger logger, GeneratorContextExt ctx) {
JType[] types = getSerializableTypes();
int typeCount = types.length;
for (int typeIndex = 0; typeIndex < typeCount; ++typeIndex) {
@@ -249,7 +258,51 @@
createFieldSerializer(logger, ctx, type);
}
}
-
+
+ /*
+ * check whether we can use a previously generated version of a
+ * FieldSerializer. If so, mark it for reuse, and return true.
+ * Otherwise return false.
+ */
+ private boolean findCacheableFieldSerializerAndMarkForReuseIfAvailable(
+ GeneratorContextExt ctx, JType type) {
+
+ CachedRebindResult lastResult = ctx.getCachedGeneratorResult();
+ if (lastResult == null || !ctx.isGeneratorResultCachingEnabled()) {
+ return false;
+ }
+
+ String fieldSerializerName =
+ SerializationUtils.getStandardSerializerName((JClassType) type);
+
+ if (type instanceof JClassType) {
+ // check that it is available for reuse
+ if (!lastResult.isTypeCached(fieldSerializerName)) {
+ return false;
+ }
+ } else {
+ 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
+ }
+
+ return false;
+ }
private String[] getPackageAndClassName(String fullClassName) {
String className = fullClassName;
String packageName = "";
@@ -265,7 +318,7 @@
return serializableTypes;
}
- private SourceWriter getSourceWriter(TreeLogger logger, GeneratorContext ctx) {
+ private SourceWriter getSourceWriter(TreeLogger logger, GeneratorContextExt ctx) {
String name[] = getPackageAndClassName(typeSerializerClassName);
String packageName = name[0];
String className = name[1];