aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-11-09 10:24:00 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-11-09 10:24:00 -0800
commitfcf35ec5e66ed72884091e30bdf4dafb813d644d (patch)
tree682b9c4dfe8fa0b71cd779b5c04332f8aa6d2e8e
parent699cd0750be681cf8d6176a7fa8d431a8c54c4c1 (diff)
support invoke in new relooper; fix branch code generation; generate emulated when we must
-rw-r--r--src/jsifier.js38
1 files changed, 27 insertions, 11 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index 8b0f9bca..2679db6c 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -575,7 +575,7 @@ function JSify(data, functionsOnly, givenFunctions) {
function walkBlock(block, indent) {
if (!block) return '';
dprint('relooping', 'walking block: ' + block.type + ',' + block.entries + ' : ' + block.labels.length);
- function getLabelLines(label, indent) {
+ function getLabelLines(label, indent, relooping) {
if (!label) return '';
var ret = '';
if (LABEL_DEBUG) {
@@ -592,14 +592,26 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// for special labels we care about (for phi), mark that we visited them
- return ret + label.lines.map(function(line) { return line.JS + (Debugging.on ? Debugging.getComment(line.lineNum) : '') })
+ var i = 0;
+ return ret + label.lines.map(function(line) {
+ var JS = line.JS;
+ if (relooping && i == label.lines.length-1) {
+ if (line.intertype == 'branch' || line.intertype == 'switch') {
+ JS = ''; // just branching operations - done in the relooper, so nothing need be done here
+ } else if (line.intertype == 'invoke') {
+ JS = line.reloopingJS; // invokes have code that is not rendered in the relooper (the call inside a try-catch)
+ }
+ }
+ i++;
+ return JS + (Debugging.on ? Debugging.getComment(line.lineNum) : '');
+ })
.join('\n')
.split('\n') // some lines include line breaks
.map(function(line) { return indent + line })
.join('\n');
}
var ret = '';
- if (!RELOOP) {
+ if (!RELOOP || func.forceEmulated) { // TODO: also if just 1 label?
if (block.labels.length > 1) {
if (block.entries.length == 1) {
ret += indent + 'label = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n';
@@ -640,7 +652,7 @@ function JSify(data, functionsOnly, givenFunctions) {
// add blocks
for (var i = 0; i < block.labels.length; i++) {
var label = block.labels[i];
- var content = getLabelLines(label, '');
+ var content = getLabelLines(label, '', true);
//printErr(func.ident + ' : ' + label.ident + ' : ' + content + '\n');
blockMap[label.ident] = Relooper.addBlock(content);
}
@@ -666,6 +678,9 @@ function JSify(data, functionsOnly, givenFunctions) {
relevant(switchLabel.labelJS));
});
Relooper.addBranch(blockMap[ident], blockMap[last.defaultLabel], 0, relevant(last.defaultLabelJS));
+ } else if (last.intertype == 'invoke') {
+ Relooper.addBranch(blockMap[ident], blockMap[last.toLabel], '!__THREW__', relevant(last.toLabelJS));
+ Relooper.addBranch(blockMap[ident], blockMap[last.unwindLabel], 0, relevant(last.unwindLabelJS));
} else if (last.intertype in RELOOP_IGNORED_LASTS) {
} else {
throw 'unknown reloop last line: ' + last.intertype;
@@ -830,7 +845,6 @@ function JSify(data, functionsOnly, givenFunctions) {
}
function makeBranch(label, lastLabel, labelIsVariable) { // lastLabel is deprecated
- if (RELOOP) return ' '; // done in relooper
var pre = '';
if (label[0] == 'B') {
assert(!labelIsVariable, 'Cannot handle branches to variables with special branching options');
@@ -934,12 +948,11 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('branch', function(item) {
var phiSets = calcPhiSets(item);
if (!item.value) {
- return item.labelJS = getPhiSetsForLabel(phiSets, item.label) + makeBranch(item.label, item.currLabelId);
+ return (item.labelJS = getPhiSetsForLabel(phiSets, item.label)) + makeBranch(item.label, item.currLabelId);
} else {
var condition = item.valueJS = finalizeLLVMParameter(item.value);
- var labelTrue = item.labelTrueJS = getPhiSetsForLabel(phiSets, item.labelTrue) + makeBranch(item.labelTrue, item.currLabelId);
- var labelFalse = item.labelFalseJS = getPhiSetsForLabel(phiSets, item.labelFalse) + makeBranch(item.labelFalse, item.currLabelId);
- if (RELOOP) return ';';
+ var labelTrue = (item.labelTrueJS = getPhiSetsForLabel(phiSets, item.labelTrue)) + makeBranch(item.labelTrue, item.currLabelId);
+ var labelFalse = (item.labelFalseJS = getPhiSetsForLabel(phiSets, item.labelFalse)) + makeBranch(item.labelFalse, item.currLabelId);
if (labelTrue == ';' && labelFalse == ';') return ';';
var head = 'if (' + condition + ') { ';
var head2 = 'if (!(' + condition + ')) { ';
@@ -1036,8 +1049,11 @@ function JSify(data, functionsOnly, givenFunctions) {
}
item.assignTo = null;
}
- ret += 'if (!__THREW__) { ' + getPhiSetsForLabel(phiSets, item.toLabel) + makeBranch(item.toLabel, item.currLabelId)
- + ' } else { ' + getPhiSetsForLabel(phiSets, item.unwindLabel) + makeBranch(item.unwindLabel, item.currLabelId) + ' }';
+ item.reloopingJS = ret; // everything but the actual branching (which the relooper will do for us)
+ item.toLabelJS = getPhiSetsForLabel(phiSets, item.toLabel);
+ item.unwindLabelJS = getPhiSetsForLabel(phiSets, item.unwindLabel);
+ ret += 'if (!__THREW__) { ' + item.toLabelJS + makeBranch(item.toLabel, item.currLabelId)
+ + ' } else { ' + item.unwindLabelJS + makeBranch(item.unwindLabel, item.currLabelId) + ' }';
return ret;
});
makeFuncLineActor('atomic', function(item) {