diff options
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r-- | tools/js-optimizer.js | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 29b36cad..4192ddd1 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2817,7 +2817,7 @@ function relocate(ast) { var other = node[3]; if (base === 0) return other; if (other[0] == 'num') { - other[1] += base; + other[1] = (other[1] + base)|0; return other; } else { node[2] = ['num', base]; @@ -3106,7 +3106,7 @@ function outline(ast) { // Reserve an extra two spots per possible outlining: one for control flow var, the other for control flow data // The control variables are zeroed out when calling an outlined function, and after using // the value after they return. - asmData.maxOutlinings = Math.round(3*measureSize(func)/sizeToOutline); + asmData.maxOutlinings = Math.round(3*measureSize(func)/extraInfo.sizeToOutline); asmData.totalStackSize = stackSize + (stack.length + 2*asmData.maxOutlinings)*8; asmData.controlStackPos = function(i) { return stackSize + (stack.length + i)*8 }; asmData.controlDataStackPos = function(i) { return stackSize + (stack.length + i)*8 + 4 }; @@ -3210,22 +3210,30 @@ function outline(ast) { var CONTROL_BREAK = 1, CONTROL_BREAK_LABEL = 2, CONTROL_CONTINUE = 3, CONTROL_CONTINUE_LABEL = 4, CONTROL_RETURN_VOID = 5, CONTROL_RETURN_INT = 6, CONTROL_RETURN_DOUBLE = 7; - var sizeToOutline = extraInfo.sizeToOutline; - var level = 0; + var sizeToOutline = null; // customized per function and as we make progress + function calculateThreshold(func) { + sizeToOutline = extraInfo.sizeToOutline; + var size = measureSize(func); + //var desiredChunks = Math.ceil(size/extraInfo.sizeToOutline); + ////sizeToOutline = Math.round((extraInfo.sizeToOutline + (2*size/desiredChunks))/3); + //sizeToOutline = Math.round(size/desiredChunks); + printErr('trying to reduce the size of ' + func[1] + ' which is ' + size + ' (>= ' + extraInfo.sizeToOutline + '), aim for ' + sizeToOutline); + } + var level = 0; var outliningParents = {}; // function name => parent it was outlined from function doOutline(func, asmData, stats, start, end) { if (asmData.splitCounter === asmData.maxOutlinings) return []; if (!extraInfo.allowCostlyOutlines) var originalStats = copy(stats); var code = stats.slice(start, end+1); + var originalCodeSize = measureSize(code); var funcSize = measureSize(func); var outlineIndex = asmData.splitCounter++; var newIdent = func[1] + '$' + outlineIndex; // 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); - //printErr(' do outline ' + [func[1], level, 'range:', start, end, 'of', stats.length, newIdent, measureSize(code), JSON.stringify(codeInfo.labels), JSON.stringify(codeInfo.breaks), JSON.stringify(codeInfo.continues)]); var owned = { sp: 1 }; // sp is always owned, each has its own keys(setUnion(codeInfo.reads, codeInfo.writes)).forEach(function(v) { if (allCodeInfo.reads[v] === codeInfo.reads[v] && allCodeInfo.writes[v] === codeInfo.writes[v] && !(v in asmData.params)) { @@ -3409,9 +3417,11 @@ function outline(ast) { stats.splice.apply(stats, [start, end-start+1].concat(reps)); // final evaluation and processing if (!extraInfo.allowCostlyOutlines && (measureSize(func) >= funcSize || measureSize(newFunc) >= funcSize)) { + //printErr('aborted outline attempt ' + [measureSize(func), measureSize(newFunc), ' one of which >= ', funcSize]); // abort, this was pointless stats.length = originalStats.length; for (var i = 0; i < stats.length; i++) stats[i] = originalStats[i]; + asmData.splitCounter--; return []; } for (var v in owned) { @@ -3426,6 +3436,8 @@ function outline(ast) { } } outliningParents[newIdent] = func[1]; + printErr('performed outline ' + [func[1], newIdent, 'code sizes (pre/post):', originalCodeSize, measureSize(code), 'overhead (w/r):', setSize(setSub(codeInfo.writes, owned)), setSize(setSub(codeInfo.reads, owned))]); + calculateThreshold(func); return [newFunc]; } @@ -3452,7 +3464,7 @@ function outline(ast) { } while (1) { i--; - calcMinIndex(); + calcMinIndex(); // TODO: optimize if (i < minIndex) { // we might be done. but, if we have just outlined, do a further attempt from the beginning. // (but only if the total costs are not extravagant) @@ -3509,7 +3521,7 @@ function outline(ast) { // If this is big enough to outline, but not too big (if very close to the size of the full function, // outlining is pointless; remove stats from the end to try to achieve the good case), then outline. // Also, try to reduce the size if it is much larger than the hoped-for size - while ((sizeSeen > maxSize || sizeSeen > 2*sizeToOutline) && end > i+1 && stats[end][0] !== 'begin-outline-call' && stats[end][0] !== 'end-outline-call') { + while ((sizeSeen > maxSize || sizeSeen > 2*sizeToOutline) && end > i && stats[end][0] !== 'begin-outline-call' && stats[end][0] !== 'end-outline-call') { sizeSeen -= measureSize(stats[end]); if (sizeSeen >= sizeToOutline) { end--; @@ -3531,12 +3543,12 @@ function outline(ast) { }); assert(sum == 0); // final decision and action + //printErr(' will try done working on sizeSeen due to ' + [(sizeSeen > maxSize || sizeSeen > 2*sizeToOutline), end > i , stats[end][0] !== 'begin-outline-call' , stats[end][0] !== 'end-outline-call'] + ' ... ' + [sizeSeen, sizeToOutline, maxSize, sizeSeen >= sizeToOutline, sizeSeen <= maxSize]); if (sizeSeen >= sizeToOutline && sizeSeen <= maxSize) { assert(i >= minIndex); var newFuncs = doOutline(func, asmData, stats, i, end); // outline [i, .. ,end] inclusive if (newFuncs.length) { ret.push.apply(ret, newFuncs); - printErr('performed outline on ' + func[1] + ' of ' + sizeSeen + ', func is now size ' + measureSize(func) + ' ==> ' + newFuncs[0][1]); } sizeSeen = 0; end = i-1; @@ -3566,10 +3578,10 @@ function outline(ast) { funcs.forEach(function(func) { var asmData = normalizeAsm(func); var size = measureSize(func); - if (size >= sizeToOutline) { - printErr('trying to reduce the size of ' + func[1] + ' which is ' + size + ' (>= ' + sizeToOutline + ')'); + if (size >= extraInfo.sizeToOutline) { aggressiveVariableElimination(func, asmData); flatten(func, asmData); + calculateThreshold(func); analyzeFunction(func, asmData); var stats = getStatements(func); var ret = outlineStatements(func, asmData, stats, 0.9*size); |