aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralon@honor <none@none>2010-09-28 19:58:22 -0700
committeralon@honor <none@none>2010-09-28 19:58:22 -0700
commit76bb3eb098ba2a62be37d53323ebbea8e93e7f7c (patch)
tree99897d8f4fae5f7d300048461d70df9e29f2b92e
parenta13db65ea9daf3ecda49da0184ba12938c2218b4 (diff)
call stack implementation
-rw-r--r--src/jsifier.js13
-rw-r--r--src/preamble.js63
-rw-r--r--tests/runner.py26
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