aboutsummaryrefslogtreecommitdiff
path: root/tools/js-optimizer.js
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-03-16 14:00:16 -0700
committerAlon Zakai <alonzakai@gmail.com>2014-03-17 17:56:17 -0700
commitfb331c96b0c710e9b2ff4f944aa4b43e62a320e6 (patch)
tree46a8bda8e8ce5a678956cf54bbb1c18ab23a8f7a /tools/js-optimizer.js
parent9b7c27056eccfa8f95dc2c61fe969ab6f353757a (diff)
fix else fusing when label has multiple assigns or checks
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r--tools/js-optimizer.js37
1 files changed, 36 insertions, 1 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index c38b51d5..1c3bc8c0 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -879,6 +879,41 @@ function simplifyIfs(ast) {
if (simplifiedAnElse) {
// there may be fusing opportunities
+
+ // we can only fuse if we remove all uses of the label. if there are
+ // other ones - if the label check can be reached from elsewhere -
+ // we must leave it
+ var abort = false;
+
+ var labelAssigns = {};
+ traverse(func, function(node, type) {
+ if (type === 'assign' && node[2][0] === 'name' && node[2][1] === 'label') {
+ if (node[3][0] === 'num') {
+ var value = node[3][1];
+ labelAssigns[value] = (labelAssigns[value] || 0) + 1;
+ } else {
+ // label is assigned a dynamic value (like from indirectbr), we cannot do anything
+ abort = true;
+ }
+ }
+ });
+ if (abort) return;
+
+ var labelChecks = {};
+ traverse(func, function(node, type) {
+ if (type === 'binary' && node[1] === '==' && node[2][0] === 'binary' && node[2][1] === '|' &&
+ node[2][2][0] === 'name' && node[2][2][1] === 'label') {
+ if (node[3][0] === 'num') {
+ var value = node[3][1];
+ labelChecks[value] = (labelChecks[value] || 0) + 1;
+ } else {
+ // label is checked vs a dynamic value (like from indirectbr), we cannot do anything
+ abort = true;
+ }
+ }
+ });
+ if (abort) return;
+
traverse(func, function(node, type) {
var stats = getStatements(node);
if (stats) {
@@ -894,7 +929,7 @@ function simplifyIfs(ast) {
postCond[3][0] === 'num') {
var postValue = postCond[3][1];
var preElse = pre[3];
- if (preElse[0] === 'block' && preElse[1] && preElse[1].length === 1) {
+ if (labelAssigns[postValue] === 1 && labelChecks[postValue] === 1 && preElse[0] === 'block' && preElse[1] && preElse[1].length === 1) {
var preStat = preElse[1][0];
if (preStat[0] === 'stat' && preStat[1][0] === 'assign' &&
preStat[1][1] === true && preStat[1][2][0] === 'name' && preStat[1][2][1] === 'label' &&