aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoralon@honor <none@none>2010-10-03 15:05:26 -0700
committeralon@honor <none@none>2010-10-03 15:05:26 -0700
commit7acd07a63ff39da63869856734c51bc665528270 (patch)
tree1053cabfdde816eb6f722658ab23ce22a5b73681 /src
parentdf1e26bbe05df56f4fa8ad2beeeac9fc2b298f04 (diff)
clean up relooper
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js77
1 files changed, 47 insertions, 30 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 28c2aa97..09403278 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -453,28 +453,32 @@ function analyzer(data) {
}
if (!RELOOP) return emulated();
- // === 'splitter' ===
+ var s_entries = searchable(entries);
+ assert(entries[0]); // need at least 1 entry
+ dprint('relooping', 'makeBlock: ' + entries + ',' + labels.length + ' labels');
- if (entries.length > 1) {
- return emulated();
- }
-
- var entry = entries[0];
- assert(entry);
- dprint('relooping', 'makeBlock: ' + entry + ',' + labels.length + ' labels');
+ var entryLabels = entries.map(function(entry) { return labelsDict[entry] });
+ assert(entryLabels[0]);
- var entryLabel = labelsDict[entry];
- assert(entryLabel);
- var lastLine = entryLabel.lines.slice(-1)[0];
- var others = labels.filter(function(label) { return label.ident != entry });
-
- var canReturn = values(entryLabel.inLabels).length > 0;
+ var canReturn = false;
+ entryLabels.forEach(function(entryLabel) {
+ canReturn = canReturn || values(entryLabel.inLabels).length > 0;
+ });
- labels = labels.filter(function(label) { return label === entryLabel || label.ident in entryLabel.allOutLabels }); // ignore unreachables
+ // Remove unreachables
+ allOutLabels = {};
+ entryLabels.forEach(function(entryLabel) {
+ mergeInto(allOutLabels, entryLabel.allOutLabels);
+ });
+ labels = labels.filter(function(label) { return label.ident in s_entries || label.ident in allOutLabels });
// === (simple) 'emulated' ===
- if (!canReturn && values(entryLabel.outLabels).length == 1) {
+ if (entries.length == 1 && !canReturn && values(entryLabels[0].outLabels).length == 1) {
+ var entry = entries[0];
+ var entryLabel = entryLabels[0];
+ var others = labels.filter(function(label) { return label.ident != entry });
+
dprint('relooping', ' Creating simple emulated, outlabels: ' + keys(entryLabel.outLabels));
var next = keys(entryLabel.outLabels)[0];
if (next in exitLabels) {
@@ -495,19 +499,23 @@ function analyzer(data) {
// === 'reloop' away a loop, if there is one ===
- if (canReturn) {
+ if (entries.length == 1 && canReturn) {
var ret = {
type: 'reloop',
- entry: entry,
+ entries: entries,
labels: labels,
};
// Find internal and external labels
- var split_ = splitter(labels, function(label) { return !(entry in label.allOutLabels) });
+ var split_ = splitter(labels, function(label) {
+ return !(label.ident in s_entries) && values(setIntersect(s_entries, label.allOutLabels)).length == 0
+ });
var externals = split_.splitOut;
var internals = split_.leftIn;
var currExitLabels = set(getLabelIds(externals));
+ dprint('relooping', function() { return ' Creating reloop: Inner: ' + dump(getLabelIds(internals)) + ', Exxer: ' + dump(currExitLabels) });
+
// Verify that no external can reach an internal
var inLabels = set(getLabelIds(internals));
externals.forEach(function(external) {
@@ -517,24 +525,33 @@ function analyzer(data) {
}
});
- dprint('relooping', function() { return ' Creating reloop: Inner: ' + dump(getLabelIds(internals)) + ', Exxer: ' + dump(currExitLabels) });
+ // We will be in a loop, |continue| gets us back to the entry
+ entries.forEach(function(entry) {
+ replaceLabelLabels(internals, searchable(entry), 'BCONT' + entries[0]); // entries[0] is the name of the loop, see walkBlock
+ });
- replaceLabelLabels(internals, searchable(entry), 'BCONT' + entry); // we will be in a loop, |continue| gets us back to the entry
+ // To get to any of our (not our parents') exit labels, we will break.
dprint('relooping', 'for exit purposes, Replacing: ' + dump(currExitLabels));
- var enteredExitLabels = replaceLabelLabels(internals, currExitLabels, 'BREAK' + entry); // to get to any of our (not our parents') exit labels,
- // we will break.
- dprint('relooping', dump(currExitLabels) + ' enteredExitLabels: ' + dump(enteredExitLabels));
- enteredExitLabels = enteredExitLabels.map(cleanLabel);
- dprint('relooping', ' enteredExitLabels: ' + dump(enteredExitLabels));
+ var enteredExitLabels = {};
+ if (externals.length > 0) {
+ entries.forEach(function(entry) {
+ mergeInto(enteredExitLabels, set(replaceLabelLabels(internals, currExitLabels, 'BREAK' + entries[0]))); // see comment on entries[0] above
+ });
+ enteredExitLabels = keys(enteredExitLabels).map(cleanLabel);
+ dprint('relooping', 'enteredExitLabels: ' + dump(enteredExitLabels));
+ assert(enteredExitLabels.length > 0);
+ }
// inner
var allExitLabels = mergeInto(set(currExitLabels), exitLabels);
var currExitLabelsHit = {};
- ret.inner = makeBlock(internals, [entry], labelsDict, allExitLabels, currExitLabelsHit);
+ ret.inner = makeBlock(internals, entries, labelsDict, allExitLabels, currExitLabelsHit);
- // outer
- ret.outer = makeBlock(externals, enteredExitLabels, labelsDict, exitLabels, currExitLabelsHit);
- mergeInto(exitLabelsHit, setSub(currExitLabelsHit, currExitLabels)); // Don't really need setSub, but nicer
+ if (externals.length > 0) {
+ // outer
+ ret.outer = makeBlock(externals, enteredExitLabels, labelsDict, exitLabels, currExitLabelsHit);
+ mergeInto(exitLabelsHit, setSub(currExitLabelsHit, currExitLabels)); // Don't really need setSub, but nicer
+ }
return ret;
}