aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler.js4
-rw-r--r--src/jsifier.js82
-rw-r--r--src/library.js35
-rw-r--r--src/parseTools.js39
-rw-r--r--src/postamble.js6
-rw-r--r--src/preamble.js70
-rw-r--r--src/settings.js1
-rw-r--r--tests/runner.py72
-rw-r--r--tests/settings.py13
9 files changed, 227 insertions, 95 deletions
diff --git a/src/compiler.js b/src/compiler.js
index ba36f215..13b2d3cc 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -29,6 +29,10 @@ for (setting in settings) {
this[setting] = settings[setting];
}
+// Sanity of settings
+
+assert(!(USE_TYPED_ARRAYS && SAFE_HEAP));
+
// Read llvm
var lines = [];
var line;
diff --git a/src/jsifier.js b/src/jsifier.js
index bcc436a4..547bde72 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -4,6 +4,10 @@ function JSify(data) {
substrate = new Substrate('JSifyer');
var TYPES = data.types;
+ var FUNCTIONS = {};
+ data.functions.forEach(function(func) {
+ FUNCTIONS[func.ident] = func;
+ });
// type
substrate.addZyme('Type', {
@@ -20,20 +24,29 @@ function JSify(data) {
});
function makePointer(slab, pos, allocator, type) { // type is FFU
- if (slab == 'HEAP') return pos;
+ if (slab in set('HEAP', 'IHEAP', 'FHEAP')) return pos;
if (slab[0] != '[') {
slab = '[' + slab + ']';
}
return 'Pointer_make(' + slab + ', ' + (pos ? pos : 0) + (allocator ? ', ' + allocator : '') + ')';
}
- function makeGetSlab(ptr) {
- // return ptr + '.slab';
- return 'HEAP';
+ function makeGetSlab(ptr, type) {
+ assert(type);
+ if (!USE_TYPED_ARRAYS) {
+ return 'HEAP';
+ } else {
+ if (type in FLOAT_TYPES || type === 'int64') {
+ return 'FHEAP';
+ } else if (type in INT_TYPES || isPointerType(type)) {
+ return 'IHEAP';
+ } else {
+ return 'HEAP';
+ }
+ }
}
function makeGetPos(ptr) {
- // return ptr + '.pos';
return ptr;
}
@@ -43,15 +56,23 @@ function JSify(data) {
}
function makeGetValue(ptr, pos, noNeedFirst, type) {
- return makeGetSlab(ptr) + '[' + calcFastOffset(ptr, pos, noNeedFirst) + ']';
+ return makeGetSlab(ptr, type) + '[' + calcFastOffset(ptr, pos, noNeedFirst) + ']';
+ }
+
+ function indexizeFunctions(value) { // TODO: Also check for other functions (externals, library, etc.)
+ if (value in FUNCTIONS) {
+ value = value + '.__index__'; // Store integer value
+ }
+ return value;
}
function makeSetValue(ptr, pos, value, noNeedFirst, type) {
+ value = indexizeFunctions(value);
var offset = calcFastOffset(ptr, pos, noNeedFirst);
if (SAFE_HEAP) {
return 'SAFE_HEAP_STORE(' + offset + ', ' + value + ')';
} else {
- return makeGetSlab(ptr) + '[' + offset + '] = ' + value;
+ return makeGetSlab(ptr, type) + '[' + offset + '] = ' + value;
}
}
@@ -135,7 +156,7 @@ function JSify(data) {
throw 'Invalid segment: ' + dump(segment);
}
};
- return splitTokenList(tokens).map(handleSegment).map(parseNumerical);
+ return splitTokenList(tokens).map(handleSegment).map(parseNumerical).map(indexizeFunctions);
}
if (value.item) {
// list of items
@@ -206,6 +227,17 @@ function JSify(data) {
this.forwardItems(ret, 'FuncLineTriager');
},
});
+
+ var FUNCTION_INDEX = 0;
+ var FUNCTION_HASH = {};
+ function getFunctionIndex(name_) {
+ if (!(name_ in FUNCTION_HASH)) {
+ FUNCTION_HASH[name_] = FUNCTION_INDEX;
+ FUNCTION_INDEX++;
+ }
+ return FUNCTION_HASH[name_];
+ }
+
// function reconstructor & post-JS optimizer
substrate.addZyme('FunctionReconstructor', {
funcs: {},
@@ -339,14 +371,21 @@ function JSify(data) {
// Finalize function
if (LABEL_DEBUG) func.JS += " INDENT = INDENT.substr(0, INDENT.length-2);\n";
func.JS += '}\n';
+ func.JS += func.ident + '.__index__ = ' + getFunctionIndex(func.ident) + ';\n';
+ func.JS += 'FUNCTION_TABLE[' + getFunctionIndex(func.ident) + '] = ' + func.ident + ';\n';
func.__result__ = true;
return func;
},
});
- function getVarData(funcData, ident) {
- if (funcData.variables[ident]) {
- return funcData.variables[ident].impl;
+ function getVarData(funcData, ident) { // XXX - need to check globals as well!
+ return funcData.variables[ident];
+ }
+
+ function getVarImpl(funcData, ident) {
+ var data = getVarData(funcData, ident);
+ if (data) {
+ return data.impl;
} else {
return 'emulated'; // All global are emulated
}
@@ -383,7 +422,7 @@ function JSify(data) {
var type = item.value.type;
var value = parseNumerical(item.value.JS);
//print("zz var: " + item.JS);
- var impl = getVarData(item.funcData, item.ident);
+ var impl = getVarImpl(item.funcData, item.ident);
switch (impl) {
case VAR_NATIVE: {
break;
@@ -422,7 +461,7 @@ function JSify(data) {
}
var impl = VAR_EMULATED;
if (item.pointer.intertype == 'value') {
- impl = getVarData(item.funcData, item.ident);
+ impl = getVarImpl(item.funcData, item.ident);
}
switch (impl) {
case VAR_NATIVIZED:
@@ -537,7 +576,7 @@ function JSify(data) {
});
makeFuncLineZyme('load', function(item) {
var ident = toNiceIdent(item.ident);
- var impl = getVarData(item.funcData, item.ident);
+ var impl = getVarImpl(item.funcData, item.ident);
switch (impl) {
case VAR_NATIVIZED: {
return ident; // We have the actual value here
@@ -721,7 +760,7 @@ function JSify(data) {
function finalizeLLVMFunctionCall(item) {
switch(item.intertype) {
case 'getelementptr':
- return makePointer(makeGetSlab(item.ident), getGetElementPtrIndexes(item), null, item.type);
+ return makePointer(makeGetSlab(item.ident, item.type), getGetElementPtrIndexes(item), null, item.type);
case 'bitcast':
case 'inttoptr':
case 'ptrtoint':
@@ -747,7 +786,7 @@ function JSify(data) {
return ident;
});
- function makeFunctionCall(ident, params) {
+ function makeFunctionCall(ident, params, funcData) {
// Special cases
if (ident == '_llvm_va_start') {
var args = 'Array.prototype.slice.call(arguments, __numArgs__)';
@@ -755,7 +794,7 @@ function JSify(data) {
if (SAFE_HEAP) {
return 'SAFE_HEAP_STORE(' + params[0].ident + ', ' + data + ', 0)';
} else {
- return 'HEAP[' + params[0].ident + '] = ' + data;
+ return 'IHEAP[' + params[0].ident + '] = ' + data;
}
} else if (ident == '_llvm_va_end') {
return ';'
@@ -767,12 +806,17 @@ function JSify(data) {
} else {
return toNiceIdent(param.ident);
}
- });
+ }).map(indexizeFunctions);
+
+ if (funcData && getVarData(funcData, ident)) {
+ ident = 'FUNCTION_TABLE[' + ident + ']';
+ }
+
return ident + '(' + params.join(', ') + ')';
}
makeFuncLineZyme('getelementptr', function(item) { return finalizeLLVMFunctionCall(item) });
makeFuncLineZyme('call', function(item) {
- return makeFunctionCall(item.ident, item.params) + (item.standalone ? ';' : '');
+ return makeFunctionCall(item.ident, item.params, item.funcData) + (item.standalone ? ';' : '');
});
// Optimzed intertypes
diff --git a/src/library.js b/src/library.js
index 09c4d8f1..0663d6c1 100644
--- a/src/library.js
+++ b/src/library.js
@@ -19,11 +19,11 @@ var Library = {
},
vsnprintf: function(dst, num, src, ptr) {
- var args = Array_copy(ptr+1, HEAP[ptr]); // # of args in in first place
+ var args = Array_copy(ptr+1, IHEAP[ptr]); // # of args in in first place
var text = __formatString.apply(null, [src].concat(args));
for (var i = 0; i < num; i++) {
- HEAP[dst+i] = HEAP[text+i];
- if (HEAP[dst+i] == 0) break;
+ IHEAP[dst+i] = IHEAP[text+i];
+ if (IHEAP[dst+i] == 0) break;
}
},
@@ -42,7 +42,7 @@ var Library = {
strlen: function(p) {
var q = p;
- while (HEAP[q] != 0) q++;
+ while (IHEAP[q] != 0) q++;
return q - p;
},
@@ -65,22 +65,22 @@ var Library = {
strcpy: function(pdest, psrc) {
var i = 0;
do {
- HEAP[pdest+i] = HEAP[psrc+i];
+ IHEAP[pdest+i] = IHEAP[psrc+i];
i ++;
- } while (HEAP[psrc+i-1] != 0);
+ } while (IHEAP[psrc+i-1] != 0);
},
strncpy: function(pdest, psrc, num) {
var padding = false;
for (var i = 0; i < num; i++) {
- HEAP[pdest+i] = padding ? 0 : HEAP[psrc+i];
- padding = padding || HEAP[psrc+i] == 0;
+ IHEAP[pdest+i] = padding ? 0 : IHEAP[psrc+i];
+ padding = padding || IHEAP[psrc+i] == 0;
}
},
strlen: function(ptr) {
var i = 0;
- while (HEAP[ptr+i] != 0) i++;
+ while (IHEAP[ptr+i] != 0) i++;
return i;
},
@@ -88,9 +88,9 @@ var Library = {
var len = Pointer_stringify(pdest).length; // TODO: use strlen, but need dependencies system
var i = 0;
do {
- HEAP[pdest+len+i] = HEAP[psrc+i];
+ IHEAP[pdest+len+i] = IHEAP[psrc+i];
i ++;
- } while (HEAP[psrc+i-1] != 0);
+ } while (IHEAP[psrc+i-1] != 0);
},
strtol: function(ptr) {
@@ -101,8 +101,8 @@ var Library = {
strcmp: function(px, py) {
var i = 0;
while (true) {
- var x = HEAP[px+i];
- var y = HEAP[py+i];
+ var x = IHEAP[px+i];
+ var y = IHEAP[py+i];
if (x == y && x == 0) return 0;
if (x == 0) return -1;
if (y == 0) return 1;
@@ -132,13 +132,6 @@ var Library = {
return 0;
},
- llvm_memset_i32: function(ptr, value, num) {
- for (var i = 0; i < num; i++) {
- HEAP[ptr+i] = value;
- }
- },
- llvm_memset_p0i8_i32: 'llvm_memset_i32',
-
llvm_eh_exception: function() {
return 'code-generated exception: ' + (new Error().stack);
},
@@ -229,7 +222,7 @@ var Library = {
time: function(ptr) {
var ret = Math.floor(Date.now()/1000);
if (ptr) {
- HEAP[ptr] = ret;
+ IHEAP[ptr] = ret;
}
return ret;
},
diff --git a/src/parseTools.js b/src/parseTools.js
index c4dae65e..4d1ed438 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -8,26 +8,27 @@ function preprocess(text, constants) {
}
var lines = text.split('\n');
var ret = '';
- var show = true;
+ var showStack = [];
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (line[0] != '#') {
- if (show) {
+ if (showStack.indexOf(false) == -1) {
ret += line + '\n';
}
} else {
if (line[1] == 'i') { // if
var ident = line.substr(4);
- show = !!this[ident] && this[ident] > 0;
+ showStack.push(!!this[ident] && this[ident] > 0);
} else if (line[2] == 'l') { // else
- show = !show;
+ showStack.push(!showStack.pop());
} else if (line[2] == 'n') { // endif
- show = true;
+ showStack.pop();
} else {
throw "Unclear preprocessor command: " + line;
}
}
}
+ assert(showStack.length == 0);
return ret;
}
@@ -47,6 +48,10 @@ function pointingLevels(type) {
return ret;
}
+function removeAllPointing(type) {
+ return removePointing(type, pointingLevels(type));
+}
+
function toNiceIdent(ident) {
assert(ident);
if (parseFloat(ident) == ident) return ident;
@@ -80,7 +85,7 @@ function isStructType(type) {
return !isNumberType(type) && type[0] == '%';
}
-function isPointerType(type) { // TODO!
+function isPointerType(type) {
return pointingLevels(type) > 0;
}
@@ -88,18 +93,13 @@ function isVoidType(type) {
return type == 'void';
}
-function isType(type) { // TODO!
- return isVoidType(type) || isNumberType(type) || isStructType(type) || isPointerType(type);
-}
-
// Detects a function definition, ([...|type,[type,...]])
function isFunctionDef(token) {
var text = token.text;
- var pointing = pointingLevels(text);
- var nonPointing = removePointing(text, pointing);
+ var nonPointing = removeAllPointing(text);
if (nonPointing[0] != '(' || nonPointing.substr(-1) != ')')
return false;
- if (nonPointing == '(...)') return true;
+ if (nonPointing in set('()', '(...)')) return true;
if (!token.item) return false;
var fail = false;
splitTokenList(token.item[0].tokens).forEach(function(segment) {
@@ -109,6 +109,19 @@ function isFunctionDef(token) {
return !fail;
}
+function isFunctionType(type) {
+ var parts = type.split(' ');
+ if (parts.length != 2) return false;
+ if (pointingLevels(type) !== 1) return false;
+ var text = removeAllPointing(parts[1]);
+ var ret = isType(parts[0]) && isFunctionDef({ text: text, item: [{tokens: [{text: text.substr(1, text.length-2)}]}] });
+ return ret;
+}
+
+function isType(type) { // TODO!
+ return isVoidType(type) || isNumberType(type) || isStructType(type) || isPointerType(type) || isFunctionType(type);
+}
+
function addIdent(token) {
token.ident = token.text;
return token;
diff --git a/src/postamble.js b/src/postamble.js
index 1329a1a4..07fe1d2e 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -23,7 +23,11 @@ function run(args) {
_main(argc, argv);
while( __ATEXIT__.length > 0) {
- __ATEXIT__.pop()();
+ var func = __ATEXIT__.pop();
+ if (typeof func === 'number') {
+ func = FUNCTION_TABLE[func];
+ }
+ func();
}
}
diff --git a/src/preamble.js b/src/preamble.js
index 5496170d..1af1a6e9 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -3,6 +3,10 @@
function __globalConstructor__() {
}
+// Maps ints ==> functions. This lets us pass around ints, which are
+// actually pointers to functions, and we convert at call()time
+FUNCTION_TABLE = [];
+
var __THREW__ = false; // Used in checking for thrown exceptions.
var __ATEXIT__ = [];
@@ -43,7 +47,7 @@ function assert(condition, text) {
}
function Pointer_niceify(ptr) {
- return { slab: HEAP, pos: ptr };
+ return { slab: IHEAP, pos: ptr };
}
// Creates a pointer for a certain slab and a certain address in that slab.
@@ -70,8 +74,19 @@ function Pointer_make(slab, pos, allocator) {
#if SAFE_HEAP
SAFE_HEAP_STORE(ret + i, slab[pos + i]);
#else
+#if USE_TYPED_ARRAYS
+ // TODO: Check - also in non-typedarray case - for functions, and if so add |.__index__|
+ var curr = slab[pos + i];
+ if (typeof curr === 'number') {
+ IHEAP[ret + i] = curr; // TODO: optimize. Can easily detect floats, but 1.0 might look like an int...
+ FHEAP[ret + i] = curr;
+ } else {
+ HEAP[ret + i] = curr;
+ }
+#else
HEAP[ret + i] = slab[pos + i];
#endif
+#endif
}
return ret;
}
@@ -118,10 +133,28 @@ __ZdaPv = _free; // llvm-gcc
function __initializeRuntime__() {
HEAP = intArrayFromString('(null)'); // So printing %s of NULL gives '(null)'
// Also this ensures we leave 0 as an invalid address, 'NULL'
+#if USE_TYPED_ARRAYS
+ if (!this['TOTAL_MEMORY']) TOTAL_MEMORY = 50*1024*1024;
+ if (this['Int32Array']) { // check for engine support
+ IHEAP = new Int32Array(TOTAL_MEMORY);
+ for (var i = 0; i < HEAP.length; i++) {
+ IHEAP[i] = HEAP[i];
+ }
+ } else {
+ IHEAP = HEAP; // fallback
+ }
+ if (this['Float64Array']) { // check for engine support
+ FHEAP = new Float64Array(TOTAL_MEMORY);
+ } else {
+ FHEAP = HEAP; // fallback
+ }
+#else
+ IHEAP = HEAP; // We use that name in our runtime code that processes strings etc., see library.js
+#endif
STACK_STACK = [];
STACK_ROOT = STACKTOP = alignMemoryPage(10);
- if (!this['TOTAL_STACK']) TOTAL_STACK = 64*1024*100; // Reserved room for stack
+ if (!this['TOTAL_STACK']) TOTAL_STACK = 1024*1024; // Reserved room for stack
STACK_MAX = STACK_ROOT + TOTAL_STACK;
STATICTOP = alignMemoryPage(STACK_MAX);
@@ -136,13 +169,22 @@ function __formatString() {
var ret = [];
var curr = -1;
while (curr != 0) {
+#if USE_TYPED_ARRAYS
+ curr = IHEAP[textIndex];
+ next = IHEAP[textIndex+1];
+#else
curr = HEAP[textIndex];
next = HEAP[textIndex+1];
+#endif
if (curr == '%'.charCodeAt(0) && ['d', 'u', 'f', '.'].indexOf(String.fromCharCode(next)) != -1) {
var argText = String(arguments[argIndex]);
// Handle very very simply formatting, namely only %.Xf
if (next == '.'.charCodeAt(0)) {
+#if USE_TYPED_ARRAYS
+ var limit = parseInt(String.fromCharCode(IHEAP[textIndex+2]));
+#else
var limit = parseInt(String.fromCharCode(HEAP[textIndex+2]));
+#endif
var dotIndex = argText.indexOf('.');
if (dotIndex == -1) {
dotIndex = argText.length;
@@ -174,14 +216,16 @@ function __formatString() {
// Copies a list of num items on the HEAP into a
// a normal JavaScript array of numbers
function Array_copy(ptr, num) {
- // XXX hardcoded ptr impl
- return HEAP.slice(ptr, ptr+num);
+#if USE_TYPED_ARRAYS
+ return Array.prototype.slice.call(IHEAP.slice(ptr, ptr+num)); // Make a normal array out of the typed one
+#else
+ return IHEAP.slice(ptr, ptr+num);
+#endif
}
// Copies a C-style string, terminated by a zero, from the HEAP into
// a normal JavaScript array of numbers
function String_copy(ptr, addZero) {
- // XXX hardcoded ptr impl
return Array_copy(ptr, _strlen(ptr)).concat(addZero ? [0] : []);
}
@@ -199,6 +243,11 @@ function _llvm_memcpy_i32(dest, src, num, idunno) {
SAFE_HEAP_STORE(dest + i, HEAP[src + i]);
#else
HEAP[dest + i] = HEAP[src + i];
+#if USE_TYPED_ARRAYS
+ // TODO: optimize somehow - this is slower than without typed arrays
+ IHEAP[dest + i] = IHEAP[src + i];
+ FHEAP[dest + i] = FHEAP[src + i];
+#endif
#endif
}
// dest = Pointer_niceify(dest);
@@ -208,6 +257,17 @@ function _llvm_memcpy_i32(dest, src, num, idunno) {
_llvm_memcpy_i64 = _llvm_memcpy_i32;
_llvm_memcpy_p0i8_p0i8_i32 = _llvm_memcpy_i32;
+function llvm_memset_i32(ptr, value, num) {
+ for (var i = 0; i < num; i++) {
+#if USE_TYPED_ARRAYS
+ HEAP[ptr+i] = IHEAP[ptr+i] = FHEAP[ptr+i] = value;
+#else
+ HEAP[ptr+i] = value;
+#endif
+ }
+}
+_llvm_memset_p0i8_i32 = llvm_memset_i32;
+
// Tools
PRINTBUFFER = '';
diff --git a/src/settings.js b/src/settings.js
index d79869f1..6b621770 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -25,6 +25,7 @@ GUARD_MEMORY = 1; // Whether we should check that each allocation to the stack d
// Code embetterments
OPTIMIZE = 0; // Optimize llvm operations into js commands
RELOOP = 0; // Recreate js native loops from llvm data
+USE_TYPED_ARRAYS = 0; // Try to use typed arrays for the heap
// Generated code debugging options
SAFE_HEAP = 0; // Check each write to the heap against a list of blocked addresses
diff --git a/tests/runner.py b/tests/runner.py
index 3cd99993..44b5f272 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -69,17 +69,19 @@ class RunnerCore(unittest.TestCase):
output = Popen([LLVM_DIS, filename + '.o'] + LLVM_DIS_OPTS + ['-o=' + filename + '.o.ll'], stdout=PIPE, stderr=STDOUT).communicate()[0]
# Run Emscripten
- emscripten_settings = ['{ "QUANTUM_SIZE": %d, "RELOOP": %d, "OPTIMIZE": %d, "GUARD_MEMORY": %d }' % (QUANTUM_SIZE, RELOOP, OPTIMIZE, GUARD_MEMORY)]
+ exported_settings = {}
+ for setting in ['QUANTUM_SIZE', 'RELOOP', 'OPTIMIZE', 'GUARD_MEMORY', 'USE_TYPED_ARRAYS']:
+ exported_settings[setting] = eval(setting)
out = open(filename + '.o.js', 'w') if not OUTPUT_TO_SCREEN else None
- timeout_run(Popen([EMSCRIPTEN, filename + '.o.ll', PARSER_ENGINE] + emscripten_settings, stdout=out, stderr=STDOUT), 240, 'Compiling')
+ timeout_run(Popen([EMSCRIPTEN, filename + '.o.ll', COMPILER_ENGINE[0], str(exported_settings).replace("'", '"')], stdout=out, stderr=STDOUT), 240, 'Compiling')
output = open(filename + '.o.js').read()
if output_processor is not None:
output_processor(output)
if output is not None and 'Traceback' in output: print output; assert 0
- def run_generated_code(self, filename, args=[], check_timeout=True):
- return timeout_run(Popen([JS_ENGINE] + JS_ENGINE_OPTS + [filename] + ([] if JS_ENGINE == SPIDERMONKEY_ENGINE else ['--']) + args,
- stdout=PIPE, stderr=STDOUT), 120 if check_timeout else None, 'Execution')
+ def run_generated_code(self, engine, filename, args=[], check_timeout=True):
+ return timeout_run(Popen(engine + [filename] + ([] if engine == SPIDERMONKEY_ENGINE else ['--']) + args,
+ stdout=PIPE, stderr=STDOUT), 30 if check_timeout else None, 'Execution')
if 'benchmark' not in sys.argv:
class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline
@@ -92,12 +94,14 @@ if 'benchmark' not in sys.argv:
if not no_build:
self.build(src, dirname, filename, output_processor, main_file)
- # Run
- js_output = self.run_generated_code(filename + '.o.js', args)
- if output_nicerizer is not None:
- js_output = output_nicerizer(js_output)
- self.assertContained(expected_output, js_output)
- self.assertNotContained('ERROR', js_output)
+ # Run in both JavaScript engines, if optimizing - significant differences there (typed arrays)
+ engines = [V8_ENGINE] if not OPTIMIZE else [V8_ENGINE, SPIDERMONKEY_ENGINE]
+ for engine in engines:
+ js_output = self.run_generated_code(engine, filename + '.o.js', args)
+ if output_nicerizer is not None:
+ js_output = output_nicerizer(js_output)
+ self.assertContained(expected_output, js_output)
+ self.assertNotContained('ERROR', js_output)
#shutil.rmtree(dirname) # TODO: leave no trace in memory. But for now nice for debugging
@@ -475,6 +479,26 @@ if 'benchmark' not in sys.argv:
'''
self.do_test(src, '*11,74*')
+ def test_funcptr(self):
+ src = '''
+ #include <stdio.h>
+ int calc1() { return 26; }
+ int calc2() { return 90; }
+ typedef int (*fp_t)();
+ int main()
+ {
+ fp_t fp = calc1;
+ void *vp = (void*)fp;
+ fp_t fpb = (fp_t)vp;
+ fp_t fp2 = calc2;
+ void *vp2 = (void*)fp2;
+ fp_t fpb2 = (fp_t)vp2;
+ printf("*%d,%d,%d,%d*\\n", fp(), fpb(), fp2(), fpb2());
+ return 0;
+ }
+ '''
+ self.do_test(src, '*26,26,90,90*')
+
def test_emptyclass(self):
src = '''
#include <stdio.h>
@@ -849,7 +873,7 @@ if 'benchmark' not in sys.argv:
def test_sauer(self):
# XXX Warning: Running this in SpiderMonkey can lead to an extreme amount of memory being
# used, see Mozilla bug 593659.
- assert PARSER_ENGINE != SPIDERMONKEY_ENGINE
+ assert COMPILER_ENGINE != SPIDERMONKEY_ENGINE
self.do_test(path_from_root(['tests', 'sauer']), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp')
@@ -857,15 +881,10 @@ if 'benchmark' not in sys.argv:
def make_test(compiler, embetter):
class TT(T):
def setUp(self):
- global COMPILER
+ global COMPILER, QUANTUM_SIZE, RELOOP, OPTIMIZE, GUARD_MEMORY, USE_TYPED_ARRAYS
COMPILER = compiler['path']
- global QUANTUM_SIZE
QUANTUM_SIZE = compiler['quantum_size']
- global RELOOP
- RELOOP = embetter
- global OPTIMIZE
- OPTIMIZE = embetter
- global GUARD_MEMORY
+ RELOOP = OPTIMIZE = USE_TYPED_ARRAYS = embetter
GUARD_MEMORY = 1-embetter
return TT
for embetter in [0,1]:
@@ -879,15 +898,14 @@ else:
sys.argv = filter(lambda x: x != 'benchmark', sys.argv)
COMPILER = LLVM_GCC
- PARSER_ENGINE = V8_ENGINE
JS_ENGINE = SPIDERMONKEY_ENGINE
- if JS_ENGINE == SPIDERMONKEY_ENGINE:
- JS_ENGINE_OPTS += ['-j', '-m'] # TODO: use this everywhere else
+ #JS_ENGINE = V8_ENGINE
- RELOOP = OPTIMIZE = 1
- GUARD_MEMORY = 0
QUANTUM_SIZE = 1
- TEST_REPS = 20
+ RELOOP = OPTIMIZE = USE_TYPED_ARRAYS = 1
+ GUARD_MEMORY = 0
+
+ TEST_REPS = 10
TOTAL_TESTS = 2
tests_done = 0
@@ -913,7 +931,7 @@ else:
times = []
for i in range(TEST_REPS):
start = time.time()
- self.run_generated_code(filename + '.o.js', args, check_timeout=False)
+ self.run_generated_code(JS_ENGINE, filename + '.o.js', args, check_timeout=False)
curr = time.time()-start
times.append(curr)
total_times[i] += curr
@@ -936,7 +954,7 @@ else:
self.do_benchmark(src, ['5', '64'])
if __name__ == '__main__':
- for cmd in map(lambda compiler: compiler['path'], COMPILERS.values()) + [LLVM_DIS, PARSER_ENGINE, JS_ENGINE]:
+ for cmd in map(lambda compiler: compiler['path'], COMPILERS.values()) + [LLVM_DIS, SPIDERMONKEY_ENGINE[0], V8_ENGINE[0]]:
print "Checking for existence of", cmd
assert(os.path.exists(cmd))
print "Running Emscripten tests..."
diff --git a/tests/settings.py b/tests/settings.py
index 4702dc09..9452fa81 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -25,18 +25,13 @@ LLVM_DIS_OPTS = []
if '2.8' in LLVM_ROOT:
LLVM_DIS_OPTS += ['-show-annotations']
-SPIDERMONKEY_ENGINE=os.path.expanduser('~/Dev/mozilla-central/js/src/js')
-V8_ENGINE=os.path.expanduser('~/Dev/v8/d8')
+SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/mozilla-central/js/src/js'), '-m'] # No |-j| due to Mozilla bug XXX
+V8_ENGINE = [os.path.expanduser('~/Dev/v8/d8')]
# XXX Warning: Compiling the 'sauer' test in SpiderMonkey can lead to an extreme amount of memory being
# used, see Mozilla bug 593659. Possibly also some other tests as well.
-#PARSER_ENGINE=SPIDERMONKEY_ENGINE
-PARSER_ENGINE=V8_ENGINE
-
-#JS_ENGINE=SPIDERMONKEY_ENGINE
-JS_ENGINE=V8_ENGINE
-
-JS_ENGINE_OPTS=[]
+#COMPILER_ENGINE=SPIDERMONKEY_ENGINE
+COMPILER_ENGINE=V8_ENGINE
OUTPUT_TO_SCREEN = 0 # useful for debugging specific tests, or for subjectively seeing what parts are slow