| /* |
| * Copyright 2008 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.dev.jjs; |
| |
| import com.google.gwt.core.ext.linker.ModuleMetricsArtifact; |
| import com.google.gwt.core.ext.linker.PrecompilationMetricsArtifact; |
| import com.google.gwt.dev.PrecompileTaskOptions; |
| import com.google.gwt.dev.PrecompileTaskOptionsImpl; |
| import com.google.gwt.dev.jjs.ast.JProgram; |
| import com.google.gwt.dev.js.ast.JsProgram; |
| import com.google.gwt.dev.util.DiskCache; |
| import com.google.gwt.dev.util.Util; |
| import com.google.gwt.thirdparty.guava.common.collect.Sets; |
| |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.Serializable; |
| import java.util.Collections; |
| import java.util.Set; |
| import java.util.SortedSet; |
| |
| /** |
| * Represents a unified, non-permutation specific AST. This AST is used to drive |
| * per-permutation compiles. |
| */ |
| public class UnifiedAst implements Serializable { |
| |
| /** |
| * Encapsulates the combined programs. |
| */ |
| public static final class AST implements Serializable { |
| private final JProgram jProgram; |
| private final JsProgram jsProgram; |
| |
| public AST(JProgram jProgram, JsProgram jsProgram) { |
| this.jProgram = jProgram; |
| this.jsProgram = jsProgram; |
| } |
| |
| public JProgram getJProgram() { |
| return jProgram; |
| } |
| |
| public JsProgram getJsProgram() { |
| return jsProgram; |
| } |
| } |
| |
| private static final DiskCache diskCache = DiskCache.INSTANCE; |
| |
| /** |
| * The original AST; nulled out once consumed (by the first call to |
| * {@link #getFreshAst()}. |
| */ |
| private transient AST initialAst; |
| |
| /** |
| * Metrics for the module load phase. Stored here so they can be written out |
| * as artifacts in the compile phase. |
| */ |
| private ModuleMetricsArtifact moduleMetrics; |
| |
| /** |
| * Used for internal synchronization. |
| */ |
| private transient Object myLockObject = new Object(); |
| |
| /** |
| * The compilation options. |
| */ |
| private final PrecompileTaskOptions options; |
| |
| /** |
| * Metrics for the precompilation phase. Stored here so they can be written |
| * out as artifacts in the compile phase. |
| */ |
| private PrecompilationMetricsArtifact precompilationMetrics; |
| |
| /** |
| * The set of all live rebind request types in the AST. |
| */ |
| private final SortedSet<String> rebindRequests; |
| |
| /** |
| * The serialized AST. |
| */ |
| private transient long serializedAstToken; |
| |
| public UnifiedAst(PrecompileTaskOptions options, AST initialAst, boolean singlePermutation, |
| Set<String> rebindRequests) { |
| this.options = new PrecompileTaskOptionsImpl(options); |
| this.initialAst = initialAst; |
| this.rebindRequests = Collections.unmodifiableSortedSet(Sets.newTreeSet(rebindRequests)); |
| this.serializedAstToken = singlePermutation ? -1 : diskCache.writeObject(initialAst); |
| } |
| |
| /** |
| * Return the current AST so that clients can explicitly walk the Java or |
| * JavaScript parse trees. |
| * |
| * @return the current AST object holding the Java and JavaScript trees. |
| */ |
| public AST getFreshAst() { |
| synchronized (myLockObject) { |
| if (initialAst != null) { |
| AST result = initialAst; |
| initialAst = null; |
| return result; |
| } else { |
| if (serializedAstToken < 0) { |
| throw new IllegalStateException( |
| "No serialized AST was cached and AST was already consumed."); |
| } |
| return diskCache.readObject(serializedAstToken, AST.class); |
| } |
| } |
| } |
| |
| /** |
| * Returns metrics about the module load portion of the build. |
| */ |
| public ModuleMetricsArtifact getModuleMetrics() { |
| return moduleMetrics; |
| } |
| |
| /** |
| * Returns the active set of JJS options associated with this compile. |
| */ |
| public PrecompileTaskOptions getOptions() { |
| return new PrecompileTaskOptionsImpl(options); |
| } |
| |
| /** |
| * Returns metrics about the precompilation portion of the build. |
| */ |
| public PrecompilationMetricsArtifact getPrecompilationMetrics() { |
| return precompilationMetrics; |
| } |
| |
| /** |
| * Returns the set of live rebind requests in the AST. |
| */ |
| public SortedSet<String> getRebindRequests() { |
| return rebindRequests; |
| } |
| |
| /** |
| * Internally prepares a new AST for compilation if one is not already |
| * prepared. |
| */ |
| public void prepare() { |
| synchronized (myLockObject) { |
| if (initialAst == null) { |
| initialAst = diskCache.readObject(serializedAstToken, AST.class); |
| } |
| } |
| } |
| |
| /** |
| * Save some module load metrics in the AST. |
| */ |
| public void setModuleMetrics(ModuleMetricsArtifact metrics) { |
| this.moduleMetrics = metrics; |
| } |
| |
| /** |
| * Save some precompilation metrics in the AST. |
| */ |
| public void setPrecompilationMetrics(PrecompilationMetricsArtifact metrics) { |
| this.precompilationMetrics = metrics; |
| } |
| |
| /** |
| * Re-initialize lock object; copy serialized AST straight to cache. |
| */ |
| private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { |
| stream.defaultReadObject(); |
| myLockObject = new Object(); |
| serializedAstToken = diskCache.transferFromStream(stream); |
| } |
| |
| /** |
| * Force byte serialization of AST before writing. |
| */ |
| private void writeObject(ObjectOutputStream stream) throws IOException { |
| stream.defaultWriteObject(); |
| if (serializedAstToken >= 0) { |
| // Copy the bytes. |
| diskCache.transferToStream(serializedAstToken, stream); |
| } else if (initialAst != null) { |
| // Serialize into raw bytes. |
| Util.writeObjectToStream(stream, initialAst); |
| } else { |
| throw new IllegalStateException("No serialized AST was cached and AST was already consumed."); |
| } |
| } |
| } |