diff options
-rw-r--r-- | src/jsifier.js | 13 | ||||
-rw-r--r-- | src/preamble.js | 63 | ||||
-rw-r--r-- | tests/runner.py | 26 |
3 files changed, 67 insertions, 35 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 39bb87e6..b84b2cf9 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -19,15 +19,13 @@ function JSify(data) { }, }); - function makePointer(slab, pos) { + function makePointer(slab, pos, stacked) { // XXX hardcoded ptr impl if (slab == 'HEAP') return pos; if (slab[0] != '[') { slab = '[' + slab + ']'; } - return 'Pointer_make(' + slab + ', ' + (pos ? pos : 0) + ')'; - // return '{ slab: ' + slab + ', pos: ' + (pos ? pos : 0) + ' }'; - // return '[' + slab + ', ' + (pos ? pos : 0) + ']'; + return 'Pointer_make(' + slab + ', ' + (pos ? pos : 0) + (stacked ? ', true' : '') + ')'; } function makeGetSlab(ptr) { @@ -243,6 +241,7 @@ function JSify(data) { }).filter(function(param) { return param != null });; func.JS = '\nfunction ' + func.ident + '(' + params.join(', ') + ') {\n'; + func.JS += ' stackEnter();\n'; if (LABEL_DEBUG) func.JS += " print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n"; if (hasVarArgs) { @@ -479,7 +478,7 @@ function JSify(data) { return ret; }); makeFuncLineZyme('return', function(item) { - var ret = ''; + var ret = 'stackExit();\n'; if (LABEL_DEBUG) ret += "INDENT = INDENT.substr(0, INDENT.length-2);\n"; ret += 'return'; if (item.value) { @@ -513,9 +512,9 @@ function JSify(data) { dprint('alloca', dump(item)); if (pointingLevels(item.allocatedType.text) == 0 && isStructType(item.allocatedType.text)) { // TODO: allocate on a stack, not on the heap (we currently leak all this) - return makePointer(JSON.stringify(makeEmptyStruct(item.allocatedType.text))); + return makePointer(JSON.stringify(makeEmptyStruct(item.allocatedType.text)), null, true); } else { - return makePointer('[0]'); + return makePointer('[0]', null, true); } }); makeFuncLineZyme('phi', function(item) { diff --git a/src/preamble.js b/src/preamble.js index 2260d08a..467ac8e5 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -8,11 +8,6 @@ var __THREW__ = false; // Used in checking for thrown exceptions. var __ATEXIT__ = []; -var HEAP = []; -var HEAPTOP = 0; -Pointer_make(intArrayFromString('(null)')); // So printing %s of NULL gives '(null)' - // Also this ensures we leave 0 as an invalid address, 'NULL' - #if SAFE_HEAP // Semi-manual memory corruption debugging HEAP_WATCHED = {}; @@ -57,7 +52,7 @@ function Pointer_niceify(ptr) { // return ptr; } -function Pointer_make(slab, pos) { +function Pointer_make(slab, pos, stacked) { pos = pos ? pos : 0; // XXX hardcoded ptr impl if (slab === HEAP) return pos; @@ -68,7 +63,7 @@ function Pointer_make(slab, pos) { } var slab = flatten(slab); // Finalize - var ret = _malloc(Math.max(slab.length - pos, 1)); + var ret = (stacked ? stackAlloc : _malloc)(Math.max(slab.length - pos, 1)); for (var i = 0; i < slab.length - pos; i++) { #if SAFE_HEAP SAFE_HEAP_STORE(ret + i, slab[pos + i]); @@ -97,38 +92,54 @@ function Pointer_stringify(ptr) { return ret; } -function _malloc(size) { -// XXX hardcoded ptr impl +// Stack allocation +function stackEnter() { + STACK_STACK.push(STACKTOP); +} +function stackExit() { + STACKTOP = STACK_STACK.pop(); +} +function stackAlloc(size) { size = Math.ceil(size/QUANTUM_SIZE)*QUANTUM_SIZE; // Allocate blocks of proper minimum size - // Also keeps HEAPTOP aligned - var ret = HEAPTOP; - HEAPTOP += size; + // Also keeps STACKTOP aligned + var ret = STACKTOP; + STACKTOP += size; return ret; - // We don't actually do new Array(size) - memory is uninitialized anyhow -// return Pointer_make([]); } +// If we don't have malloc/free implemented, use a simple implementation. This +// allows compiled C/C++ to implement its own malloc/free +if (!this._malloc) { + _malloc = function(size) { + size = Math.ceil(size/QUANTUM_SIZE)*QUANTUM_SIZE; // Allocate blocks of proper minimum size + // Also keeps HEAPTOP aligned + var ret = HEAPTOP; + HEAPTOP += size; + return ret; + } + + _free = function(ptr) { + // XXX TODO - actual implementation! Currently we leak it all + } +} // Mangled "new"s... need a heuristic for autogeneration... __Znwj = _malloc; // gcc __Znaj = _malloc; // gcc __Znam = _malloc; // clang __Znwm = _malloc; // clang - -function _free(ptr) { -// XXX hardcoded ptr impl - // XXX TODO - actual implementation! Currently we leak it all - - // Nothing needs to be done! But we mark the pointer - // as invalid. Note that we should do it for all other - // pointers of this slab too. -// ptr.slab = null; -// ptr[0] = null; -} - // Mangled "delete"s... need a heuristic for autogeneration... __ZdlPv = _free; // gcc __ZdaPv = _free; // gcc +var HEAP = []; +var HEAPTOP = 0; +Pointer_make(intArrayFromString('(null)')); // So printing %s of NULL gives '(null)' + // Also this ensures we leave 0 as an invalid address, 'NULL' +STACK_STACK = []; +STACKTOP = HEAPTOP; +TOTAL_STACK = 64*1024; // Reserved room for stack +HEAPTOP += TOTAL_STACK; + // stdio.h // C-style: we work on ints on the HEAP. diff --git a/tests/runner.py b/tests/runner.py index 49b390fd..08560fd8 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -27,7 +27,7 @@ def timeout_run(proc, timeout, note): return proc.communicate()[0] class T(unittest.TestCase): - def do_test(self, src, expected_output, args=[], output_nicerizer=None, output_processor=None, no_python=False, no_build=False, main_file=None): + def do_test(self, src, expected_output, args=[], output_nicerizer=None, output_processor=None, no_build=False, main_file=None): global DEBUG dirname = TEMP_DIR + '/tmp' # tempfile.mkdtemp(dir=TEMP_DIR) if not os.path.exists(dirname): @@ -186,6 +186,28 @@ class T(unittest.TestCase): ''' self.do_test(src, '*3600*') + def test_stack(self): + src = ''' + #include <stdio.h> + int test(int i) { + int x = 10; + if (i > 0) { + return test(i-1); + } + return int(&x); + } + int main() + { + // We should get the same value for the first and last - stack has unwound + int x1 = test(0); + int x2 = test(100); + int x3 = test(0); + printf("*%d,%d*\\n", x3-x1, x2 != x1); + return 0; + } + ''' + self.do_test(src, '*0,1*') + def test_strings(self): src = ''' #include <stdio.h> @@ -759,7 +781,7 @@ class T(unittest.TestCase): (50,'''GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA*TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACAT*cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg**tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa**NtactMcSMtYtcMgRtacttctWBacgaa**agatactctgggcaacacacatacttctctcatgttgtttcttcggacctttcataacct**ttcctggcacatggttagctgcacatcacaggattgtaagggtctagtggttcagtgagc**ggaatatcattcgtcggtggtgttaatctatctcggtgtagcttataaatgcatccgtaa**gaatattatgtttatttgtcggtacgttcatggtagtggtgtcgccgatttagacgtaaa**ggcatgtatg*''') ] for i, j in results: src = open(path_from_root(['tests', 'fasta.cpp']), 'r').read() - self.do_test(src, j, [str(i)], lambda x: x.replace('\n', '*'), no_python=True, no_build=i>1) + self.do_test(src, j, [str(i)], lambda x: x.replace('\n', '*'), no_build=i>1) def test_sauer(self): # XXX Warning: Running this in SpiderMonkey can lead to an extreme amount of memory being |