aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js52
-rw-r--r--src/jsifier.js13
-rw-r--r--src/parseTools.js9
3 files changed, 55 insertions, 19 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index ae40896d..f79217bd 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -443,7 +443,13 @@ function analyzer(data, givenTypes) {
ret.push(item[id]);
dprint('relooping', 'zz ' + id + ' replace ' + item[id] + ' with ' + toLabelId);
if (toLabelId) {
- item[id] = toLabelId + '|' + item[id];
+ // replace wildcards in new value with old parts
+ var oldParts = item[id].split('|');
+ var newParts = toLabelId.split('|');
+ for (var i = 1; i < 3; i++) {
+ if (newParts[i] === '*') newParts[i] = oldParts[i];
+ }
+ item[id] = newParts.join('|') + '|' + item[id];
}
}
});
@@ -640,6 +646,7 @@ function analyzer(data, givenTypes) {
var ret = {
type: 'reloop',
id: blockId,
+ needBlockId: true,
entries: entries,
labels: labels
};
@@ -767,6 +774,7 @@ function analyzer(data, givenTypes) {
return {
type: 'multiple',
id: blockId,
+ needBlockId: true,
entries: actualEntries,
entryLabels: actualEntryLabels,
labels: handlingNow,
@@ -798,7 +806,7 @@ function analyzer(data, givenTypes) {
if (!RELOOP) return finish();
// Find where each block will 'naturally' get to, just by the flow of code
- function exploreBlock(block, endOfTheWorld) { // endoftheworld - where we will get, if we have nothing else to get to - 'fall off the face of the earth'
+ function exploreBlockEndings(block, endOfTheWorld) { // endoftheworld - where we will get, if we have nothing else to get to - 'fall off the face of the earth'
if (!block) return;
function singular(block) {
@@ -814,9 +822,9 @@ function analyzer(data, givenTypes) {
dprint('relooping', "// exploring block: " + block.type + ' : ' + block.entries);
if (block.type == 'reloop') {
- exploreBlock(block.inner, singular(block.inner));
+ exploreBlockEndings(block.inner, singular(block.inner));
} else if (block.type == 'multiple') {
- block.entryLabels.forEach(function(entryLabel) { exploreBlock(entryLabel.block, singular(block.next)) });
+ block.entryLabels.forEach(function(entryLabel) { exploreBlockEndings(entryLabel.block, singular(block.next)) });
} else if (block.type === 'emulated' && block.next && block.next.type === 'multiple') {
assert(block.labels.length == 1);
var lastLine = block.labels[0].lines.slice(-1)[0];
@@ -828,7 +836,7 @@ function analyzer(data, givenTypes) {
}
}
- exploreBlock(block.next, endOfTheWorld);
+ exploreBlockEndings(block.next, endOfTheWorld);
if (block.next) {
block.willGetTo = singular(block.next);
@@ -840,12 +848,12 @@ function analyzer(data, givenTypes) {
}
// Remove unneeded label settings, if we set it to where we will get anyhow
- function optimizeBlock(block) {
+ function optimizeBlockEndings(block) {
if (!block) return;
dprint('relooping', "// optimizing block: " + block.type + ' : ' + block.entries);
- recurseBlock(block, optimizeBlock);
+ recurseBlock(block, optimizeBlockEndings);
if (block.type === 'emulated' && block.willGetTo) {
dprint('relooping', '// removing (trying): ' + block.willGetTo);
@@ -873,11 +881,37 @@ function analyzer(data, givenTypes) {
}
}
+ // Checks whether we actually need labels. We return whether we have a loop nested inside us.
+ function optimizeOutUnneededLabels(block) {
+ if (!block) return false;
+
+ dprint('relooping', "// optimizing (2) block: " + block.type + ' : ' + block.entries);
+
+ var containLoop = sum(recurseBlock(block, optimizeOutUnneededLabels)) > 0;
+
+ if (block.type === 'emulated') {
+ return containLoop;
+ } else if (block.type === 'multiple') {
+ // TODO: Apply the same optimization below for 'reloop', to looped multiples
+ return containLoop || !block.loopless;
+ } else if (block.type === 'reloop') {
+ if (!containLoop) {
+ block.needBlockId = false;
+
+ replaceLabelLabels(block.labels, set('BCONT|' + block.id + '|*'), 'BCONT||*');
+ replaceLabelLabels(block.labels, set('BREAK|' + block.id + '|*'), 'BREAK||*');
+ }
+ return true;
+ }
+ assert(false);
+ }
+
// TODO: Parallelize
item.functions.forEach(function(func) {
dprint('relooping', "// loopOptimizing function: " + func.ident);
- exploreBlock(func.block);
- optimizeBlock(func.block);
+ exploreBlockEndings(func.block);
+ optimizeBlockEndings(func.block);
+ optimizeOutUnneededLabels(func.block);
});
return finish();
}
diff --git a/src/jsifier.js b/src/jsifier.js
index 7efc407c..e93467c3 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -455,14 +455,14 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
}
ret += '\n';
} else if (block.type == 'reloop') {
- ret += indent + block.id + ': while(1) { ' + (SHOW_LABELS ? ' /* ' + block.entries + + ' */' : '') + '\n';
+ ret += indent + (block.needBlockId ? block.id + ': ' : '') + 'while(1) { ' + (SHOW_LABELS ? ' /* ' + block.entries + + ' */' : '') + '\n';
ret += walkBlock(block.inner, indent + ' ');
ret += indent + '}\n';
} else if (block.type == 'multiple') {
var first = true;
var multipleIdent = '';
if (!block.loopless) {
- ret += indent + block.id + ':' + ' do { \n';
+ ret += indent + (block.needBlockId ? block.id + ': ' : '') + 'do { \n';
multipleIdent = ' ';
}
var stolen = block.stolenCondition;
@@ -630,9 +630,10 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
}
if (label[0] == 'B') {
var parts = label.split('|');
- var trueLabel = parts[1];
- var oldLabel = parts[2];
- var labelSetting = '__label__ = ' + getLabelId(oldLabel) + ';' + (SHOW_LABELS ? ' /* to: ' + cleanLabel(oldLabel) + ' */' : ''); // TODO: optimize away
+ var trueLabel = parts[1] || '';
+ var oldLabel = parts[2] || '';
+ var labelSetting = oldLabel ? '__label__ = ' + getLabelId(oldLabel) + ';' +
+ (SHOW_LABELS ? ' /* to: ' + cleanLabel(oldLabel) + ' */' : '') : ''; // TODO: optimize away the setting
if (label[1] == 'R') {
return pre + labelSetting + 'break ' + trueLabel + ';';
} else if (label[1] == 'C') { // CONT
@@ -640,7 +641,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
} else if (label[1] == 'N') { // NOPP
return pre + ';'; // Returning no text might confuse this parser
} else if (label[1] == 'J') { // JSET
- return pre + labelSetting;
+ return pre + labelSetting + ';';
} else {
throw 'Invalid B-op in branch: ' + trueLabel + ',' + oldLabel;
}
diff --git a/src/parseTools.js b/src/parseTools.js
index 52afcfe7..fed1ee7c 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -512,13 +512,14 @@ function calcAllocatedSize(type, TYPES) {
// Flow blocks
function recurseBlock(block, func) {
+ var ret = [];
if (block.type == 'reloop') {
- func(block.inner);
+ ret.push(func(block.inner));
} else if (block.type == 'multiple') {
- block.entryLabels.forEach(function(entryLabel) { func(entryLabel.block) });
+ block.entryLabels.forEach(function(entryLabel) { ret.push(func(entryLabel.block)) });
}
-
- func(block.next);
+ ret.push(func(block.next));
+ return ret;
}
function getActualLabelId(labelId) {