diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-11-18 18:33:07 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-11-18 18:33:07 -0800 |
commit | 6fe6d4c2e43a7b2637c9cace06c7ef3f21018f0d (patch) | |
tree | 353d6f65de0b0c44f2fe88a96bb10231b931b69c | |
parent | fbfbdba4bf1913fe0a97d1e3ca5b1c14a38c8964 (diff) |
cleverer dependency resolving in phis
-rw-r--r-- | src/jsifier.js | 42 | ||||
-rw-r--r-- | src/parseTools.js | 6 |
2 files changed, 42 insertions, 6 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 2da90219..38cdac35 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -717,10 +717,45 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { if (!phiSets || !phiSets[label]) return ''; var labelSets = phiSets[label]; if (labelSets.length == 1) { - return 'var ' + labelSets[0].ident + ' = ' + labelSets[0].valueJS + ';'; + return labelSets[0].ident + ' = ' + labelSets[0].valueJS + ';'; } - // TODO: optimize number of copies // TODO: eliminate unneeded sets (to undefined etc.) + var deps = {}; // for each ident we will set, which others it depends on + var valueJSes = {}; + labelSets.forEach(function(labelSet) { + deps[labelSet.ident] = {}; + valueJSes[labelSet.ident] = labelSet.valueJS; + }); + labelSets.forEach(function(labelSet) { + walkInterdata(labelSet.value, function mark(item) { + if (item.intertype == 'value' && item.ident in deps) { + deps[labelSet.ident][item.ident] = true; + } + }); + }); + var pre = '', post = '', idents; + mainLoop: while ((idents = keys(deps)).length > 0) { + function remove(ident) { + for (var i = 0; i < idents.length; i++) { + delete deps[idents[i]][ident]; + } + delete deps[ident]; + } + for (var i = 0; i < idents.length; i++) { + if (keys(deps[idents[i]]).length == 0) { + pre = idents[i] + ' = ' + valueJSes[idents[i]] + ';' + pre; + remove(idents[i]); + continue mainLoop; + } + } + // If we got here, we have circular dependencies, and must break at least one. + pre = 'var ' + idents[0] + '$phi = ' + valueJSes[idents[i]] + ';' + pre; + post += idents[0] + ' = ' + idents[0] + '$phi;'; + remove(idents[0]); + } + return pre + post; + + /* // Safe, unoptimized copying var ret = ''; for (var i = 0; i < labelSets.length-1; i++) { ret += 'var ' + labelSets[i].ident + '$phi = ' + labelSets[i].valueJS + ';'; @@ -729,7 +764,8 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { for (var i = 0; i < labelSets.length-1; i++) { ret += labelSets[i].ident + ' = ' + labelSets[i].ident + '$phi;'; } - return '/* phi */' + ret; + return ret; + */ } makeFuncLineActor('branch', function(item) { diff --git a/src/parseTools.js b/src/parseTools.js index e3734e0e..07855c70 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1692,9 +1692,9 @@ function processMathop(item) { with(item) { // TODO: Use this in analyzer, possibly also in jsifier function walkInterdata(item, pre, post, obj) { if (!item || !item.intertype) return false; - if (pre(item, obj)) return true; + if (pre && pre(item, obj)) return true; var originalObj = obj; - if (obj.replaceWith) obj = obj.replaceWith; // allow pre to replace the object we pass to all its children + if (obj && obj.replaceWith) obj = obj.replaceWith; // allow pre to replace the object we pass to all its children if (item.value && walkInterdata(item.value, pre, post, obj)) return true; var i; for (i = 1; i <= 4; i++) { @@ -1712,7 +1712,7 @@ function walkInterdata(item, pre, post, obj) { if (walkInterdata(box, pre, post, obj)) return true; } } - return post(item, originalObj, obj); + return post && post(item, originalObj, obj); } function parseBlockAddress(segment) { |