aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralon@honor <none@none>2010-10-02 23:29:02 -0700
committeralon@honor <none@none>2010-10-02 23:29:02 -0700
commit2f64c269303d4731f511e8b77e1ec8fb5f906763 (patch)
treec30b4a075239b6739efc41e3a76abada6ab93e8c
parent981b5832f5c0ae8a732e5e89f313c88efdadd0e3 (diff)
add missing branch detection of default in switch. all reloop but sauer, dlmalloc/clang
-rw-r--r--src/analyzer.js20
-rw-r--r--src/intertyper.js2
-rw-r--r--src/jsifier.js5
-rw-r--r--src/utility.js11
-rw-r--r--tests/runner.py4
-rw-r--r--tests/settings.py2
6 files changed, 36 insertions, 8 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 54f766cc..b44165b1 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -348,7 +348,7 @@ function analyzer(data) {
labels.forEach(function(label) {
label.lines.forEach(function(line) {
function process(item) {
- ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel'].forEach(function(id) {
+ ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) {
if (item[id]) {
if (item[id][0] == 'B') { // BREAK, BCONT, BNOPP
label.hasBreak = true;
@@ -460,7 +460,7 @@ function analyzer(data) {
if (entries.length > 1) return emulated();
var entry = entries[0];
assert(entry);
- dprint('relooping', 'Relooping: ' + entry + ',' + labels.length + ' labels');
+ dprint('relooping', 'makeBlock: ' + entry + ',' + labels.length + ' labels');
var entryLabel = labelsDict[entry];
assert(entryLabel);
@@ -469,11 +469,12 @@ function analyzer(data) {
var canReturn = values(entryLabel.inLabels).length > 0;
+ labels = labels.filter(function(label) { return label === entryLabel || label.ident in entryLabel.allOutLabels }); // ignore unreachables
+
// === (simple) 'emulated' ===
if (!canReturn && values(entryLabel.outLabels).length == 1) {
dprint('relooping', ' Creating simple emulated, outlabels: ' + keys(entryLabel.outLabels));
- assertEq(lastLine.intertype, 'branch');
var next = keys(entryLabel.outLabels)[0];
if (next in exitLabels) {
exitLabelsHit[next] = true;
@@ -506,6 +507,19 @@ function analyzer(data) {
var internals = split_.leftIn;
var currExitLabels = set(getLabelIds(externals));
+ // Verify that no external can reach an internal
+ var inLabels = set(getLabelIds(internals));
+ var fail = false;
+ externals.forEach(function(external) {
+ if (fail || values(setIntersect(external.outLabels, inLabels)).length > 0) {
+ fail = true;
+ }
+ });
+ if (fail) {
+ dprint('relooping', 'Found an external that wants to reach an internal, fallback to flow emulation');
+ return emulated();
+ }
+
dprint('relooping', function() { return ' Creating reloop: Inner: ' + dump(getLabelIds(internals)) + ', Exxer: ' + dump(currExitLabels) });
replaceLabelLabels(internals, searchable(entry), 'BCONT' + entry); // we will be in a loop, |continue| gets us back to the entry
diff --git a/src/intertyper.js b/src/intertyper.js
index ed670e65..3092a310 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -559,7 +559,7 @@ function intertyper(data) {
intertype: 'switch',
type: item.tokens[1].text,
ident: item.tokens[2].text,
- defaultLabel: item.tokens[5].text,
+ defaultLabel: toNiceIdent(item.tokens[5].text),
switchLabels: parseSwitchLabels(item.tokens[6]),
lineNum: item.lineNum,
}];
diff --git a/src/jsifier.js b/src/jsifier.js
index a4d7b96e..69bc7d1e 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -260,6 +260,7 @@ function JSify(data) {
if (!block.entry && block.entries.length == 1) block.entry = block.entries[0];
dprint('relooping', 'walking block: ' + block.type + ',' + block.entry + ',' + block.entries + ' : ' + block.labels.length);
function getLabelLines(label, indent) {
+ if (!label) return '';
var ret = '';
if (LABEL_DEBUG) {
ret += indent + "print(INDENT + '" + func.ident + ":" + label.ident + "');\n";
@@ -427,7 +428,7 @@ function JSify(data) {
if (label[0] == 'B') {
if (label[1] == 'R') {
assert(oldLabel);
- return '__label__ = ' + getLabelId(oldLabel) + '; ' + // TODO: optimize away
+ return '__label__ = ' + getLabelId(oldLabel) + '; /* ' + label + ' */' + // TODO: optimize away
'break ' + label.substr(5) + ';';
} else if (label[1] == 'C') {
return 'continue ' + label.substr(5) + ';';
@@ -435,7 +436,7 @@ function JSify(data) {
return ';'; // Returning no text might confuse this parser
}
} else {
- return '__label__ = ' + getLabelId(label) + '; break;';
+ return '__label__ = ' + getLabelId(label) + '; /* ' + label + ' */ break;';
}
}
diff --git a/src/utility.js b/src/utility.js
index 3d8ce86e..d5583ffb 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -202,3 +202,14 @@ function setSub(x, y) {
return ret;
}
+// Intersection of 2 sets. Faster if |xx| << |yy|
+function setIntersect(x, y) {
+ var ret = {};
+ for (xx in x) {
+ if (xx in y) {
+ ret[xx] = true;
+ }
+ }
+ return ret;
+}
+
diff --git a/tests/runner.py b/tests/runner.py
index c43125c3..dc3dfba0 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -69,7 +69,8 @@ class T(unittest.TestCase):
if DEBUG: print output
# Run Emscripten
emscripten_settings = ['{ "QUANTUM_SIZE": %d, "RELOOP": %d }' % (QUANTUM_SIZE, RELOOP)]
- timeout_run(Popen([EMSCRIPTEN, filename + '.o.llvm', PARSER_ENGINE] + emscripten_settings, stdout=open(filename + '.o.js', 'w'), stderr=STDOUT), 2400, 'Compiling')
+ out = open(filename + '.o.js', 'w') if not OUTPUT_TO_SCREEN else None
+ timeout_run(Popen([EMSCRIPTEN, filename + '.o.llvm', PARSER_ENGINE] + emscripten_settings, stdout=out, stderr=STDOUT), 240, 'Compiling')
output = open(filename + '.o.js').read()
if output_processor is not None:
output_processor(output)
@@ -825,7 +826,6 @@ class T(unittest.TestCase):
# used, see Mozilla bug 593659.
assert PARSER_ENGINE != SPIDERMONKEY_ENGINE
- # FIXME - hangs the compiler after an assert
assert not RELOOP
self.do_test(path_from_root(['tests', 'sauer']), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp')
diff --git a/tests/settings.py b/tests/settings.py
index 0782528d..e07241fc 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -33,3 +33,5 @@ JS_ENGINE=SPIDERMONKEY_ENGINE
JS_ENGINE_OPTS=[]
+OUTPUT_TO_SCREEN = 0 # useful for debugging specific tests, or for subjectively seeing what parts are slow
+