diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-07-20 19:34:58 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-07-20 19:34:58 -0700 |
commit | 1830d2c50c5e242d452741850b6b9d652245663b (patch) | |
tree | 1b778e8642838852df46fe1a02fb86d7d0b56890 /tools/js-optimizer.js | |
parent | 1cb5216141f58cdf45035bbd24f19702353b26d1 (diff) |
recursively outline when the total cost is not too high, and adjust outlining parameters
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r-- | tools/js-optimizer.js | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index f529a05f..1086cf92 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -3118,10 +3118,13 @@ function outline(ast) { var sizeToOutline = extraInfo.sizeToOutline; var level = 0; + var costs = {}; // new function name => overhead cost of outlining + function doOutline(func, asmData, stats, start, end) { var code = stats.slice(start, end+1); + var funcSize = measureSize(func); var newIdent = func[1] + '$' + (asmData.splitCounter++); - printErr(' do outline ' + [func[1], level, 'range:', start, end, 'of', stats.length, newIdent]); //dumpSrc(['block', code]);//dumpAst(['block', code]); + //printErr(' do outline ' + [func[1], level, 'range:', start, end, 'of', stats.length, newIdent, measureSize(code)]); //dumpSrc(['block', code]);//dumpAst(['block', code]); // analyze variables, and find 'owned' variables - that only appear in the outlined code, and do not need any spill support var codeInfo = analyzeCode(func, asmData, code); var allCodeInfo = analyzeCode(func, asmData, func); @@ -3299,6 +3302,10 @@ function outline(ast) { getStatements(func).push(['stat', ['return', makeAsmCoercion(['num', 0], allCodeInfo.hasReturnInt ? ASM_INT : ASM_DOUBLE)]]); } } + // the cost is the total size increase of all code, after the outlining operation. We also + // inherit the outlining cost of the parent function, if any, so the repeated outlining + // cannot infinitely recurse. + costs[newIdent] = measureSize(func) + measureSize(newFunc) - funcSize + (costs[func[1]] || 0); return [newFunc]; } @@ -3400,10 +3407,11 @@ function outline(ast) { var asmData = normalizeAsm(func); var size = measureSize(func); if (size >= sizeToOutline) { + printErr('trying to reduce the size of ' + func[1] + ' which is ' + size + ' (>= ' + sizeToOutline + ')'); aggressiveVariableElimination(func, asmData); analyzeFunction(func, asmData); var stats = getStatements(func); - var ret = outlineStatements(func, asmData, stats, 0.5*size); + var ret = outlineStatements(func, asmData, stats, 0.9*size); if (ret && ret.length > 0) { newFuncs.push.apply(newFuncs, ret); // We have outlined. Add stack support @@ -3444,12 +3452,12 @@ function outline(ast) { } } } + printErr('... resulting size of ' + func[1] + ' is ' + measureSize(func)); } denormalizeAsm(func, asmData); }); funcs = null; - sizeToOutline *= 2; // be more and more conservative about outlining as we look into outlined functions // TODO: control flow: route returns and breaks. outlined code should have all breaks/continues/returns break into the outermost scope, // after setting a state variable, etc. @@ -3458,8 +3466,11 @@ function outline(ast) { // add new functions to the toplevel, or create a toplevel if there isn't one ast[1].push.apply(ast[1], newFuncs); - // funcs = newFuncs; // TODO: consider recursing into newly outlined functions - // more = true; + funcs = newFuncs.filter(function(newFunc) { + // recursively outline if we have a large new function that did not come at a high cost + return measureSize(newFunc) > sizeToOutline && costs[newFunc[1]] < 0.1*sizeToOutline; + }); + more = funcs.length > 0; } } } |