Skip to content
This repository was archived by the owner on Sep 26, 2020. It is now read-only.

Commit 1011186

Browse files
author
cromwellian@google.com
committed
Adds new configuration property to specify minimum fragment size.
<set-configuration-property name="compiler.splitpoint.leftovermerge.size" value="size in bytes"/> Any exclusive fragment smaller than this limit will be merged into the left overs fragment. Change-Id: Ifcf035d88db70e890c739eab3997b85fa2e5677e Review-Link: https://gwt-review.googlesource.com/#/c/2581/ git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11607 8db76d5a-ed1c-0410-87a9-c151d255dfc7
1 parent fbfdcd3 commit 1011186

File tree

6 files changed

+265
-25
lines changed

6 files changed

+265
-25
lines changed

dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,9 @@ public static PermutationResult compilePermutation(TreeLogger logger, UnifiedAst
418418
// merging.
419419
if (fragmentsMerge > 0) {
420420
CodeSplitter2.exec(logger, jprogram, jsProgram, jjsmap, fragmentsMerge,
421-
chooseDependencyRecorder(options.isSoycEnabled(), baos));
421+
chooseDependencyRecorder(options.isSoycEnabled(), baos),
422+
findIntegerConfigurationProperty(propertyOracles, logger,
423+
CodeSplitter2.LEFTOVERMERGE_SIZE, 0));
422424
} else {
423425
CodeSplitter.exec(logger, jprogram, jsProgram, jjsmap, chooseDependencyRecorder(options
424426
.isSoycEnabled(), baos));
@@ -587,6 +589,25 @@ public static boolean findBooleanProperty(PropertyOracle[] propertyOracles, Tree
587589
return toReturn;
588590
}
589591

592+
/**
593+
* Look for a configuration property in all property oracles.
594+
*/
595+
public static int findIntegerConfigurationProperty(
596+
PropertyOracle[] propertyOracles, TreeLogger logger,
597+
String name, int def) {
598+
int toReturn = def;
599+
for (PropertyOracle oracle : propertyOracles) {
600+
try {
601+
com.google.gwt.core.ext.ConfigurationProperty property = oracle.getConfigurationProperty(name);
602+
toReturn = Integer.parseInt(property.getValues().get(0));
603+
} catch (Exception e) {
604+
break;
605+
}
606+
}
607+
return toReturn;
608+
}
609+
610+
590611
public static UnifiedAst precompile(TreeLogger logger, ModuleDef module,
591612
RebindPermutationOracle rpo, String[] declEntryPts, String[] additionalRootTypes,
592613
JJSOptions options, boolean singlePermutation) throws UnableToCompleteException {

dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter2.java

Lines changed: 135 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@
4343
import com.google.gwt.dev.jjs.impl.FragmentExtractor.CfaLivenessPredicate;
4444
import com.google.gwt.dev.jjs.impl.FragmentExtractor.LivenessPredicate;
4545
import com.google.gwt.dev.jjs.impl.FragmentExtractor.NothingAlivePredicate;
46+
import com.google.gwt.dev.js.JsToStringGenerationVisitor;
4647
import com.google.gwt.dev.js.ast.JsBlock;
4748
import com.google.gwt.dev.js.ast.JsContext;
4849
import com.google.gwt.dev.js.ast.JsModVisitor;
4950
import com.google.gwt.dev.js.ast.JsNumericEntry;
5051
import com.google.gwt.dev.js.ast.JsProgram;
5152
import com.google.gwt.dev.js.ast.JsStatement;
5253
import com.google.gwt.dev.util.JsniRef;
54+
import com.google.gwt.dev.util.TextOutput;
5355
import com.google.gwt.dev.util.collect.HashMap;
5456
import com.google.gwt.dev.util.collect.Lists;
5557
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
@@ -277,7 +279,10 @@ boolean setLive(String string, int splitPoint) {
277279
* The property key for a list of initially loaded split points.
278280
*/
279281
private static final String PROP_INITIAL_SEQUENCE = "compiler.splitpoint.initial.sequence";
280-
282+
283+
public static final String LEFTOVERMERGE_SIZE =
284+
"compiler.splitpoint.leftovermerge.size";
285+
281286
public static ControlFlowAnalyzer computeInitiallyLive(JProgram jprogram) {
282287
return computeInitiallyLive(jprogram, CodeSplitter.NULL_RECORDER);
283288
}
@@ -295,16 +300,19 @@ public static ControlFlowAnalyzer computeInitiallyLive(
295300
return cfa;
296301
}
297302

298-
public static void exec(TreeLogger logger, JProgram jprogram, JsProgram jsprogram,
303+
public static void exec(TreeLogger logger, JProgram jprogram,
304+
JsProgram jsprogram,
299305
JavaToJavaScriptMap map, int fragmentsToMerge,
300-
MultipleDependencyGraphRecorder dependencyRecorder) {
306+
MultipleDependencyGraphRecorder dependencyRecorder,
307+
int leftOverMergeLimit) {
301308
if (jprogram.getRunAsyncs().size() == 0) {
302309
// Don't do anything if there is no call to runAsync
303310
return;
304311
}
305312
Event codeSplitterEvent = SpeedTracerLogger.start(CompilerEventType.CODE_SPLITTER);
306313
new CodeSplitter2(
307-
logger, jprogram, jsprogram, map, fragmentsToMerge, dependencyRecorder).execImpl();
314+
logger, jprogram, jsprogram, map, fragmentsToMerge,
315+
dependencyRecorder, leftOverMergeLimit).execImpl();
308316
codeSplitterEvent.end();
309317
}
310318

@@ -648,7 +656,8 @@ private static <T> void updateReverseMap(int splitPoint, Map<T, Integer> map, Se
648656
* Number of split points to merge.
649657
*/
650658
private final int splitPointsMerge;
651-
659+
private int leftOverMergeLimit;
660+
652661
/**
653662
* Maps the split point index X to Y where where that split point X would
654663
* appear in the Y.cache.js
@@ -665,12 +674,15 @@ private static <T> void updateReverseMap(int splitPoint, Map<T, Integer> map, Se
665674
*/
666675
private final int[] splitPointToFragmentMap;
667676

668-
private CodeSplitter2(TreeLogger logger, JProgram jprogram, JsProgram jsprogram,
677+
private CodeSplitter2(TreeLogger logger, JProgram jprogram,
678+
JsProgram jsprogram,
669679
JavaToJavaScriptMap map, int splitPointsMerge,
670-
MultipleDependencyGraphRecorder dependencyRecorder) {
680+
MultipleDependencyGraphRecorder dependencyRecorder,
681+
int leftOverMergeLimit) {
671682
this.jprogram = jprogram;
672683
this.jsprogram = jsprogram;
673684
this.splitPointsMerge = splitPointsMerge;
685+
this.leftOverMergeLimit = leftOverMergeLimit;
674686
this.fragmentExtractor = new FragmentExtractor(jprogram, jsprogram, map);
675687
this.initialLoadSequence = new LinkedHashSet<Integer>(jprogram.getSplitPointInitialSequence());
676688

@@ -713,7 +725,100 @@ private void addFragment(int splitPoint, LivenessPredicate alreadyLoaded,
713725
stats.addAll(stmtsToAppend);
714726
fragmentStats.put(splitPoint, stats);
715727
}
716-
728+
729+
private boolean fragmentSizeBelowMergeLimit(List<JsStatement> stats,
730+
final int leftOverMergeLimit) {
731+
int sizeInBytes = 0;
732+
TextOutput out = new TextOutput() {
733+
int count = 0;
734+
735+
@Override
736+
public int getColumn() {
737+
return 0;
738+
}
739+
740+
@Override
741+
public int getLine() {
742+
return 0;
743+
}
744+
745+
@Override
746+
public int getPosition() {
747+
return count;
748+
}
749+
750+
@Override
751+
public void indentIn() {
752+
}
753+
754+
@Override
755+
public void indentOut() {
756+
}
757+
758+
@Override
759+
public void newline() {
760+
inc(1);
761+
}
762+
763+
@Override
764+
public void newlineOpt() {
765+
}
766+
767+
@Override
768+
public void print(char c) {
769+
inc(1);
770+
}
771+
772+
@Override
773+
public void print(char[] s) {
774+
inc(s.length);
775+
}
776+
777+
@Override
778+
public void print(String s) {
779+
inc(s.length());
780+
}
781+
782+
private void inc(int length) {
783+
count += length;
784+
if (count >= leftOverMergeLimit) {
785+
// yucky, but necessary, early exit
786+
throw new MergeLimitExceededException();
787+
}
788+
}
789+
790+
@Override
791+
public void printOpt(char c) {
792+
}
793+
794+
@Override
795+
public void printOpt(char[] s) {
796+
}
797+
798+
@Override
799+
public void printOpt(String s) {
800+
}
801+
};
802+
803+
try {
804+
JsToStringGenerationVisitor v = new JsToStringGenerationVisitor(out);
805+
for (JsStatement stat : stats) {
806+
v.accept(stat);
807+
}
808+
sizeInBytes += out.getPosition();
809+
} catch (InternalCompilerException me) {
810+
if (me.getCause().getClass() == MergeLimitExceededException.class) {
811+
return false;
812+
} else {
813+
throw me;
814+
}
815+
}
816+
return sizeInBytes < leftOverMergeLimit;
817+
}
818+
819+
private static class MergeLimitExceededException extends RuntimeException {
820+
}
821+
717822
private ControlFlowAnalyzer computeAllButNCfas(
718823
ControlFlowAnalyzer liveAfterInitialSequence, List<Integer> sp) {
719824
List<ControlFlowAnalyzer> allButOnes = new ArrayList<ControlFlowAnalyzer>();
@@ -867,7 +972,8 @@ private void extractStatements(ControlFlowAnalyzer initiallyLive) {
867972
}
868973
}
869974
allFields.addAll(everything.getFieldsWritten());
870-
975+
ArrayList<JsStatement> leftOverMergeStats = new ArrayList<JsStatement>();
976+
871977
// Search for all the atoms that are exclusively needed in each split point.
872978
for (int i = 1; i < splitPointToFragmentMap.length; i++) {
873979

@@ -925,19 +1031,36 @@ private void extractStatements(ControlFlowAnalyzer initiallyLive) {
9251031

9261032
LivenessPredicate alreadyLoaded = new ExclusivityMapLivenessPredicate(fragmentMap, 0);
9271033
LivenessPredicate liveNow = new ExclusivityMapLivenessPredicate(fragmentMap, i);
928-
List<JsStatement> statsToAppend = fragmentExtractor.createOnLoadedCall(cacheIndex);
929-
addFragment(i, alreadyLoaded, liveNow, statsToAppend, fragmentStats);
1034+
List<JsStatement> exclusiveStats = fragmentExtractor.extractStatements(liveNow, alreadyLoaded);
1035+
if (fragmentSizeBelowMergeLimit(exclusiveStats, leftOverMergeLimit)) {
1036+
leftOverMergeStats.addAll(exclusiveStats);
1037+
// merged to leftovers
1038+
splitPointToFragmentMap[i] = -1;
1039+
continue;
1040+
} else {
1041+
List<JsStatement> statsToAppend = fragmentExtractor.createOnLoadedCall(cacheIndex);
1042+
addFragment(i, alreadyLoaded, liveNow, statsToAppend, fragmentStats);
1043+
}
9301044
cacheIndex++;
9311045
}
9321046

1047+
1048+
for (int i = 0; i < splitPointToFragmentMap.length; i++) {
1049+
if (splitPointToFragmentMap[i] == -1) {
1050+
// set fragment number -1 to be leftovers fragment number
1051+
splitPointToFragmentMap[i] = splitPointToFragmentMap.length;
1052+
}
1053+
}
1054+
9331055
/*
9341056
* Compute the leftovers fragment.
9351057
*/
9361058
{
9371059
LivenessPredicate alreadyLoaded = new CfaLivenessPredicate(liveAfterInitialSequence);
9381060
LivenessPredicate liveNow = new ExclusivityMapLivenessPredicate(fragmentMap, 0);
9391061
List<JsStatement> statsToAppend = fragmentExtractor.createOnLoadedCall(cacheIndex);
940-
addFragment(splitPointToFragmentMap.length, alreadyLoaded, liveNow, statsToAppend, fragmentStats);
1062+
leftOverMergeStats.addAll(statsToAppend);
1063+
addFragment(splitPointToFragmentMap.length, alreadyLoaded, liveNow, leftOverMergeStats, fragmentStats);
9411064
}
9421065

9431066
// now install the new statements in the program fragments

dev/core/src/com/google/gwt/dev/js/JsSourceGenerationVisitorWithSizeBreakdown.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.google.gwt.dev.js.ast.JsName;
2929
import com.google.gwt.dev.js.ast.JsProgram;
3030
import com.google.gwt.dev.js.ast.JsProgramFragment;
31-
import com.google.gwt.dev.js.ast.JsSeedIdOf;
3231
import com.google.gwt.dev.js.ast.JsStatement;
3332
import com.google.gwt.dev.js.ast.JsVars.JsVar;
3433
import com.google.gwt.dev.js.ast.JsVisitable;
@@ -84,12 +83,6 @@ public boolean visit(JsProgramFragment x, JsContext ctx) {
8483
return true;
8584
}
8685

87-
@Override
88-
public boolean visit(JsSeedIdOf x, JsContext ctx) {
89-
out.print(String.valueOf(x.getSeedId()));
90-
return false;
91-
}
92-
9386
@Override
9487
protected final <T extends JsVisitable> T doAccept(T node) {
9588
JsName newName = nameToBillTo(node, billedAncestor != null);

dev/core/src/com/google/gwt/dev/js/JsToStringGenerationVisitor.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import com.google.gwt.dev.js.ast.JsPropertyInitializer;
6060
import com.google.gwt.dev.js.ast.JsRegExp;
6161
import com.google.gwt.dev.js.ast.JsReturn;
62+
import com.google.gwt.dev.js.ast.JsSeedIdOf;
6263
import com.google.gwt.dev.js.ast.JsStatement;
6364
import com.google.gwt.dev.js.ast.JsStringLiteral;
6465
import com.google.gwt.dev.js.ast.JsSwitch;
@@ -895,6 +896,12 @@ public boolean visit(JsReturn x, JsContext ctx) {
895896
return false;
896897
}
897898

899+
@Override
900+
public boolean visit(JsSeedIdOf x, JsContext ctx) {
901+
p.print(String.valueOf(x.getSeedId()));
902+
return false;
903+
}
904+
898905
@Override
899906
public boolean visit(JsStringLiteral x, JsContext ctx) {
900907
printStringLiteral(x.getValue());

0 commit comments

Comments
 (0)