aboutsummaryrefslogtreecommitdiff
path: root/src/jsifier.js
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-04-18 20:20:55 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-04-18 20:54:22 -0700
commitc0074e01ac06a66faf3e9d91f1cecb4ff02c7ee9 (patch)
tree0b8e70862b0a352ed5d58008b472c657057c6ad6 /src/jsifier.js
parentd9173c5dfb0c58a7d5be96f1e4615cefd77f6f43 (diff)
setjmp support for asm.js
Diffstat (limited to 'src/jsifier.js')
-rw-r--r--src/jsifier.js44
1 files changed, 33 insertions, 11 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index a4dd797b..7086922c 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -701,18 +701,22 @@ function JSify(data, functionsOnly, givenFunctions) {
ret += indent + 'label = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n';
} // otherwise, should have been set before!
if (func.setjmpTable) {
- assert(!ASM_JS, 'asm.js mode does not support setjmp yet');
- var setjmpTable = {};
- ret += indent + 'var mySetjmpIds = {};\n';
- ret += indent + 'var setjmpTable = {';
- func.setjmpTable.forEach(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
- ret += '"' + getLabelId(triple[0]) + '": ' + 'function(value) { label = ' + getLabelId(triple[1]) + '; ' + triple[2] + ' = value },';
- });
- ret += 'dummy: 0';
- ret += '};\n';
+ if (!ASM_JS) {
+ var setjmpTable = {};
+ ret += indent + 'var mySetjmpIds = {};\n';
+ ret += indent + 'var setjmpTable = {';
+ func.setjmpTable.forEach(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
+ ret += '"' + getLabelId(triple.oldLabel) + '": ' + 'function(value) { label = ' + getLabelId(triple.newLabel) + '; ' + triple.assignTo + ' = value },';
+ });
+ ret += 'dummy: 0';
+ ret += '};\n';
+ } else {
+ ret += 'var setjmpLabel = 0;\n';
+ ret += 'var setjmpTable = ' + RuntimeGenerator.stackAlloc(4 * (MAX_SETJMPS + 1) * 2) + ';\n';
+ }
}
ret += indent + 'while(1) ';
- if (func.setjmpTable) {
+ if (func.setjmpTable && !ASM_JS) {
ret += 'try { ';
}
ret += 'switch(' + asmCoercion('label', 'i32') + ') {\n';
@@ -720,9 +724,19 @@ function JSify(data, functionsOnly, givenFunctions) {
return indent + ' case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
+ getLabelLines(label, indent + ' ');
}).join('\n') + '\n';
+ if (func.setjmpTable && ASM_JS) {
+ // emit a label in which we write to the proper local variable, before jumping to the actual label
+ ret += ' case -1111: ';
+ ret += func.setjmpTable.map(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
+ return 'if ((setjmpLabel|0) == ' + getLabelId(triple.oldLabel) + ') { ' + triple.assignTo + ' = threwValue; label = ' + triple.newLabel + ' }\n';
+ }).join(' else ');
+ if (ASSERTIONS) ret += 'else abort(-3);\n';
+ ret += '__THREW__ = threwValue = 0;\n';
+ ret += 'break;\n';
+ }
if (ASSERTIONS) ret += indent + ' default: assert(0' + (ASM_JS ? '' : ', "bad label: " + label') + ');\n';
ret += indent + '}\n';
- if (func.setjmpTable) {
+ if (func.setjmpTable && !ASM_JS) {
ret += ' } catch(e) { if (!e.longjmp || !(e.id in mySetjmpIds)) throw(e); setjmpTable[setjmpLabels[e.id]](e.value) }';
}
} else {
@@ -1301,6 +1315,8 @@ function JSify(data, functionsOnly, givenFunctions) {
// We cannot compile assembly. See comment in intertyper.js:'Call'
assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
+ if (ASM_JS && funcData.setjmpTable) forceByPointer = true; // in asm.js mode, we must do an invoke for each call
+
ident = Variables.resolveAliasToIdent(ident);
var shortident = ident.slice(1);
var simpleIdent = shortident;
@@ -1455,6 +1471,12 @@ function JSify(data, functionsOnly, givenFunctions) {
ret += '; return 0'; // special case: abort() can happen without return, breaking the return type of asm functions. ensure a return
}
}
+
+ if (ASM_JS && funcData.setjmpTable) {
+ // check if a longjmp was done
+ ret += '; if (((__THREW__|0) != 0) & ((threwValue|0) > 0)) { setjmpLabel = _testSetjmp(' + makeGetValue('__THREW__', 0, 'i32') + ', setjmpTable); if ((setjmpLabel|0) > 0) { label = -1111; break } } __THREW__ = threwValue = 0;\n';
+ }
+
return ret;
}
makeFuncLineActor('getelementptr', function(item) { return finalizeLLVMFunctionCall(item) });