A faster implementation of SOYC that
reports whole-number size breakdowns in terms of
the program state after optimization.
Review by: kprobst
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5872 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/CompilationAnalysis.java b/dev/core/src/com/google/gwt/core/ext/linker/CompilationAnalysis.java
index f4332b6..615f333 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/CompilationAnalysis.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/CompilationAnalysis.java
@@ -17,6 +17,10 @@
import com.google.gwt.core.ext.Linker;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
/**
* Represents analysis data for a CompilationResult.
*/
@@ -32,70 +36,77 @@
public abstract EmittedArtifact getDepFile();
/**
+ * @return a file with detailed story information
+ */
+ public abstract EmittedArtifact getDetailedStoriesFile();
+
+ /**
+ * @return a file of size maps
+ */
+ public abstract EmittedArtifact getSizeMapsFile();
+
+ /**
* @return a file of split points
*/
public abstract EmittedArtifact getSplitPointsFile();
- /**
- * @return a file of stories
- */
- public abstract EmittedArtifact getStoriesFile();
-
@Override
public final int hashCode() {
-
- assert (getDepFile() != null);
- assert (getStoriesFile() != null);
- assert (getSplitPointsFile() != null);
-
- return 17 * (37 + getDepFile().getPartialPath().hashCode())
- + (37 + getStoriesFile().getPartialPath().hashCode())
- + (37 + getSplitPointsFile().getPartialPath().hashCode());
+ int code = 37;
+ for (EmittedArtifact file : allFiles()) {
+ if (file == null) {
+ code = code * 17 + 37;
+ } else {
+ code = code * 17 + file.getPartialPath().hashCode();
+ }
+ }
+ return code;
}
@Override
protected final int compareToComparableArtifact(CompilationAnalysis o) {
+ LinkedList<EmittedArtifact> myFiles = new LinkedList<EmittedArtifact>(
+ allFiles());
+ LinkedList<EmittedArtifact> otherFiles = new LinkedList<EmittedArtifact>(
+ o.allFiles());
+ assert (myFiles.size() == otherFiles.size());
- if ((getDepFile() == null) && (o.getDepFile() == null)) {
- return 0;
- } else if ((getDepFile() == null) && (o.getDepFile() != null)) {
- return 1;
- } else if ((getDepFile() != null) && (o.getDepFile() == null)) {
- return -1;
- } else if (getDepFile().getPartialPath().compareTo(
- o.getDepFile().getPartialPath()) == 0) {
- if ((getStoriesFile() == null) && (o.getStoriesFile() == null)) {
- return 0;
- } else if ((getStoriesFile() == null) && (o.getStoriesFile() != null)) {
- return 1;
- } else if ((getStoriesFile() != null) && (o.getStoriesFile() == null)) {
- return -1;
- } else if (getStoriesFile().getPartialPath().compareTo(
- o.getStoriesFile().getPartialPath()) == 0) {
- if ((getSplitPointsFile() == null) && (o.getSplitPointsFile() == null)) {
- return 0;
- }
- if ((getSplitPointsFile() == null) && (o.getSplitPointsFile() != null)) {
- return 1;
- } else if ((getSplitPointsFile() != null)
- && (o.getSplitPointsFile() == null)) {
- return -1;
- } else {
- return getSplitPointsFile().getPartialPath().compareTo(
- o.getSplitPointsFile().getPartialPath());
- }
- } else {
- return getStoriesFile().getPartialPath().compareTo(
- o.getStoriesFile().getPartialPath());
+ while (!myFiles.isEmpty()) {
+ EmittedArtifact myFile = myFiles.removeFirst();
+ EmittedArtifact otherFile = otherFiles.removeFirst();
+ if (myFile == null && otherFile == null) {
+ continue;
}
- } else {
- return getDepFile().getPartialPath().compareTo(
- o.getDepFile().getPartialPath());
+ if (myFile == null && otherFile != null) {
+ return -1;
+ }
+ if (myFile != null && otherFile == null) {
+ return 1;
+ }
+ assert myFile != null;
+ assert otherFile != null;
+
+ int fileCompare = myFile.getPartialPath().compareTo(
+ otherFile.getPartialPath());
+ if (fileCompare != 0) {
+ return fileCompare;
+ }
}
+
+ return 0;
}
@Override
protected final Class<CompilationAnalysis> getComparableArtifactType() {
return CompilationAnalysis.class;
}
+
+ private List<EmittedArtifact> allFiles() {
+ List<EmittedArtifact> files = new ArrayList<EmittedArtifact>();
+ files.add(getSplitPointsFile());
+ files.add(getDepFile());
+ files.add(getSizeMapsFile());
+ files.add(getDetailedStoriesFile());
+ return files;
+ }
}
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationAnalysis.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationAnalysis.java
index 022baef..b9a8969 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationAnalysis.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardCompilationAnalysis.java
@@ -43,24 +43,31 @@
private SoycArtifact depFile;
/**
+ * File containing detailed story information.
+ */
+ private SoycArtifact detailedStoriesFile;
+
+ /**
* File containing split points.
*/
private SoycArtifact splitPointsFile;
/**
- * File containing stories.
+ * File containing size maps.
*/
- private SoycArtifact storiesFile;
+ private SoycArtifact sizeMapsFile;
/**
* Constructed by PermutationCompiler.
*/
public StandardCompilationAnalysis(SoycArtifact dependencies,
- SoycArtifact stories, SoycArtifact splitPoints) {
+ SoycArtifact sizeMaps, SoycArtifact splitPoints,
+ SoycArtifact detailedStories) {
super(StandardLinkerContext.class);
this.depFile = dependencies;
- this.storiesFile = stories;
+ this.sizeMapsFile = sizeMaps;
this.splitPointsFile = splitPoints;
+ this.detailedStoriesFile = detailedStories;
}
@Override
@@ -69,12 +76,17 @@
}
@Override
- public SoycArtifact getSplitPointsFile() {
- return splitPointsFile;
+ public SoycArtifact getDetailedStoriesFile() {
+ return detailedStoriesFile;
}
@Override
- public SoycArtifact getStoriesFile() {
- return storiesFile;
+ public SoycArtifact getSizeMapsFile() {
+ return sizeMapsFile;
+ }
+
+ @Override
+ public SoycArtifact getSplitPointsFile() {
+ return splitPointsFile;
}
}
diff --git a/dev/core/src/com/google/gwt/core/ext/soyc/impl/SizeMapRecorder.java b/dev/core/src/com/google/gwt/core/ext/soyc/impl/SizeMapRecorder.java
new file mode 100644
index 0000000..997d2b0
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/soyc/impl/SizeMapRecorder.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2009 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.soyc.impl;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.dev.jjs.ast.JMethod;
+import com.google.gwt.dev.jjs.ast.JReferenceType;
+import com.google.gwt.dev.jjs.ast.JType;
+import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
+import com.google.gwt.dev.js.SizeBreakdown;
+import com.google.gwt.dev.js.ast.JsName;
+import com.google.gwt.dev.util.Util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * Records an array of {@link SizeBreakdown} to a gzipped XML file. That file is
+ * then read to produce a Story of Your Compile.
+ */
+public class SizeMapRecorder {
+ /**
+ * A human-accessible type and description of a program reference. These are
+ * produced by
+ * {@link SizeMapRecorder#typedProgramReference(JsName, JavaToJavaScriptMap)}
+ * and used by
+ * {@link SizeMapRecorder#recordMap(TreeLogger, OutputStream, SizeBreakdown[], JavaToJavaScriptMap)}
+ * .
+ */
+ private static class TypedProgramReference {
+ public final String type;
+ public final String description;
+
+ public TypedProgramReference(String type, String description) {
+ this.type = type;
+ this.description = description;
+ }
+ }
+
+ public static void recordMap(TreeLogger logger, OutputStream out,
+ SizeBreakdown[] sizeBreakdowns, JavaToJavaScriptMap jjsmap,
+ Map<JsName, String> obfuscateMap) throws IOException {
+ out = new GZIPOutputStream(out);
+ Writer writer = new OutputStreamWriter(out, Util.DEFAULT_ENCODING);
+
+ writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ writer.append("<sizemaps>\n");
+
+ for (int i = 0; i < sizeBreakdowns.length; i++) {
+ writer.append("<sizemap fragment=\"" + i + "\" " + "size=\""
+ + sizeBreakdowns[i].getSize() + "\">\n");
+ for (Entry<JsName, Integer> sizeMapEntry : sizeBreakdowns[i].getSizeMap().entrySet()) {
+ JsName name = sizeMapEntry.getKey();
+ int size = sizeMapEntry.getValue();
+ TypedProgramReference typedRef = typedProgramReference(name, jjsmap,
+ obfuscateMap);
+ writer.append(" <size " + "type=\"" + Util.escapeXml(typedRef.type)
+ + "\" " + "ref=\"" + Util.escapeXml(typedRef.description) + "\" "
+ + "size=\"" + size + "\"/>\n");
+ }
+ writer.append("</sizemap>\n");
+ }
+
+ writer.append("</sizemaps>");
+ writer.close();
+ }
+
+ private static TypedProgramReference typedProgramReference(JsName name,
+ JavaToJavaScriptMap jjsmap, Map<JsName, String> obfuscateMap) {
+ JMethod method = jjsmap.nameToMethod(name);
+ if (method != null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(method.getEnclosingType().getName());
+ sb.append("::");
+ sb.append(method.getName());
+ sb.append("(");
+ for (JType type : method.getOriginalParamTypes()) {
+ sb.append(type.getJsniSignatureName());
+ }
+ sb.append(")");
+ sb.append(method.getOriginalReturnType().getJsniSignatureName());
+ String desc = sb.toString();
+ return new TypedProgramReference("method", desc);
+ }
+
+ JReferenceType type = jjsmap.nameToType(name);
+ if (type != null) {
+ return new TypedProgramReference("type", type.getName());
+ }
+
+ String string = obfuscateMap.get(name);
+ if (string != null) {
+ return new TypedProgramReference("string", string);
+ }
+
+ return new TypedProgramReference("var", name.getShortIdent());
+ }
+}
diff --git a/dev/core/src/com/google/gwt/core/linker/SoycReportLinker.java b/dev/core/src/com/google/gwt/core/linker/SoycReportLinker.java
index 2d93ab4..bb32174 100644
--- a/dev/core/src/com/google/gwt/core/linker/SoycReportLinker.java
+++ b/dev/core/src/com/google/gwt/core/linker/SoycReportLinker.java
@@ -43,8 +43,11 @@
if (soycFiles.getDepFile() != null) {
results.add(soycFiles.getDepFile());
}
- if (soycFiles.getStoriesFile() != null) {
- results.add(soycFiles.getStoriesFile());
+ if (soycFiles.getSizeMapsFile() != null) {
+ results.add(soycFiles.getSizeMapsFile());
+ }
+ if (soycFiles.getDetailedStoriesFile() != null) {
+ results.add(soycFiles.getDetailedStoriesFile());
}
results.add(soycFiles.getSplitPointsFile());
}
diff --git a/dev/core/src/com/google/gwt/dev/Precompile.java b/dev/core/src/com/google/gwt/dev/Precompile.java
index 23bf485..e137fea 100644
--- a/dev/core/src/com/google/gwt/dev/Precompile.java
+++ b/dev/core/src/com/google/gwt/dev/Precompile.java
@@ -54,6 +54,7 @@
import com.google.gwt.dev.util.arg.ArgHandlerMaxPermsPerPrecompile;
import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle;
import com.google.gwt.dev.util.arg.ArgHandlerSoyc;
+import com.google.gwt.dev.util.arg.ArgHandlerSoycDetailed;
import com.google.gwt.dev.util.arg.ArgHandlerValidateOnlyFlag;
import com.google.gwt.dev.util.arg.OptionDisableUpdateCheck;
import com.google.gwt.dev.util.arg.OptionDumpSignatures;
@@ -104,6 +105,7 @@
registerHandler(new ArgHandlerDumpSignatures(options));
registerHandler(new ArgHandlerMaxPermsPerPrecompile(options));
registerHandler(new ArgHandlerSoyc(options));
+ registerHandler(new ArgHandlerSoycDetailed(options));
}
@Override
@@ -192,6 +194,10 @@
return jjsOptions.isSoycEnabled();
}
+ public boolean isSoycExtra() {
+ return jjsOptions.isSoycExtra();
+ }
+
public boolean isUpdateCheckDisabled() {
return disableUpdateCheck;
}
@@ -256,6 +262,10 @@
jjsOptions.setSoycEnabled(enabled);
}
+ public void setSoycExtra(boolean soycExtra) {
+ jjsOptions.setSoycExtra(soycExtra);
+ }
+
public void setValidateOnly(boolean validateOnly) {
this.validateOnly = validateOnly;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java b/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
index f9ff12c..28b7bbc 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
@@ -25,6 +25,7 @@
import com.google.gwt.dev.util.arg.OptionRunAsyncEnabled;
import com.google.gwt.dev.util.arg.OptionScriptStyle;
import com.google.gwt.dev.util.arg.OptionSoycEnabled;
+import com.google.gwt.dev.util.arg.OptionSoycDetailed;
/**
* Controls options for the {@link JavaToJavaScriptCompiler}.
@@ -32,5 +33,5 @@
public interface JJSOptions extends OptionAggressivelyOptimize,
OptionDisableClassMetadata, OptionDisableCastChecking, OptionDraftCompile,
OptionEnableAssertions, OptionRunAsyncEnabled, OptionScriptStyle,
- OptionSoycEnabled, OptionCompilationStateRetained, OptionOptimizePrecompile {
+ OptionSoycEnabled, OptionSoycDetailed, OptionCompilationStateRetained, OptionOptimizePrecompile {
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java b/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
index 80c49f5..a26d4a2 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
@@ -32,6 +32,7 @@
private JsOutputOption output = JsOutputOption.OBFUSCATED;
private boolean runAsyncEnabled = true;
private boolean soycEnabled = false;
+ private boolean soycExtra = false;
public JJSOptionsImpl() {
}
@@ -50,6 +51,7 @@
setOutput(other.getOutput());
setRunAsyncEnabled(other.isRunAsyncEnabled());
setSoycEnabled(other.isSoycEnabled());
+ setSoycExtra(other.isSoycExtra());
}
public JsOutputOption getOutput() {
@@ -92,6 +94,10 @@
return soycEnabled;
}
+ public boolean isSoycExtra() {
+ return soycExtra;
+ }
+
public void setAggressivelyOptimize(boolean aggressivelyOptimize) {
this.aggressivelyOptimize = aggressivelyOptimize;
}
@@ -131,4 +137,8 @@
public void setSoycEnabled(boolean enabled) {
soycEnabled = enabled;
}
+
+ public void setSoycExtra(boolean enabled) {
+ soycExtra = enabled;
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index 52468eb..02b1199 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -26,6 +26,7 @@
import com.google.gwt.core.ext.linker.impl.StandardCompilationAnalysis.SoycArtifact;
import com.google.gwt.core.ext.soyc.Range;
import com.google.gwt.core.ext.soyc.impl.DependencyRecorder;
+import com.google.gwt.core.ext.soyc.impl.SizeMapRecorder;
import com.google.gwt.core.ext.soyc.impl.SplitPointRecorder;
import com.google.gwt.core.ext.soyc.impl.StoryRecorder;
import com.google.gwt.dev.cfg.ModuleDef;
@@ -88,13 +89,14 @@
import com.google.gwt.dev.js.JsObfuscateNamer;
import com.google.gwt.dev.js.JsPrettyNamer;
import com.google.gwt.dev.js.JsReportGenerationVisitor;
-import com.google.gwt.dev.js.JsSourceGenerationVisitor;
+import com.google.gwt.dev.js.JsSourceGenerationVisitorWithSizeBreakdown;
import com.google.gwt.dev.js.JsStackEmulator;
import com.google.gwt.dev.js.JsStaticEval;
import com.google.gwt.dev.js.JsStringInterner;
import com.google.gwt.dev.js.JsSymbolResolver;
import com.google.gwt.dev.js.JsUnusedFunctionRemover;
import com.google.gwt.dev.js.JsVerboseNamer;
+import com.google.gwt.dev.js.SizeBreakdown;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.util.AbstractTextOutput;
@@ -104,6 +106,7 @@
import com.google.gwt.dev.util.PerfLogger;
import com.google.gwt.dev.util.TextOutput;
import com.google.gwt.dev.util.Util;
+import com.google.gwt.dev.util.collect.Maps;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
@@ -291,9 +294,10 @@
}
// (10.5) Obfuscate
+ Map<JsName, String> obfuscateMap = Maps.create();
switch (options.getOutput()) {
case OBFUSCATED:
- JsStringInterner.exec(jprogram, jsProgram);
+ obfuscateMap = JsStringInterner.exec(jprogram, jsProgram);
JsObfuscateNamer.exec(jsProgram);
break;
case PRETTY:
@@ -301,7 +305,7 @@
JsPrettyNamer.exec(jsProgram);
break;
case DETAILED:
- JsStringInterner.exec(jprogram, jsProgram);
+ obfuscateMap = JsStringInterner.exec(jprogram, jsProgram);
JsVerboseNamer.exec(jsProgram);
break;
default:
@@ -317,33 +321,19 @@
// (12) Generate the final output text.
String[] js = new String[jsProgram.getFragmentCount()];
- List<Map<Range, SourceInfo>> sourceInfoMaps = options.isSoycEnabled()
- ? new ArrayList<Map<Range, SourceInfo>>(jsProgram.getFragmentCount())
- : null;
StatementRanges[] ranges = new StatementRanges[js.length];
- for (int i = 0; i < js.length; i++) {
- DefaultTextOutput out = new DefaultTextOutput(
- options.getOutput().shouldMinimize());
- JsSourceGenerationVisitor v;
- if (sourceInfoMaps != null) {
- v = new JsReportGenerationVisitor(out);
- } else {
- v = new JsSourceGenerationVisitor(out);
- }
- v.accept(jsProgram.getFragmentBlock(i));
- js[i] = out.toString();
- if (sourceInfoMaps != null) {
- sourceInfoMaps.add(((JsReportGenerationVisitor) v).getSourceInfoMap());
- }
- ranges[i] = v.getStatementRanges();
- }
+ SizeBreakdown[] sizeBreakdowns = options.isSoycEnabled()
+ ? new SizeBreakdown[js.length] : null;
+ List<Map<Range, SourceInfo>> sourceInfoMaps = options.isSoycExtra()
+ ? new ArrayList<Map<Range, SourceInfo>>() : null;
+ generateJavaScriptCode(options, jsProgram, map, js, ranges,
+ sizeBreakdowns, sourceInfoMaps);
PermutationResult toReturn = new PermutationResultImpl(js,
makeSymbolMap(symbolTable), ranges, permutationId);
-
toReturn.getArtifacts().add(
- makeSoycArtifact(logger, permutationId, jprogram, js, sourceInfoMaps,
- dependencies));
+ makeSoycArtifact(logger, permutationId, jprogram, js, sizeBreakdowns,
+ sourceInfoMaps, dependencies, map, obfuscateMap));
System.out.println("Permutation took "
+ (System.currentTimeMillis() - permStart) + " ms");
@@ -422,7 +412,7 @@
checkForErrors(logger, goldenCuds, false);
PerfLogger.start("Build AST");
- CorrelationFactory correlator = options.isSoycEnabled()
+ CorrelationFactory correlator = options.isSoycExtra()
? new RealCorrelationFactory() : new DummyCorrelationFactory();
JProgram jprogram = new JProgram(correlator);
JsProgram jsProgram = new JsProgram(correlator);
@@ -816,6 +806,46 @@
return null;
}
+ /**
+ * Generate JavaScript code from the given JavaScript ASTs. Also produces
+ * information about that transformation.
+ *
+ * @param options The options this compiler instance is running with
+ * @param jsProgram The AST to convert to source code
+ * @param jjsMap A map between the JavaScript AST and the Java AST it came
+ * from
+ * @param js An array to hold the output JavaScript
+ * @param ranges An array to hold the statement ranges for that JavaScript
+ * @param sizeBreakdowns An array to hold the size breakdowns for that
+ * JavaScript
+ * @param sourceInfoMaps An array to hold the source info maps for that
+ * JavaScript
+ */
+ private static void generateJavaScriptCode(JJSOptions options,
+ JsProgram jsProgram, JavaToJavaScriptMap jjsMap, String[] js,
+ StatementRanges[] ranges, SizeBreakdown[] sizeBreakdowns,
+ List<Map<Range, SourceInfo>> sourceInfoMaps) {
+ for (int i = 0; i < js.length; i++) {
+ DefaultTextOutput out = new DefaultTextOutput(
+ options.getOutput().shouldMinimize());
+ JsSourceGenerationVisitorWithSizeBreakdown v;
+ if (sourceInfoMaps != null) {
+ v = new JsReportGenerationVisitor(out, jjsMap);
+ } else {
+ v = new JsSourceGenerationVisitorWithSizeBreakdown(out, jjsMap);
+ }
+ v.accept(jsProgram.getFragmentBlock(i));
+ js[i] = out.toString();
+ if (sizeBreakdowns != null) {
+ sizeBreakdowns[i] = v.getSizeBreakdown();
+ }
+ if (sourceInfoMaps != null) {
+ sourceInfoMaps.add(((JsReportGenerationVisitor) v).getSourceInfoMap());
+ }
+ ranges[i] = v.getStatementRanges();
+ }
+ }
+
private static UnableToCompleteException logAndTranslateException(
TreeLogger logger, Throwable e) {
if (e instanceof UnableToCompleteException) {
@@ -861,10 +891,13 @@
private static StandardCompilationAnalysis makeSoycArtifact(
TreeLogger logger, int permutationId, JProgram jprogram, String[] js,
- List<Map<Range, SourceInfo>> sourceInfoMaps, SoycArtifact dependencies) {
+ SizeBreakdown[] sizeBreakdowns,
+ List<Map<Range, SourceInfo>> sourceInfoMaps, SoycArtifact dependencies,
+ JavaToJavaScriptMap jjsmap, Map<JsName, String> obfuscateMap)
+ throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PerfLogger.start("Computing SOYC output");
+ PerfLogger.start("Recording SOYC output");
PerfLogger.start("Record split points");
SplitPointRecorder.recordSplitPoints(jprogram, baos, logger);
@@ -872,20 +905,32 @@
+ ".xml.gz", baos.toByteArray());
PerfLogger.end();
- SoycArtifact stories = null;
+ SoycArtifact sizeMaps = null;
+ SoycArtifact detailedStories = null;
+
+ if (sizeBreakdowns != null) {
+ PerfLogger.start("Record size map");
+ baos.reset();
+ SizeMapRecorder.recordMap(logger, baos, sizeBreakdowns, jjsmap,
+ obfuscateMap);
+ sizeMaps = new SoycArtifact("stories" + permutationId + ".xml.gz",
+ baos.toByteArray());
+ PerfLogger.end();
+ }
if (sourceInfoMaps != null) {
- PerfLogger.start("Record stories");
+ PerfLogger.start("Record detailed stories");
baos.reset();
StoryRecorder.recordStories(logger, baos, sourceInfoMaps, js);
- stories = new SoycArtifact("stories" + permutationId + ".xml.gz",
- baos.toByteArray());
+ detailedStories = new SoycArtifact("detailedStories" + permutationId
+ + ".xml.gz", baos.toByteArray());
PerfLogger.end();
}
PerfLogger.end();
- return new StandardCompilationAnalysis(dependencies, stories, splitPoints);
+ return new StandardCompilationAnalysis(dependencies, sizeMaps, splitPoints,
+ detailedStories);
}
/**
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
index 864be36..5ac8a58 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentExtractor.java
@@ -161,6 +161,29 @@
}
}
+ /**
+ * Return the Java method corresponding to <code>stat</code>, or
+ * <code>null</code> if there isn't one. It recognizes JavaScript of the form
+ * <code>function foo(...) { ...}</code>, where <code>foo</code> is the name
+ * of the JavaScript translation of a Java method.
+ */
+ public static JMethod methodFor(JsStatement stat, JavaToJavaScriptMap map) {
+ if (stat instanceof JsExprStmt) {
+ JsExpression exp = ((JsExprStmt) stat).getExpression();
+ if (exp instanceof JsFunction) {
+ JsFunction func = (JsFunction) exp;
+ if (func.getName() != null) {
+ JMethod method = map.nameToMethod(func.getName());
+ if (method != null) {
+ return method;
+ }
+ }
+ }
+ }
+
+ return map.vtableInitToMethod(stat);
+ }
+
private Set<JsName> entryMethodNames;
private final JProgram jprogram;
@@ -363,9 +386,6 @@
}
JMethod meth = methodFor(stat);
- if (meth == null) {
- meth = map.vtableInitToMethod(stat);
- }
if (meth != null) {
/*
@@ -411,16 +431,7 @@
* of the JavaScript translation of a Java method.
*/
private JMethod methodFor(JsStatement stat) {
- if (stat instanceof JsExprStmt) {
- JsExpression exp = ((JsExprStmt) stat).getExpression();
- if (exp instanceof JsFunction) {
- JsFunction func = (JsFunction) exp;
- if (func.getName() != null) {
- return map.nameToMethod(func.getName());
- }
- }
- }
- return null;
+ return methodFor(stat, map);
}
/**
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index 58b0ae3..4acb98f 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -1884,6 +1884,8 @@
*/
private Set<JMethod> crossClassTargets = new HashSet<JMethod>();
+ private Map<String, JsFunction> indexedFunctions = Maps.create();
+
/**
* Contains JsNames for all interface methods. A special scope is needed so
* that independent classes will obfuscate their interface implementation
@@ -1891,8 +1893,6 @@
*/
private final JsScope interfaceScope;
- private Map<String, JsFunction> indexedFunctions = Maps.create();
-
private final JsProgram jsProgram;
/**
@@ -2143,6 +2143,10 @@
return nameToMethodMap.get(name);
}
+ public JReferenceType nameToType(JsName name) {
+ return constructorNameToTypeMap.get(name);
+ }
+
public JReferenceType typeForStatement(JsStatement stat) {
return typeForStatMap.get(stat);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java
index 7a96d82..3a232b1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaToJavaScriptMap.java
@@ -49,6 +49,12 @@
JMethod nameToMethod(JsName name);
/**
+ * If <code>name</code> is the name of a constructor function corresponding to
+ * a Java type, then return that type. Otherwise, return <code>null</code>.
+ */
+ JReferenceType nameToType(JsName name);
+
+ /**
* If <code>stat</code> is used to set up the definition of some class, return
* that class. Otherwise, return null.
*/
diff --git a/dev/core/src/com/google/gwt/dev/js/JsReportGenerationVisitor.java b/dev/core/src/com/google/gwt/dev/js/JsReportGenerationVisitor.java
index b5c7180..acfda17 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsReportGenerationVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsReportGenerationVisitor.java
@@ -18,6 +18,7 @@
import com.google.gwt.core.ext.soyc.Range;
import com.google.gwt.dev.jjs.HasSourceInfo;
import com.google.gwt.dev.jjs.SourceInfo;
+import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.ast.JsVisitable;
import com.google.gwt.dev.util.TextOutput;
@@ -30,12 +31,12 @@
* A variation on the standard source generation visitor that records the
* locations of SourceInfo objects in the output.
*/
-public class JsReportGenerationVisitor extends JsSourceGenerationVisitor {
+public class JsReportGenerationVisitor extends JsSourceGenerationVisitorWithSizeBreakdown {
private final Map<Range, SourceInfo> sourceInfoMap = new HashMap<Range, SourceInfo>();
private final TextOutput out;
- public JsReportGenerationVisitor(TextOutput out) {
- super(out);
+ public JsReportGenerationVisitor(TextOutput out, JavaToJavaScriptMap map) {
+ super(out, map);
this.out = out;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java b/dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java
new file mode 100644
index 0000000..466ec4a
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2009 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.js;
+
+import com.google.gwt.dev.jjs.ast.JMethod;
+import com.google.gwt.dev.jjs.ast.JReferenceType;
+import com.google.gwt.dev.jjs.impl.FragmentExtractor;
+import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
+import com.google.gwt.dev.js.ast.JsBlock;
+import com.google.gwt.dev.js.ast.JsContext;
+import com.google.gwt.dev.js.ast.JsName;
+import com.google.gwt.dev.js.ast.JsProgram;
+import com.google.gwt.dev.js.ast.JsProgramFragment;
+import com.google.gwt.dev.js.ast.JsStatement;
+import com.google.gwt.dev.js.ast.JsVisitable;
+import com.google.gwt.dev.js.ast.JsVars.JsVar;
+import com.google.gwt.dev.util.TextOutput;
+import com.google.gwt.dev.util.collect.HashMap;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A version of {@link JsSourceGenerationVisitor} that records a
+ * {@link SizeBreakdown} as it goes.
+ */
+public class JsSourceGenerationVisitorWithSizeBreakdown extends
+ JsSourceGenerationVisitor {
+
+ private final JavaToJavaScriptMap map;
+ private JsName nameToBillTo;
+ private TextOutput out;
+ private final Map<JsName, Integer> sizeMap = new HashMap<JsName, Integer>();
+
+ public JsSourceGenerationVisitorWithSizeBreakdown(TextOutput out,
+ JavaToJavaScriptMap javaToJavaScriptMap) {
+ super(out);
+ this.out = out;
+ this.map = javaToJavaScriptMap;
+ }
+
+ public SizeBreakdown getSizeBreakdown() {
+ return new SizeBreakdown(out.getPosition(), sizeMap);
+ }
+
+ @Override
+ public boolean visit(JsBlock x, JsContext<JsStatement> ctx) {
+ printJsBlock(x, false, true);
+ return false;
+ }
+
+ @Override
+ public boolean visit(JsProgram x, JsContext<JsProgram> ctx) {
+ // Descend naturally.
+ return true;
+ }
+
+ @Override
+ public boolean visit(JsProgramFragment x, JsContext<JsProgramFragment> ctx) {
+ // Descend naturally.
+ return true;
+ }
+
+ @Override
+ protected <T extends JsVisitable<T>> T doAccept(T node) {
+ JsName newName = nameToBillTo(node);
+ if (newName == null) {
+ return super.doAccept(node);
+ } else {
+ JsName oldName = nameToBillTo;
+ nameToBillTo = newName;
+ int start = out.getPosition();
+ T retValue = super.doAccept(node);
+ billChars(nameToBillTo, out.getPosition() - start);
+ nameToBillTo = oldName;
+ return retValue;
+ }
+ }
+
+ @Override
+ protected <T extends JsVisitable<T>> void doAcceptList(List<T> collection) {
+ for (T t : collection) {
+ doAccept(t);
+ }
+ }
+
+ @Override
+ protected <T extends JsVisitable<T>> void doAcceptWithInsertRemove(
+ List<T> collection) {
+ for (T t : collection) {
+ doAccept(t);
+ }
+ }
+
+ private void billChars(JsName nameToBillTo, int chars) {
+ Integer oldSize = sizeMap.get(nameToBillTo);
+ if (oldSize == null) {
+ oldSize = 0;
+ }
+ sizeMap.put(nameToBillTo, oldSize + chars);
+ }
+
+ private JsName nameToBillTo(JsVisitable<?> node) {
+ if (node instanceof JsStatement) {
+ JsStatement stat = (JsStatement) node;
+ JReferenceType type = map.typeForStatement(stat);
+ if (type != null) {
+ return map.nameForType(type);
+ }
+
+ JMethod method = FragmentExtractor.methodFor(stat, map);
+ if (method != null) {
+ return map.nameForMethod(method);
+ }
+ }
+
+ if (node instanceof JsVar) {
+ if (nameToBillTo == null) {
+ return ((JsVar) node).getName();
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStringInterner.java b/dev/core/src/com/google/gwt/dev/js/JsStringInterner.java
index 415737a..126bd52 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStringInterner.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStringInterner.java
@@ -36,11 +36,13 @@
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
+import java.util.Map.Entry;
/**
* Interns all String literals in a JsProgram. Each unique String will be
@@ -191,14 +193,14 @@
}
}
+ public static final String PREFIX = "$intern_";
+
private static final Comparator<JsStringLiteral> LITERAL_COMPARATOR = new Comparator<JsStringLiteral>() {
public int compare(JsStringLiteral o1, JsStringLiteral o2) {
return o1.getValue().compareTo(o2.getValue());
}
};
- public static final String PREFIX = "$intern_";
-
/**
* Apply interning of String literals to a JsProgram. The symbol names for the
* interned strings will be defined within the program's top scope and the
@@ -208,8 +210,9 @@
* @param jprogram the JProgram that has fragment dependency data for
* <code>program</code>
* @param program the JsProgram
+ * @return a map describing the interning that occurred
*/
- public static void exec(JProgram jprogram, JsProgram program) {
+ public static Map<JsName, String> exec(JProgram jprogram, JsProgram program) {
StringVisitor v = new StringVisitor(jprogram, program.getScope());
v.accept(program);
@@ -227,6 +230,8 @@
createVars(program, program.getFragmentBlock(entry.getKey()),
entry.getValue(), v.toCreate);
}
+
+ return reverse(v.toCreate);
}
/**
@@ -267,6 +272,16 @@
}
}
+ private static Map<JsName, String> reverse(
+ SortedMap<JsStringLiteral, JsName> toCreate) {
+ Map<JsName, String> reversed = new LinkedHashMap<JsName, String>(
+ toCreate.size());
+ for (Entry<JsStringLiteral, JsName> entry : toCreate.entrySet()) {
+ reversed.put(entry.getValue(), entry.getKey().getValue());
+ }
+ return reversed;
+ }
+
/**
* Utility class.
*/
diff --git a/dev/core/src/com/google/gwt/dev/js/SizeBreakdown.java b/dev/core/src/com/google/gwt/dev/js/SizeBreakdown.java
new file mode 100644
index 0000000..29aaf0b
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/js/SizeBreakdown.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009 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.js;
+
+import com.google.gwt.dev.js.ast.JsName;
+
+import java.util.Map;
+
+/**
+ * A size breakdown of a single JavaScript code fragment.
+ */
+public class SizeBreakdown {
+ private final int size;
+ private final Map<JsName, Integer> sizeMap;
+
+ public SizeBreakdown(int size, Map<JsName, Integer> sizeMap) {
+ this.size = size;
+ this.sizeMap = sizeMap;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public Map<JsName, Integer> getSizeMap() {
+ return sizeMap;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerSoycDetailed.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerSoycDetailed.java
new file mode 100644
index 0000000..d8b78c9
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerSoycDetailed.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 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.util.arg;
+
+import com.google.gwt.util.tools.ArgHandlerFlag;
+
+/**
+ * An ArgHandler that enables detailed Story Of Your Compile data collection.
+ */
+public class ArgHandlerSoycDetailed extends ArgHandlerFlag {
+ private final OptionSoycDetailed options;
+
+ public ArgHandlerSoycDetailed(OptionSoycDetailed options) {
+ this.options = options;
+ }
+
+ @Override
+ public String getPurpose() {
+ return "Emit extra, detailed SOYC information at the expense of compile time";
+ }
+
+ @Override
+ public String getTag() {
+ return "-XsoycDetailed";
+ }
+
+ @Override
+ public boolean isUndocumented() {
+ return true;
+ }
+
+ @Override
+ public boolean setFlag() {
+ options.setSoycExtra(true);
+ return true;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/OptionSoycDetailed.java b/dev/core/src/com/google/gwt/dev/util/arg/OptionSoycDetailed.java
new file mode 100644
index 0000000..6ab0217
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/util/arg/OptionSoycDetailed.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009 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.util.arg;
+
+/**
+ * Option to request extra SOYC output at the expense of more compile time.
+ */
+public interface OptionSoycDetailed {
+
+ /**
+ * Returns true if the compiler should record and emit extra SOYC information.
+ */
+ boolean isSoycExtra();
+
+ /**
+ * Sets whether or not the compiler should record and emit extra SOYC
+ * information.
+ */
+ void setSoycExtra(boolean soycExtra);
+}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java b/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java
index b05fead..3b9b451 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java
@@ -25,20 +25,15 @@
public class CodeCollection {
public TreeSet<String> classes = new TreeSet<String>();
- public String codeType = "";
public float cumPartialSize = 0f;
public int cumSize = 0;
public TreeSet<String> stories = new TreeSet<String>();
- public CodeCollection(String type) {
- codeType = type;
- }
-
public float getCumPartialSize(SizeBreakdown breakdown) {
cumPartialSize = 0f;
for (String className : classes) {
- if (breakdown.classToPartialSize.containsKey(className)) {
- cumPartialSize += breakdown.classToPartialSize.get(className);
+ if (breakdown.classToSize.containsKey(className)) {
+ cumPartialSize += breakdown.classToSize.get(className);
}
}
return cumPartialSize;
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java b/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java
index 0465d4c..3f18afa 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java
@@ -30,29 +30,19 @@
public class GlobalInformation {
private static final SizeBreakdown[] EMPTY_SIZE_BREAKDOWN = new SizeBreakdown[0];
- public static String backupLocation = "(Source location not known)";
-
public static Boolean displayDependencies = false;
public static Boolean displaySplitPoints = false;
public static HashMap<String, String> classToPackage = new HashMap<String, String>();
- public static HashMap<String, HashSet<String>> classToWhatItDependsOn = new HashMap<String, HashSet<String>>();
- public static HashMap<Integer, Float> fragmentToPartialSize = new HashMap<Integer, Float>();
- public static HashMap<Integer, HashSet<String>> fragmentToStories = new HashMap<Integer, HashSet<String>>();
-
- public static int numBytesDoubleCounted = 0;
- public static int numFragments = 0;
- public static int numSplitPoints = 0;
public static Map<String, TreeSet<String>> packageToClasses = new TreeMap<String, TreeSet<String>>();
+ public static HashMap<String, HashSet<String>> classToWhatItDependsOn = new HashMap<String, HashSet<String>>();
+
+ public static int numSplitPoints = 0;
+
public static HashMap<Integer, String> splitPointToLocation = new HashMap<Integer, String>();
public static ArrayList<Integer> splitPointInitialLoadSequence = new ArrayList<Integer>();
- public static HashMap<String, HashSet<String>> storiesToCorrClasses = new HashMap<String, HashSet<String>>();
- public static HashMap<String, HashSet<String>> storiesToCorrClassesAndMethods = new HashMap<String, HashSet<String>>();
-
- public static HashMap<String, String> storiesToLitType = new HashMap<String, String>();
-
public static Settings settings = new Settings();
public static SizeBreakdown initialCodeBreakdown = new SizeBreakdown(
@@ -82,13 +72,6 @@
}
}
- public static void computePartialPackageSizes() {
- for (SizeBreakdown breakdown : allSizeBreakdowns()) {
- computePartialPackageSizes(breakdown.packageToPartialSize,
- breakdown.classToPartialSize);
- }
- }
-
public static SizeBreakdown splitPointCodeBreakdown(int sp) {
assert sp >= 1 && sp <= numSplitPoints;
if (!exclusiveCodeBreakdowns.containsKey(sp)) {
@@ -98,6 +81,9 @@
return exclusiveCodeBreakdowns.get(sp);
}
+ /**
+ * TODO(spoon) move this to the SizeBreakdown class.
+ */
private static void computePackageSizes(Map<String, Integer> packageToSize,
Map<String, Integer> classToSize) {
packageToSize.clear();
@@ -112,23 +98,4 @@
}
}
}
-
- private static void computePartialPackageSizes(
- Map<String, Float> packageToPartialSize,
- Map<String, Float> classToPartialSize) {
- float cumPartialSizeFromPackages = 0f;
-
- packageToPartialSize.clear();
- for (String packageName : packageToClasses.keySet()) {
- packageToPartialSize.put(packageName, 0f);
- for (String className : packageToClasses.get(packageName)) {
- if (classToPartialSize.containsKey(className)) {
- float curSize = classToPartialSize.get(className);
- cumPartialSizeFromPackages += curSize;
- float newSize = curSize + packageToPartialSize.get(packageName);
- packageToPartialSize.put(packageName, newSize);
- }
- }
- }
- }
}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/LiteralsCollection.java b/tools/soyc-vis/src/com/google/gwt/soyc/LiteralsCollection.java
index 36a984f..18f2747 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/LiteralsCollection.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/LiteralsCollection.java
@@ -16,41 +16,13 @@
package com.google.gwt.soyc;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.HashSet;
-import java.util.TreeMap;
+import java.util.Set;
+import java.util.TreeSet;
/**
* A collection of literals.
*/
public class LiteralsCollection {
- public int cumSize = 0;
- public int cumStringSize = 0;
- public String literalType = "";
- public Map<String, HashSet<String>> literalToLocations = new TreeMap<String, HashSet<String>>();
- public Map<String, HashSet<String>> storyToLocations = new HashMap<String, HashSet<String>>();
- public TreeMap<String, String> stringLiteralToType = new TreeMap<String, String>();
- public Map<String, Integer> stringTypeToSize = new HashMap<String, Integer>();
- public Map<String, Integer> stringTypeToCount = new HashMap<String, Integer>();
-
- public LiteralsCollection(String type) {
- literalType = type;
- }
-
- /**
- * Utility method.
- */
- public void printAllStrings() {
- int iSum = 0;
- System.out.println("--- now printing strings ---");
- for (String st : stringLiteralToType.keySet()) {
- int numBytes = st.getBytes().length;
- iSum += numBytes;
- System.out.println(st + "[" + numBytes + "]");
- }
- System.out.println("sum: " + iSum);
- System.out.println("--- done printing strings ---");
- }
-
+ public int size = 0;
+ public final Set<String> literals = new TreeSet<String>();
}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java b/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java
index 41caf9b..2116795 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java
@@ -43,12 +43,30 @@
* A utility to make the top level HTTML file for one permutation.
*/
public class MakeTopLevelHtmlForPerm {
+ /**
+ * A class that specifies the URL to which a class should be linked in a size
+ * breakdown. It is always either a dependencies page, an intermediate status
+ * page that itself links to dependencies pages, or <code>null</code>. If it's
+ * <code>null</code>, then no link should be created for the class.
+ */
+ public interface DependencyLinker {
+ String dependencyLinkForClass(String className);
+ }
+
+ /**
+ * A {@link DependencyLinker} for exclusive fragments. It doesn't link to any
+ * dependencies.
+ */
public class DependencyLinkerForExclusiveFragment implements DependencyLinker {
public String dependencyLinkForClass(String className) {
return null;
}
}
+ /**
+ * A {@link DependencyLinker} for the initially downloaded code. It links into
+ * the initial dependencies.
+ */
public class DependencyLinkerForInitialCode implements DependencyLinker {
public String dependencyLinkForClass(String className) {
String packageName = GlobalInformation.classToPackage.get(className);
@@ -57,22 +75,27 @@
}
}
+ /**
+ * A {@link DependencyLinker} for the leftovers fragment. It links a class to
+ * the leftovers status page for that class.
+ *
+ */
public class DependencyLinkerForLeftoversFragment implements DependencyLinker {
public String dependencyLinkForClass(String className) {
return leftoversStatusFileName(className);
}
}
+ /**
+ * A dependency linker for the size breakdown of the entire program. It links
+ * each class to a general split status page describing that class.
+ */
public class DependencyLinkerForTotalBreakdown implements DependencyLinker {
public String dependencyLinkForClass(String className) {
return splitStatusFileName(className);
}
}
- interface DependencyLinker {
- String dependencyLinkForClass(String className);
- }
-
/**
* By a convention shared with the compiler, the initial download is fragment
* number 0.
@@ -279,7 +302,7 @@
outFile.println("<body>");
int yOffset = 0;
- for (Float size : sortedCodeTypes.keySet()) {
+ for (float size : sortedCodeTypes.keySet()) {
String codeType = sortedCodeTypes.get(size);
String drillDownFileName = breakdown.getId() + "_" + codeType
@@ -306,7 +329,7 @@
int yOffsetText = yOffset + 8;
outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:5px;\">%.1f</div>\n", size);
+ + "px; left:5px;\">%d</div>\n", (int) size);
outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
+ "px; left:70px;\">%.1f", perc);
outFile.println("%</div>\n");
@@ -379,41 +402,26 @@
addHeaderWithBreakdownContext(breakdown, outFile);
outFile.println("</center>");
- outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
+ outFile.println(" <div style=\"width:100%; float:left; padding-top: 10px;\">");
outFile.println("<b>Package breakdown</b>");
outFile.println(" </div>");
- outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px; \">");
- outFile.println("<b>Code type breakdown</b>");
- outFile.println(" </div>");
- outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
+ outFile.println(" <div style=\"width:100%; float:left; padding-top: 10px;\">");
outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Package Name</div>");
outFile.println(" </div>");
- outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px;\">");
- outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
- outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Code Type</div>");
- outFile.println(" </div>");
-
String packageBreakdownFileName = makePackageHtml(breakdown);
- outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:left;\">");
+ outFile.println("<div style=\"height:35%; width:100%; margin:0 auto; background-color:white; float:left;\">");
outFile.println("<iframe src=\"" + packageBreakdownFileName
+ "\" width=100% height=100% scrolling=auto></iframe>");
outFile.println(" </div>");
- String codeTypeBreakdownFileName = makeCodeTypeHtml(breakdown,
- nameToCodeColl);
- outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:right;\">");
- outFile.println("<iframe src=\"" + codeTypeBreakdownFileName
- + "\" width=100% height=100% scrolling=auto></iframe>");
- outFile.println(" </div>");
-
outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
outFile.println("<b>Literals breakdown</b>");
outFile.println(" </div>");
outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px; \">");
- outFile.println("<b>String literals breakdown</b>");
+ outFile.println("<b>Code type breakdown</b>");
outFile.println(" </div>");
outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
@@ -423,7 +431,7 @@
outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px; \">");
outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
- outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">String Literal Type</div>");
+ outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Code Type</div>");
outFile.println(" </div>");
String literalsBreakdownFileName = makeLiteralsHtml(breakdown,
@@ -433,10 +441,10 @@
+ "\" width=100% height=100% scrolling=auto></iframe>");
outFile.println("</div>");
- String stringLiteralsBreakdownFileName = makeStringLiteralsHtml(breakdown,
- nameToLitColl);
+ String codeTypeBreakdownFileName = makeCodeTypeHtml(breakdown,
+ nameToCodeColl);
outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:right;\">");
- outFile.println("<iframe src=\"" + stringLiteralsBreakdownFileName
+ outFile.println("<iframe src=\"" + codeTypeBreakdownFileName
+ "\" width=100% height=100% scrolling=auto></iframe>");
outFile.println(" </div>");
@@ -459,11 +467,11 @@
Collections.reverseOrder());
for (String className : nameToCodeColl.get(codeType).classes) {
- if (breakdown.classToPartialSize.containsKey(className)) {
+ if (breakdown.classToSize.containsKey(className)) {
float curSize = 0f;
- if (breakdown.classToPartialSize.containsKey(className)) {
- curSize = breakdown.classToPartialSize.get(className);
+ if (breakdown.classToSize.containsKey(className)) {
+ curSize = breakdown.classToSize.get(className);
}
if (curSize != 0f) {
@@ -502,7 +510,7 @@
outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 120px; left:70px; position:absolute; background-color:white\"");
int yOffset = 0;
- for (Float size : sortedClasses.keySet()) {
+ for (float size : sortedClasses.keySet()) {
String className = sortedClasses.get(size);
@@ -526,7 +534,7 @@
int yOffsetText = yOffset + 8;
outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:5px;\">%.1f</div>\n", size);
+ + "px; left:5px;\">%d</div>\n", (int) size);
outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText
+ "px; left:70px;\">" + className + "</div>");
@@ -584,73 +592,29 @@
outFile.println("<center>");
outFile.println("<table border=\"1\" width=\"80%\" style=\"font-size: 11pt;\" bgcolor=\"white\">");
- for (String literal : nameToLitColl.get(literalType).literalToLocations.keySet()) {
-
- if ((literalType.compareTo("string") != 0)
- || (nameToLitColl.get("string").stringLiteralToType.get(literal).compareTo(
- "otherStrings") != 0)) {
-
- if (literal.trim().compareTo("") == 0) {
- literal = "[whitespace only string]";
+ for (String literal : nameToLitColl.get(literalType).literals) {
+ String newLiteral = "";
+ if (literal.length() > 80) {
+ int i;
+ for (i = 80; i < literal.length(); i = i + 80) {
+ String part1 = literal.substring(i - 80, i);
+ newLiteral = newLiteral + part1 + " ";
}
-
- String newLiteral = "";
- if (literal.length() > 80) {
- int i;
- for (i = 80; i < literal.length(); i = i + 80) {
- String part1 = literal.substring(i - 80, i);
- newLiteral = newLiteral + part1 + " ";
- }
- if (i - 80 > 0) {
- newLiteral = newLiteral + literal.substring(i - 80);
- }
- } else {
- newLiteral = literal;
+ if (i - 80 > 0) {
+ newLiteral = newLiteral + literal.substring(i - 80);
}
-
- String escliteral = escapeXml(newLiteral);
-
- outFile.println("<tr>");
- outFile.println("<td width=\"40%\">" + escliteral + "</td>");
-
- int ct = 0;
- if ((nameToLitColl.containsKey(literalType))
- && (nameToLitColl.get(literalType).literalToLocations.containsKey(literal))) {
- for (String location : nameToLitColl.get(literalType).literalToLocations.get(literal)) {
-
- if (ct > 0) {
- outFile.println("<tr>");
- outFile.println("<td width=\"40%\"> </td>");
- }
-
- String newLocation = "";
- if (location.length() > 80) {
- int i;
- for (i = 80; i < location.length(); i = i + 80) {
- String part1 = location.substring(i - 80, i);
- newLocation = newLocation + part1 + " ";
- }
- if (i - 80 > 0) {
- newLocation = newLocation + location.substring(i - 80);
- }
- } else {
- newLocation = location;
- }
-
- outFile.println("<td width=\"40%\">" + newLocation + "</td>");
-
- if (ct > 0) {
- outFile.println("</tr>");
- }
- ct++;
- }
- } else {
- System.err.println("either literalType " + literalType
- + " not known, or no location for literal " + literal);
- }
-
- outFile.println("</tr>");
+ } else {
+ newLiteral = literal;
}
+
+ if (newLiteral.trim().length() == 0) {
+ newLiteral = "[whitespace only string]";
+ }
+ String escliteral = escapeXml(newLiteral);
+
+ outFile.println("<tr>");
+ outFile.println("<td>" + escliteral + "</td>");
+ outFile.println("</tr>");
}
outFile.println("</table>");
@@ -677,10 +641,10 @@
for (String className : GlobalInformation.packageToClasses.get(packageName)) {
float curSize = 0f;
- if (!breakdown.classToPartialSize.containsKey(className)) {
+ if (!breakdown.classToSize.containsKey(className)) {
// This class not present in this code collection
} else {
- curSize = breakdown.classToPartialSize.get(className);
+ curSize = breakdown.classToSize.get(className);
}
int depCount = 0;
@@ -722,7 +686,7 @@
outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 120px; left:70px; position:absolute; background-color:white\"");
int yOffset = 0;
- for (Float size : sortedClasses.keySet()) {
+ for (float size : sortedClasses.keySet()) {
String className = sortedClasses.get(size);
@@ -774,7 +738,7 @@
int yOffsetText = yOffset + 8;
outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:5px;\">%.1f</div>\n", size);
+ + "px; left:5px;\">%d</div>\n", (int) size);
if (GlobalInformation.displayDependencies == true) {
String dependencyLink = depLinker.dependencyLinkForClass(className);
outFile.print("<div class=\"barlabel\" style=\"top:" + yOffsetText
@@ -811,121 +775,6 @@
}
}
- public void makeStringLiteralsClassesTableHtmls(SizeBreakdown breakdown)
- throws IOException {
- Map<String, LiteralsCollection> nameToLitColl = breakdown.nameToLitColl;
-
- for (String literalType : nameToLitColl.get("string").stringTypeToSize.keySet()) {
- String outFileName = literalType + "Strings.html";
- final PrintWriter outFile = new PrintWriter(getOutFile(breakdown.getId()
- + "_" + outFileName));
-
- String title = "Literals of type \"" + literalType + "\"";
- String header = headerLineForBreakdown(breakdown);
-
- addStandardHtmlProlog(outFile, title, header);
-
- if (literalType.compareTo("otherStrings") == 0) {
- outFile.println("<center>");
- outFile.println("(JavaScript variable names are not displayed.)");
- outFile.println("</center>");
- }
-
- else {
- outFile.println("<center>");
- outFile.println("<table border=\"1\" width=\"80%\" style=\"font-size: 11pt;\" bgcolor=\"white\">");
-
- for (String literal : nameToLitColl.get("string").stringLiteralToType.keySet()) {
-
- if (nameToLitColl.get("string").stringLiteralToType.get(literal).compareTo(
- literalType) == 0) {
-
- if (literal.trim().compareTo("") == 0) {
- literal = "[whitespace only string]";
- }
-
- String newLiteral = "";
- if (literal.length() > 80) {
- int i;
- for (i = 80; i < literal.length(); i = i + 80) {
- String part1 = literal.substring(i - 80, i);
- newLiteral = newLiteral + part1 + " ";
- }
- if (i - 80 > 0) {
- newLiteral = newLiteral + literal.substring(i - 80);
- }
- } else {
- newLiteral = literal;
- }
-
- String escliteral = escapeXml(newLiteral);
-
- outFile.println("<tr>");
- outFile.println("<td width=\"40%\">" + escliteral + "</td>");
-
- int ct = 0;
-
- if (nameToLitColl.get("string").literalToLocations.containsKey(literal)) {
-
- for (String location : nameToLitColl.get("string").literalToLocations.get(literal)) {
-
- if ((location.indexOf("Line 0") == -1)
- && (location.compareTo(GlobalInformation.backupLocation) != 0)) { // i.e.,
- // if
- // we
- // actually
- // know
- // the
- // location
- if (ct > 0) {
- outFile.println("<tr>");
- outFile.println("<td width=\"40%\"> </td>");
- }
-
- String newLocation = "";
- if (location.length() > 80) {
- int i;
- for (i = 80; i < location.length(); i = i + 80) {
- String part1 = location.substring(i - 80, i);
- newLocation = newLocation + part1 + " ";
- }
- if (i - 80 > 0) {
- newLocation = newLocation + location.substring(i - 80);
- }
- } else {
- newLocation = location;
- }
-
- outFile.println("<td width=\"40%\"> " + newLocation
- + " </td>");
-
- if (ct > 0) {
- outFile.println("</tr>");
- }
- ct++;
- }
- }
- if (ct == 0) {
- outFile.println("<td width=\"40%\"> "
- + GlobalInformation.backupLocation + " </td>");
- }
- } else {
- System.err.println("no location given for string literal: "
- + literal);
- }
- outFile.println("</tr>");
- }
- }
-
- outFile.println("</table>");
- outFile.println("<center>");
- }
-
- addStandardHtmlEnding(outFile);
- outFile.close();
- }
- }
-
public void makeTopLevelShell() throws IOException {
PrintWriter outFile = new PrintWriter(
getOutFile("SoycDashboard-index.html"));
@@ -947,7 +796,7 @@
outFile.println("<center>");
outFile.println("<h3>Story of Your Compile Dashboard</h3>");
outFile.println("<hr>");
- if (GlobalInformation.fragmentToStories.size() > 1) {
+ if (GlobalInformation.splitPointToLocation.size() > 1) {
outFile.println("<b>Initial download size: <span style=\"color:maroon\">"
+ GlobalInformation.initialCodeBreakdown.sizeAllCode
+ "</span></span></b>");
@@ -971,7 +820,7 @@
int outerHeight = 25 * numRows;
outFile.println("<div style=\"width:100%; margin:20px 0 20px 0; background-color:white;position:relative;height:"
+ outerHeight + "\">");
- float maxSize = GlobalInformation.totalCodeBreakdown.sizeAllCode;
+ int maxSize = GlobalInformation.totalCodeBreakdown.sizeAllCode;
int yOffset = 0;
for (int i = FRAGMENT_NUMBER_TOTAL_PROGRAM; i <= numSplitPoints + 1; i++) {
@@ -994,13 +843,8 @@
String drillDownFileName = shellFileName(breakdown);
String splitPointDescription = breakdown.getDescription();
- float size;
- if (i >= 0) {
- size = GlobalInformation.fragmentToPartialSize.get(i);
- } else {
- size = GlobalInformation.totalCodeBreakdown.sizeAllCode;
- }
- float ratio = (size / maxSize) * 79;
+ int size = breakdown.sizeAllCode;
+ float ratio = (1.0F * size / maxSize) * 79;
if (ratio < 3) {
ratio = 3;
}
@@ -1019,7 +863,7 @@
int yOffsetText = yOffset + 8;
outFile.printf("<div class=\"barlabel\" style=\"top: " + yOffsetText
- + "px; left:5px;\">%.1f</div>\n", size);
+ + "px; left:5px;\">%d</div>\n", size);
outFile.println("<div class=\"barlabel\" style=\"top: " + yOffsetText
+ "px; left:120px;\"><a href=\"" + drillDownFileName
+ "\" target=\"_top\">" + splitPointDescription + "</a></div>");
@@ -1181,7 +1025,7 @@
Collections.reverseOrder());
for (String literal : nameToLitColl.keySet()) {
- float curSize = nameToLitColl.get(literal).cumSize;
+ float curSize = nameToLitColl.get(literal).size;
sumSize += curSize;
if (curSize != 0f) {
@@ -1205,7 +1049,7 @@
outFile.println("<body>");
int yOffset = 0;
- for (Float size : sortedLitTypes.keySet()) {
+ for (float size : sortedLitTypes.keySet()) {
String literal = sortedLitTypes.get(size);
String drillDownFileName = breakdown.getId() + "_" + literal
@@ -1232,7 +1076,7 @@
int yOffsetText = yOffset + 8;
outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:5px;\">%.1f</div>\n", size);
+ + "px; left:5px;\">%d</div>\n", (int) size);
outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
+ "px; left:70px;\">%.1f", perc);
outFile.println("%</div>\n");
@@ -1252,8 +1096,8 @@
private String makePackageHtml(SizeBreakdown breakdown)
throws FileNotFoundException {
String outFileName = breakdown.getId() + "_" + "packageBreakdown.html";
- Map<String, Float> packageToPartialSize = breakdown.packageToPartialSize;
- TreeMap<Float, String> sortedPackages = new TreeMap<Float, String>(
+ Map<String, Integer> packageToPartialSize = breakdown.packageToSize;
+ TreeMap<Integer, String> sortedPackages = new TreeMap<Integer, String>(
Collections.reverseOrder());
float maxSize = 0f;
float sumSize = 0f;
@@ -1278,7 +1122,7 @@
outFile.println("<body>");
int yOffset = 0;
- for (Float size : sortedPackages.keySet()) {
+ for (int size : sortedPackages.keySet()) {
String packageName = sortedPackages.get(size);
String drillDownFileName = classesInPackageFileName(breakdown,
packageName);
@@ -1305,7 +1149,7 @@
int yOffsetText = yOffset + 8;
outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:5px;\">%.1f</div>\n", size);
+ + "px; left:5px;\">%d</div>\n", size);
outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
+ "px; left:70px;\">%.1f", perc);
outFile.println("%</div>\n");
@@ -1352,89 +1196,6 @@
out.close();
}
- private String makeStringLiteralsHtml(SizeBreakdown breakdown,
- Map<String, LiteralsCollection> nameToLitColl) throws IOException {
- String outFileName = breakdown.getId() + "_stringLiteralsBreakdown.html";
- final PrintWriter outFile = new PrintWriter(getOutFile(outFileName));
-
- outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
- outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
- outFile.println("<html>");
- outFile.println("<head>");
- outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
- outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">");
- outFile.println("</head>");
- outFile.println("<body>");
-
- if (nameToLitColl.get("string").stringTypeToSize.size() > 0) {
-
- float maxSize = 0f;
- float sumSize = 0f;
- TreeMap<Float, String> sortedStLitTypes = new TreeMap<Float, String>(
- Collections.reverseOrder());
-
- for (String stringLiteral : nameToLitColl.get("string").stringTypeToSize.keySet()) {
- float curSize = nameToLitColl.get("string").stringTypeToSize.get(stringLiteral);
- sumSize += curSize;
-
- if (curSize != 0f) {
- sortedStLitTypes.put(curSize, stringLiteral);
-
- if (curSize > maxSize) {
- maxSize = curSize;
- }
- }
- }
-
- int yOffset = 0;
- for (Float size : sortedStLitTypes.keySet()) {
-
- String stringLiteral = sortedStLitTypes.get(size);
- String drillDownFileName = breakdown.getId() + "_" + stringLiteral
- + "Strings.html";
-
- float ratio = (size / maxSize) * 79;
- float perc = (size / sumSize) * 100;
-
- if (ratio < 3) {
- ratio = 3;
- }
-
- outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: "
- + yOffset + "px; left: 110px;\">");
- outFile.println("<div id=\"lb\">");
- outFile.println("<div id=\"rb\">");
- outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
- outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
- outFile.println("<div id=\"content\">");
- outFile.println("</div>");
- outFile.println("</div></div></div></div>");
- outFile.println("</div></div></div></div>");
- outFile.println("</div>");
-
- int yOffsetText = yOffset + 8;
- outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:5px;\">%.1f</div>\n", size);
- outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:70px;\">%.1f", perc);
- outFile.println("%</div>\n");
- outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:110px;\"><a href=\"" + drillDownFileName
- + "\" target=\"_top\">" + stringLiteral + "</a></div>");
-
- yOffset = yOffset + 25;
- }
- } else {
- outFile.println("No string literals found for this application.");
- }
-
- outFile.println("</body>");
- outFile.println("</html>");
- outFile.close();
-
- return outFileName;
- }
-
/**
* Find which split points include code belonging to <code>className</code>.
*/
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/SizeBreakdown.java b/tools/soyc-vis/src/com/google/gwt/soyc/SizeBreakdown.java
index e260dd4..86b00b4 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/SizeBreakdown.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/SizeBreakdown.java
@@ -15,11 +15,8 @@
*/
package com.google.gwt.soyc;
-import com.google.gwt.dev.util.collect.HashSet;
-
import java.util.HashMap;
import java.util.Map;
-import java.util.Set;
import java.util.TreeMap;
/**
@@ -28,38 +25,34 @@
public class SizeBreakdown {
private static void initializeLiteralsCollection(
Map<String, LiteralsCollection> nameToLitColl) {
- nameToLitColl.put("long", new LiteralsCollection("long"));
- nameToLitColl.put("null", new LiteralsCollection("null"));
- nameToLitColl.put("class", new LiteralsCollection("class"));
- nameToLitColl.put("int", new LiteralsCollection("int"));
- nameToLitColl.put("string", new LiteralsCollection("string"));
- nameToLitColl.put("number", new LiteralsCollection("number"));
- nameToLitColl.put("boolean", new LiteralsCollection("boolean"));
- nameToLitColl.put("double", new LiteralsCollection("double"));
- nameToLitColl.put("char", new LiteralsCollection("char"));
- nameToLitColl.put("undefined", new LiteralsCollection("undefined"));
- nameToLitColl.put("float", new LiteralsCollection("float"));
+ nameToLitColl.put("long", new LiteralsCollection());
+ nameToLitColl.put("null", new LiteralsCollection());
+ nameToLitColl.put("class", new LiteralsCollection());
+ nameToLitColl.put("int", new LiteralsCollection());
+ nameToLitColl.put("string", new LiteralsCollection());
+ nameToLitColl.put("number", new LiteralsCollection());
+ nameToLitColl.put("boolean", new LiteralsCollection());
+ nameToLitColl.put("double", new LiteralsCollection());
+ nameToLitColl.put("char", new LiteralsCollection());
+ nameToLitColl.put("undefined", new LiteralsCollection());
+ nameToLitColl.put("float", new LiteralsCollection());
}
private static void initializeNameToCodeCollection(
HashMap<String, CodeCollection> nameToCodeColl) {
- nameToCodeColl.put("allOther", new CodeCollection("allOther"));
- nameToCodeColl.put("widget", new CodeCollection("widget"));
- nameToCodeColl.put("rpcUser", new CodeCollection("rpcUser"));
- nameToCodeColl.put("rpcGen", new CodeCollection("rpcGen"));
- nameToCodeColl.put("rpcGwt", new CodeCollection("rpcGwt"));
- nameToCodeColl.put("gwtLang", new CodeCollection("long"));
- nameToCodeColl.put("jre", new CodeCollection("jre"));
+ nameToCodeColl.put("allOther", new CodeCollection());
+ nameToCodeColl.put("widget", new CodeCollection());
+ nameToCodeColl.put("rpcUser", new CodeCollection());
+ nameToCodeColl.put("rpcGen", new CodeCollection());
+ nameToCodeColl.put("rpcGwt", new CodeCollection());
+ nameToCodeColl.put("gwtLang", new CodeCollection());
+ nameToCodeColl.put("jre", new CodeCollection());
}
- public Map<String, Float> classToPartialSize = new HashMap<String, Float>();
public Map<String, Integer> classToSize = new HashMap<String, Integer>();
- public Map<String, LiteralsCollection> nameToLitColl = new TreeMap<String, LiteralsCollection>();
- public int nonAttributedBytes = 0;
- public Set<String> nonAttributedStories = new HashSet<String>();;
- public Map<String, Float> packageToPartialSize = new HashMap<String, Float>();
- public Map<String, Integer> packageToSize = new HashMap<String, Integer>();
public HashMap<String, CodeCollection> nameToCodeColl = new HashMap<String, CodeCollection>();
+ public Map<String, LiteralsCollection> nameToLitColl = new TreeMap<String, LiteralsCollection>();
+ public Map<String, Integer> packageToSize = new HashMap<String, Integer>();
public int sizeAllCode;
@@ -87,7 +80,7 @@
public String getId() {
return id;
}
-
+
@Override
public String toString() {
return getId();
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java b/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java
index 95308a3..d4db8c9 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java
@@ -31,7 +31,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@@ -48,9 +47,17 @@
*/
public class SoycDashboard {
private static class FormatException extends RuntimeException {
+ public FormatException() {
+ super();
+ }
+
public FormatException(String message) {
super(message);
}
+
+ public FormatException(Throwable cause) {
+ super(cause);
+ }
}
public static void main(String[] args) {
@@ -113,7 +120,7 @@
*/
// make the parser handler
- DefaultHandler handler = parseXMLDocument();
+ DefaultHandler handler = parseXMLDocumentSizeMap();
// start parsing
SAXParserFactory factoryMain = SAXParserFactory.newInstance();
@@ -133,7 +140,6 @@
// now we need to aggregate numbers
GlobalInformation.computePackageSizes();
- GlobalInformation.computePartialPackageSizes();
// clean up the RPC categories
for (SizeBreakdown breakdown : GlobalInformation.allSizeBreakdowns()) {
@@ -172,6 +178,22 @@
}
}
+ private static Collection<SizeBreakdown> breakdownsForFragment(
+ Integer fragment) {
+ List<SizeBreakdown> breakdowns = new ArrayList<SizeBreakdown>();
+ breakdowns.add(GlobalInformation.totalCodeBreakdown);
+ if (fragment == 0) {
+ breakdowns.add(GlobalInformation.initialCodeBreakdown);
+ }
+ if (fragment == (GlobalInformation.numSplitPoints + 1)) {
+ breakdowns.add(GlobalInformation.leftoversBreakdown);
+ }
+ if (fragment >= 1 && fragment <= GlobalInformation.numSplitPoints) {
+ breakdowns.add(GlobalInformation.splitPointCodeBreakdown(fragment));
+ }
+ return breakdowns;
+ }
+
private static DependencyLinker chooseDependencyLinker(
MakeTopLevelHtmlForPerm makeTopLevelHtmlForPerm, SizeBreakdown breakdown) {
if (breakdown == GlobalInformation.totalCodeBreakdown) {
@@ -228,520 +250,10 @@
makeTopLevelHtmlForPerm.makePackageClassesHtmls(breakdown, depLinker);
makeTopLevelHtmlForPerm.makeCodeTypeClassesHtmls(breakdown);
makeTopLevelHtmlForPerm.makeLiteralsClassesTableHtmls(breakdown);
- makeTopLevelHtmlForPerm.makeStringLiteralsClassesTableHtmls(breakdown);
makeTopLevelHtmlForPerm.makeBreakdownShell(breakdown);
makeTopLevelHtmlForPerm.makeTopLevelShell();
}
- private static DefaultHandler parseXMLDocument() {
- DefaultHandler handler = new DefaultHandler() {
- String curClassId;
- Integer curFragment;
- String curLineNumber;
- String curLocation;
- HashSet<String> curRelevantCodeTypes = new HashSet<String>();
- HashSet<String> curRelevantLitTypes = new HashSet<String>();
- String curStoryId;
- String curStoryLiteralType;
- String curStoryRef;
- boolean specialCodeType = false;
- StringBuilder valueBuilder = new StringBuilder();
-
- /**
- * This method collects a block of the value of the current XML node that
- * the SAX parser parses. It simply adds to the the previous blocks, so
- * that we can collect the entire value block.
- */
- @Override
- public void characters(char ch[], int start, int length) {
- valueBuilder.append(ch, start, length);
- }
-
- /**
- * This method marks the end of an XML element that the SAX parser parses.
- * It has access to the full value of the node and uses it to add
- * information to the relevant literal or code collections.
- *
- * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
- * java.lang.String, java.lang.String)
- */
- @Override
- public void endElement(String nsUri, String strippedName, String qName) {
-
- if (strippedName.compareTo("storyref") == 0) {
- String value = valueBuilder.toString();
-
- int numBytes = currentStorySize();
- if (curStoryRef != null) {
- if (!GlobalInformation.fragmentToPartialSize.containsKey(curFragment)) {
- GlobalInformation.fragmentToPartialSize.put(curFragment,
- (float) numBytes);
- } else {
- float newSize = GlobalInformation.fragmentToPartialSize.get(curFragment)
- + numBytes;
- GlobalInformation.fragmentToPartialSize.put(curFragment, newSize);
- }
-
- for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
- breakdown.sizeAllCode += numBytes;
- }
-
- // add this size to the classes associated with it
- if (GlobalInformation.storiesToCorrClasses.containsKey(curStoryRef)) {
-
- if ((GlobalInformation.storiesToLitType.containsKey(curStoryRef))
- && (GlobalInformation.storiesToCorrClasses.get(curStoryRef).size() > 0)) {
- GlobalInformation.numBytesDoubleCounted += numBytes;
- }
-
- for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
- accountForCurrentStory(breakdown.nameToCodeColl, breakdown);
- }
- }
-
- for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
- updateLitTypes(breakdown.nameToLitColl, value, numBytes);
- }
- }
- }
- }
-
- /**
- * This method deals with the beginning of the XML element. It analyzes
- * the XML node and adds its information to the relevant literal or code
- * collection for later analysis.
- *
- * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
- * java.lang.String, java.lang.String, org.xml.sax.Attributes)
- */
- @Override
- public void startElement(String nsUri, String strippedName,
- String tagName, Attributes attributes) {
- valueBuilder.delete(0, valueBuilder.length());
-
- if (strippedName.compareTo("story") == 0) {
- parseStory(attributes);
- } else if (strippedName.compareTo("of") == 0) {
- for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
- parseOverrides(breakdown.nameToCodeColl, attributes);
- }
- } else if (strippedName.compareTo("by") == 0) {
- for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
- parseCorrelations(breakdown.nameToCodeColl, attributes);
- }
- } else if (strippedName.compareTo("origin") == 0) {
- for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
- parseOrigins(breakdown.nameToLitColl, attributes);
- }
- } else if (strippedName.compareTo("js") == 0) {
- if (attributes.getValue("fragment") != null) {
- curFragment = Integer.parseInt(attributes.getValue("fragment"));
- } else {
- curFragment = -2;
- }
- } else if (strippedName.compareTo("storyref") == 0) {
- for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
- parseJs(breakdown.nameToLitColl, breakdown.nameToCodeColl,
- attributes, curFragment);
- }
- }
- }
-
- private void accountForCurrentStory(
- final HashMap<String, CodeCollection> nameToCodeColl,
- SizeBreakdown breakdown) {
- int storySize = currentStorySize();
- if ((!GlobalInformation.storiesToLitType.containsKey(curStoryRef))
- && (!GlobalInformation.storiesToCorrClasses.containsKey(curStoryRef))) {
- breakdown.nonAttributedStories.add(curStoryRef);
- breakdown.nonAttributedBytes += storySize;
- }
-
- // go through all the classes for this story
- for (String className : GlobalInformation.storiesToCorrClasses.get(curStoryRef)) {
- // get the corresponding package
-
- String packageName = "";
-
- if (!GlobalInformation.classToPackage.containsKey(className)) {
- // derive the package name from the class
- packageName = className;
- packageName = packageName.replaceAll("\\.[A-Z].*", "");
- GlobalInformation.classToPackage.put(className, packageName);
- } else {
- packageName = GlobalInformation.classToPackage.get(className);
- }
- parseClass(nameToCodeColl, className, packageName);
-
- if (!GlobalInformation.packageToClasses.containsKey(packageName)) {
- TreeSet<String> insertSet = new TreeSet<String>();
- insertSet.add(className);
- GlobalInformation.packageToClasses.put(packageName, insertSet);
- } else {
- GlobalInformation.packageToClasses.get(packageName).add(className);
- }
-
- if (breakdown.classToSize.containsKey(className)) {
- int newSize = breakdown.classToSize.get(className) + storySize;
- breakdown.classToSize.put(className, newSize);
- } else {
- breakdown.classToSize.put(className, storySize);
- }
-
- if (breakdown.classToPartialSize.containsKey(className)) {
- float newSize = breakdown.classToPartialSize.get(className)
- + currentStoryPartialSize();
- breakdown.classToPartialSize.put(className, newSize);
- } else {
- breakdown.classToPartialSize.put(className,
- currentStoryPartialSize());
- }
- }
- }
-
- private Collection<SizeBreakdown> breakdownsForCurFragment() {
- List<SizeBreakdown> breakdowns = new ArrayList<SizeBreakdown>();
- breakdowns.add(GlobalInformation.totalCodeBreakdown);
- if (curFragment == 0) {
- breakdowns.add(GlobalInformation.initialCodeBreakdown);
- }
- if (curFragment == (GlobalInformation.numSplitPoints + 1)) {
- breakdowns.add(GlobalInformation.leftoversBreakdown);
- }
- if (curFragment >= 1 && curFragment <= GlobalInformation.numSplitPoints) {
- breakdowns.add(GlobalInformation.splitPointCodeBreakdown(curFragment));
- }
- return breakdowns;
- }
-
- private float currentStoryPartialSize() {
- return (float) currentStorySize()
- / (float) GlobalInformation.storiesToCorrClasses.get(curStoryRef).size();
- }
-
- private int currentStorySize() {
- return valueBuilder.toString().getBytes().length;
- }
-
- /*
- * parses the "class" portion of the XML file
- */
- private void parseClass(
- final HashMap<String, CodeCollection> nameToCodeColl,
- String curClassId, String curPackage) {
- // if (attributes.getValue("id") != null) {
- // curClassId = attributes.getValue("id");
-
- // GlobalInformation.classToPackage.put(curClassId, curPackage);
-
- if (curPackage.startsWith("java")) {
- nameToCodeColl.get("jre").classes.add(curClassId);
- } else if (curPackage.startsWith("com.google.gwt.lang")) {
- nameToCodeColl.get("gwtLang").classes.add(curClassId);
- }
- if (curClassId.contains("_CustomFieldSerializer")) {
- nameToCodeColl.get("rpcUser").classes.add(curClassId);
- } else if (curClassId.endsWith("_FieldSerializer")
- || curClassId.endsWith("_Proxy")
- || curClassId.endsWith("_TypeSerializer")) {
- nameToCodeColl.get("rpcGen").classes.add(curClassId);
- }
- // }
- }
-
- /*
- * parses the "correlations" portion of the XML file
- */
- private void parseCorrelations(
- final HashMap<String, CodeCollection> nameToCodeColl,
- Attributes attributes) {
-
- if (attributes.getValue("idref") != null) {
-
- String corrClassOrMethod = attributes.getValue("idref");
- String corrClass = attributes.getValue("idref");
-
- if (corrClass.contains(":")) {
- corrClass = corrClass.replaceAll(":.*", "");
- }
-
- if (!GlobalInformation.storiesToCorrClassesAndMethods.containsKey(curStoryId)) {
- HashSet<String> insertSet = new HashSet<String>();
- insertSet.add(corrClassOrMethod);
- GlobalInformation.storiesToCorrClassesAndMethods.put(curStoryId,
- insertSet);
- } else {
- GlobalInformation.storiesToCorrClassesAndMethods.get(curStoryId).add(
- corrClassOrMethod);
- }
-
- if (!GlobalInformation.storiesToCorrClasses.containsKey(curStoryId)) {
- HashSet<String> insertSet = new HashSet<String>();
- insertSet.add(corrClass);
- GlobalInformation.storiesToCorrClasses.put(curStoryId, insertSet);
- } else {
- GlobalInformation.storiesToCorrClasses.get(curStoryId).add(
- corrClass);
- }
-
- for (String codeType : nameToCodeColl.keySet()) {
- if (nameToCodeColl.get(codeType).classes.contains(corrClass)) {
- nameToCodeColl.get(codeType).stories.add(curStoryId);
- }
- }
- }
- }
-
- /*
- * parses the "JS" portion of the XML file
- */
- private void parseJs(final Map<String, LiteralsCollection> nameToLitColl,
- final HashMap<String, CodeCollection> nameToCodeColl,
- Attributes attributes, Integer curFragment) {
- curRelevantLitTypes.clear();
- curRelevantCodeTypes.clear();
-
- if (attributes.getValue("idref") != null) {
-
- curStoryRef = attributes.getValue("idref");
-
- if (curFragment != -1) {
- // add this to the stories for this fragment
- if (!GlobalInformation.fragmentToStories.containsKey(curFragment)) {
- HashSet<String> insertSet = new HashSet<String>();
- insertSet.add(curStoryRef);
- GlobalInformation.fragmentToStories.put(curFragment, insertSet);
- } else {
- GlobalInformation.fragmentToStories.get(curFragment).add(
- curStoryRef);
- }
- }
-
- for (String litType : nameToLitColl.keySet()) {
- if (nameToLitColl.get(litType).storyToLocations.containsKey(curStoryRef)) {
- curRelevantLitTypes.add(litType);
- }
- }
-
- specialCodeType = false;
- for (String codeType : nameToCodeColl.keySet()) {
- if (nameToCodeColl.get(codeType).stories.contains(curStoryRef)) {
- curRelevantCodeTypes.add(codeType);
- specialCodeType = true;
- }
- }
- if (specialCodeType == false) {
-
- nameToCodeColl.get("allOther").stories.add(curStoryRef);
- curRelevantCodeTypes.add("allOther");
- }
- }
- }
-
- /*
- * parses the "origins" portion of the XML file
- */
- private void parseOrigins(
- final Map<String, LiteralsCollection> nameToLitColl,
- Attributes attributes) {
- if ((curStoryLiteralType.compareTo("") != 0)
- && (attributes.getValue("lineNumber") != null)
- && (attributes.getValue("location") != null)) {
- curLineNumber = attributes.getValue("lineNumber");
- curLocation = attributes.getValue("location");
- String curOrigin = curLocation + ": Line " + curLineNumber;
-
- if (!nameToLitColl.get(curStoryLiteralType).storyToLocations.containsKey(curStoryId)) {
- HashSet<String> insertSet = new HashSet<String>();
- insertSet.add(curOrigin);
- nameToLitColl.get(curStoryLiteralType).storyToLocations.put(
- curStoryId, insertSet);
- } else {
- nameToLitColl.get(curStoryLiteralType).storyToLocations.get(
- curStoryId).add(curOrigin);
- }
- }
- }
-
- /*
- * parses the "overrides" portion of the XML file
- */
- private void parseOverrides(
- final HashMap<String, CodeCollection> nameToCodeColl,
- Attributes attributes) {
- if (attributes.getValue("idref") != null) {
- String overriddenClass = attributes.getValue("idref");
-
- // we either generalize to classes, or the
- // numbers are messed up...
- if (overriddenClass.contains(":")) {
- overriddenClass = overriddenClass.replaceAll(":.*", "");
- }
-
- if (overriddenClass.compareTo("com.google.gwt.user.client.ui.UIObject") == 0) {
- nameToCodeColl.get("widget").classes.add(curClassId);
- } else if (overriddenClass.contains("java.io.Serializable")
- || overriddenClass.contains("IsSerializable")) {
- nameToCodeColl.get("rpcUser").classes.add(curClassId);
- } else if (overriddenClass.contains("com.google.gwt.user.client.rpc.core.java")) {
- nameToCodeColl.get("rpcGwt").classes.add(curClassId);
- }
- }
- }
-
- /*
- * parses the "story" portion of the XML file
- */
- private void parseStory(Attributes attributes) {
- if (attributes.getValue("id") != null) {
- curStoryId = attributes.getValue("id");
- if (attributes.getValue("literal") != null) {
- curStoryLiteralType = attributes.getValue("literal");
- GlobalInformation.storiesToLitType.put(curStoryId,
- curStoryLiteralType);
- for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
- if (!breakdown.nameToLitColl.get(curStoryLiteralType).storyToLocations.containsKey(curStoryId)) {
- HashSet<String> insertSet = new HashSet<String>();
- breakdown.nameToLitColl.get(curStoryLiteralType).storyToLocations.put(
- curStoryId, insertSet);
- }
- }
- } else {
- curStoryLiteralType = "";
- }
- }
- }
-
- /*
- * This method assigns strings to the appropriate category
- */
- private void updateLitTypes(
- final Map<String, LiteralsCollection> nameToLitColl, String value,
- int numBytes) {
-
- int iNumCounted = 0;
-
- for (String relLitType : curRelevantLitTypes) {
- iNumCounted++;
-
- // then give string literals special treatment
- if (relLitType.compareTo("string") == 0) {
-
- // note that this will double-count (i.e., it will count a string
- // twice if it's in the output twice), as it should.
- nameToLitColl.get("string").cumStringSize += numBytes;
- nameToLitColl.get(relLitType).cumSize += numBytes;
-
- // get the origins
- HashSet<String> originSet = nameToLitColl.get("string").storyToLocations.get(curStoryRef);
-
- // find the most appropriate string literal category
- String mostAppropriateCategory = "";
- String mostAppropriateLocation = "";
- String backupLocation = "";
- for (String origin : originSet) {
-
- if ((origin.contains("ClassLiteralHolder"))
- && (mostAppropriateCategory.compareTo("") == 0)) {
- mostAppropriateCategory = "compiler";
- mostAppropriateLocation = origin;
- } else if ((origin.startsWith("transient source for"))
- && (origin.contains("_TypeSerializer"))
- && (mostAppropriateCategory.compareTo("") == 0)) {
- mostAppropriateCategory = "transient";
- mostAppropriateLocation = origin;
- } else if ((origin.contains("InlineResourceBundleGenerator"))
- && (mostAppropriateCategory.compareTo("") == 0)) {
- mostAppropriateCategory = "inlinedTextRes";
- mostAppropriateLocation = origin;
- }
- if (origin.compareTo("com.google.gwt.dev.js.ast.JsProgram: Line 0") != 0) {
- backupLocation = origin;
- }
- }
-
- if (backupLocation.compareTo("") == 0) {
- backupLocation = GlobalInformation.backupLocation;
- }
- if ((((value.startsWith("'")) && (value.endsWith("'"))) || ((value.startsWith("\"")) && (value.endsWith("\""))))
- && (mostAppropriateCategory.compareTo("") == 0)) {
- mostAppropriateCategory = "user";
- mostAppropriateLocation = backupLocation;
- } else if (mostAppropriateCategory.compareTo("") == 0) {
- mostAppropriateCategory = "otherStrings";
- mostAppropriateLocation = backupLocation;
- }
-
- if (!nameToLitColl.get("string").stringLiteralToType.containsKey(value)) {
- nameToLitColl.get("string").stringLiteralToType.put(value,
- mostAppropriateCategory);
- if (!nameToLitColl.get("string").stringTypeToCount.containsKey(mostAppropriateCategory)) {
- nameToLitColl.get("string").stringTypeToCount.put(
- mostAppropriateCategory, 1);
- } else {
- int iNewCount = nameToLitColl.get("string").stringTypeToCount.get(mostAppropriateCategory) + 1;
- nameToLitColl.get("string").stringTypeToCount.put(
- mostAppropriateCategory, iNewCount);
- }
-
- int iNewSize = numBytes;
- if (nameToLitColl.get("string").stringTypeToSize.containsKey(mostAppropriateCategory)) {
- iNewSize += nameToLitColl.get("string").stringTypeToSize.get(mostAppropriateCategory);
- }
- nameToLitColl.get("string").stringTypeToSize.put(
- mostAppropriateCategory, iNewSize);
-
- if (nameToLitColl.get("string").storyToLocations.containsKey(curStoryRef)) {
- HashSet<String> insertSet = new HashSet<String>();
- insertSet.add(mostAppropriateLocation);
- nameToLitColl.get(relLitType).literalToLocations.put(value,
- insertSet);
- }
- }
- } else {
- // note that this will double-count (i.e., it will count a literal
- // twice if it's in the output twice), as it should.
- nameToLitColl.get(relLitType).cumSize += numBytes;
-
- if (nameToLitColl.get(relLitType).storyToLocations.containsKey(curStoryRef)) {
- if (nameToLitColl.get(relLitType).literalToLocations.containsKey(value)) {
- nameToLitColl.get(relLitType).literalToLocations.get(value).addAll(
- nameToLitColl.get(relLitType).storyToLocations.get(curStoryRef));
- } else {
- HashSet<String> insertSet = nameToLitColl.get(relLitType).storyToLocations.get(curStoryRef);
- nameToLitColl.get(relLitType).literalToLocations.put(value,
- insertSet);
- }
- }
- }
- }
- }
-
- /*
- * parses the "depends on" portion of the XML file
- */
- /*
- * private void parseDependsOn( final HashMap<String, CodeCollection>
- * nameToCodeColl, Attributes attributes) { if
- * (curFunctionId.compareTo("") == 0) { if (attributes.getValue("idref")
- * != null) { String curDepClassId = attributes.getValue("idref");
- *
- * if (curDepClassId.contains(":")) { // strip everything after the :: (to
- * get to class, even if it's a // method) curDepClassId =
- * curDepClassId.replaceAll(":.*", ""); }
- *
- * if (curDepClassId.contains(".")) { if
- * (!GlobalInformation.classToWhatItDependsOn.containsKey(curClassId)) {
- * HashSet<String> insertSet = new HashSet<String>();
- * insertSet.add(curDepClassId);
- * GlobalInformation.classToWhatItDependsOn.put(curClassId, insertSet); }
- * else { GlobalInformation.classToWhatItDependsOn.get(curClassId).add(
- * curDepClassId); } } } } }
- */
- };
- return handler;
- }
-
private static DefaultHandler parseXMLDocumentDependencies(
final Map<String, Map<String, String>> allDependencies) {
DefaultHandler handler = new DefaultHandler() {
@@ -799,6 +311,143 @@
return handler;
}
+ private static DefaultHandler parseXMLDocumentSizeMap() {
+ return new DefaultHandler() {
+ int fragment = -1;
+
+ @Override
+ public void endElement(String uri, String localName, String qName) {
+ if (localName.compareTo("sizemap") == 0) {
+ fragment = -1;
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) {
+ if (localName.compareTo("sizemap") == 0) {
+ // starting a new size map
+ String fragString = attributes.getValue("fragment");
+ if (fragString == null) {
+ throw new FormatException();
+ }
+ try {
+ fragment = Integer.valueOf(fragString);
+ } catch (NumberFormatException e) {
+ throw new FormatException(e);
+ }
+ String sizeString = attributes.getValue("size");
+ if (sizeString == null) {
+ throw new FormatException();
+ }
+ int size;
+ try {
+ size = Integer.valueOf(sizeString);
+ } catch (NumberFormatException e) {
+ throw new FormatException(e);
+ }
+ for (SizeBreakdown breakdown : breakdownsForFragment(fragment)) {
+ breakdown.sizeAllCode += size;
+ }
+ } else if (localName.compareTo("size") == 0) {
+ String type = attributes.getValue("type");
+ if (type == null) {
+ throw new FormatException();
+ }
+ String ref = attributes.getValue("ref");
+ if (ref == null) {
+ throw new FormatException();
+ }
+ String sizeString = attributes.getValue("size");
+ if (sizeString == null) {
+ throw new FormatException();
+ }
+ int size;
+ try {
+ size = Integer.valueOf(sizeString);
+ } catch (NumberFormatException e) {
+ throw new FormatException(e);
+ }
+ recordSize(type, ref, size);
+ }
+ }
+
+ private void accountForSize(SizeBreakdown breakdown, String refType,
+ String ref, int size) {
+ if (refType.equals("string")) {
+ LiteralsCollection stringLiterals = breakdown.nameToLitColl.get("string");
+ stringLiterals.size += size;
+ stringLiterals.literals.add(ref);
+ } else if (refType.equals("var")) {
+ // Nothing to record, because no breakdown is provided for random
+ // variables
+ } else {
+ if (!refType.equals("type") && !refType.equals("method")) {
+ throw new FormatException();
+ }
+ String className = ref;
+ if (className.contains("::")) {
+ /*
+ * It's a method reference. Discard the method part.
+ */
+ int idx = className.indexOf(':');
+ className = className.substring(0, idx);
+ }
+
+ // derive the package name from the class
+ String packageName;
+ if (!GlobalInformation.classToPackage.containsKey(className)) {
+ packageName = className;
+ packageName = packageName.replaceAll("\\.[A-Z].*", "");
+ GlobalInformation.classToPackage.put(className, packageName);
+ } else {
+ packageName = GlobalInformation.classToPackage.get(className);
+ }
+ if (!GlobalInformation.packageToClasses.containsKey(packageName)) {
+ TreeSet<String> insertSet = new TreeSet<String>();
+ insertSet.add(className);
+ GlobalInformation.packageToClasses.put(packageName, insertSet);
+ } else {
+ GlobalInformation.packageToClasses.get(packageName).add(className);
+ }
+
+ recordClassCategories(breakdown.nameToCodeColl, className,
+ packageName);
+
+ if (breakdown.classToSize.containsKey(className)) {
+ int newSize = breakdown.classToSize.get(className) + size;
+ breakdown.classToSize.put(className, newSize);
+ } else {
+ breakdown.classToSize.put(className, size);
+ }
+ }
+ }
+
+ private void recordClassCategories(
+ final HashMap<String, CodeCollection> nameToCodeColl,
+ String className, String packageName) {
+ if (packageName.startsWith("java")) {
+ nameToCodeColl.get("jre").classes.add(className);
+ } else if (packageName.startsWith("com.google.gwt.lang")) {
+ nameToCodeColl.get("gwtLang").classes.add(className);
+ }
+ if (className.contains("_CustomFieldSerializer")) {
+ nameToCodeColl.get("rpcUser").classes.add(className);
+ } else if (className.endsWith("_FieldSerializer")
+ || className.endsWith("_Proxy")
+ || className.endsWith("_TypeSerializer")) {
+ nameToCodeColl.get("rpcGen").classes.add(className);
+ }
+ }
+
+ private void recordSize(String refType, String ref, int size) {
+ for (SizeBreakdown breakdown : breakdownsForFragment(fragment)) {
+ accountForSize(breakdown, refType, ref, size);
+ }
+ }
+ };
+ }
+
private static DefaultHandler parseXMLDocumentSplitPoints() {
DefaultHandler handler = new DefaultHandler() {