diff options
author | alon@honor <none@none> | 2010-10-02 12:03:07 -0700 |
---|---|---|
committer | alon@honor <none@none> | 2010-10-02 12:03:07 -0700 |
commit | 51d1c32a775cbb4ac578911fe1ae03b064a792bd (patch) | |
tree | a9903e22ed5bcfba177bad8f93c12268b5f61279 | |
parent | a3f35c0ffd4b6c3e38752ea8ff1e3fc2101a313b (diff) |
memory implementation cleanup
-rw-r--r-- | src/jsifier.js | 13 | ||||
-rw-r--r-- | src/library.js | 17 | ||||
-rw-r--r-- | src/postamble.js | 6 | ||||
-rw-r--r-- | src/preamble.js | 60 | ||||
-rw-r--r-- | src/settings.js | 1 | ||||
-rw-r--r-- | tests/runner.py | 2 | ||||
-rw-r--r-- | tests/settings.py | 2 |
7 files changed, 62 insertions, 39 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 057130e8..4e47bdf6 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -95,12 +95,12 @@ function JSify(data) { function parseConst(value, type) { dprint('gconst', '//yyyyy ' + JSON.stringify(value) + ',' + type + '\n'); if (isNumberType(type) || pointingLevels(type) == 1) { - return makePointer(parseNumerical(value.text), null, 'ALLOC_UNFREEABLE'); + return makePointer(parseNumerical(value.text), null, 'ALLOC_STATIC'); } else if (value.text == 'zeroinitializer') { - return makePointer(JSON.stringify(makeEmptyStruct(type)), null, 'ALLOC_UNFREEABLE'); + return makePointer(JSON.stringify(makeEmptyStruct(type)), null, 'ALLOC_STATIC'); } else if (value.text && value.text[0] == '"') { value.text = value.text.substr(1, value.text.length-2); - return makePointer(JSON.stringify(parseLLVMString(value.text)) + ' /* ' + value.text + '*/', null, 'ALLOC_UNFREEABLE'); + return makePointer(JSON.stringify(parseLLVMString(value.text)) + ' /* ' + value.text + '*/', null, 'ALLOC_STATIC'); } else { // Gets an array of constant items, separated by ',' tokens function handleSegments(tokens) { @@ -136,12 +136,12 @@ function JSify(data) { } if (value.item) { // list of items - return makePointer('[ ' + alignStruct(handleSegments(value.item[0].tokens), type).join(', ') + ' ]', null, 'ALLOC_UNFREEABLE'); + return makePointer('[ ' + alignStruct(handleSegments(value.item[0].tokens), type).join(', ') + ' ]', null, 'ALLOC_STATIC'); } else if (value.type == '{') { // struct - return makePointer('[ ' + alignStruct(handleSegments(value.tokens), type).join(', ') + ' ]', null, 'ALLOC_UNFREEABLE'); + return makePointer('[ ' + alignStruct(handleSegments(value.tokens), type).join(', ') + ' ]', null, 'ALLOC_STATIC'); } else if (value[0]) { - return makePointer('[ ' + alignStruct(handleSegments(value[0].tokens), type).join(', ') + ' ]', null, 'ALLOC_UNFREEABLE'); + return makePointer('[ ' + alignStruct(handleSegments(value[0].tokens), type).join(', ') + ' ]', null, 'ALLOC_STATIC'); } else { throw '// failzzzzzzzzzzzzzz ' + dump(value.item) + ' ::: ' + dump(value); } @@ -489,6 +489,7 @@ function JSify(data) { + makeFunctionCall(item.ident, item.params) + '; ' + '__THREW__ = false } catch(e) { ' + '__THREW__ = true; ' + + (EXCEPTION_DEBUG ? 'print("Exception: " + e + " : " + (new Error().stack)); ' : '') + '} })(); if (!__THREW__) { ' + makeBranch(item.toLabel) + ' } else { ' + makeBranch(item.unwindLabel) + ' }'; return ret; }); diff --git a/src/library.js b/src/library.js index 72d7f599..ad8e440f 100644 --- a/src/library.js +++ b/src/library.js @@ -139,7 +139,7 @@ var Library = { }, llvm_eh_exception: function() { - return 'code-generated exception'; + return 'code-generated exception: ' + (new Error().stack); }, llvm_eh_selector: function(exception, personality, num) { @@ -188,13 +188,24 @@ var Library = { sysconf: function(name_) { switch(name_) { - case 30: return 4096; // _SC_PAGE_SIZE + case 30: return PAGE_SIZE; // _SC_PAGE_SIZE default: throw 'unknown sysconf param: ' + name_; } }, sbrk: function(bytes) { - return unfreeableMalloc(bytes); + // We need to make sure no one else allocates unfreeable memory! + // We must control this entirely. So we don't even need to do + // unfreeable allocations - the HEAP is ours, from HEAPTOP up. + // TODO: We could in theory slice off the top of the HEAP when + // sbrk gets a negative increment in |bytes|... + var self = arguments.callee; + if (!self.HEAPTOP) { + self.HEAPTOP = HEAPTOP; + } else { + assert(self.HEAPTOP == HEAPTOP, "Noone should touch the heap!"); + } + return alignMemoryPage(HEAPTOP); }, // time.h diff --git a/src/postamble.js b/src/postamble.js index a185b306..2b97abdc 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -10,13 +10,13 @@ function run(args) { argv.push(0); } } - var argv = [Pointer_make(intArrayFromString("/bin/this.program"), null, ALLOC_UNFREEABLE) ]; + var argv = [Pointer_make(intArrayFromString("/bin/this.program"), null, ALLOC_STATIC) ]; pad(); for (var i = 0; i < argc-1; i = i + 1) { - argv.push(Pointer_make(intArrayFromString(args[i]), null, ALLOC_UNFREEABLE)); + argv.push(Pointer_make(intArrayFromString(args[i]), null, ALLOC_STATIC)); pad(); } - argv = Pointer_make(argv, null, ALLOC_UNFREEABLE); + argv = Pointer_make(argv, null, ALLOC_STATIC); __globalConstructor__(); diff --git a/src/preamble.js b/src/preamble.js index e1036b8e..08edb022 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -37,7 +37,8 @@ START_TIME = Date.now(); function assert(condition, text) { if (!condition) { - throw 'Assertion failed: ' + text + ':\n' + (new Error).stack; + print('Assertion failed: ' + text + ':\n' + (new Error).stack); + throw "Assertion"; } } @@ -59,7 +60,7 @@ function Pointer_make(slab, pos, allocator) { } var slab = flatten(slab); // Finalize - var ret = [_malloc, stackAlloc, unfreeableMalloc][allocator ? allocator : ALLOC_UNFREEABLE](Math.max(slab.length - pos, 1)); + var ret = [_malloc, stackAlloc, staticAlloc][allocator ? allocator : ALLOC_STATIC](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]); @@ -89,11 +90,20 @@ function Pointer_stringify(ptr) { // Memory management -ALLOC_NORMAL = 0; -ALLOC_STACK = 1; -ALLOC_UNFREEABLE = 2; +ALLOC_NORMAL = 0; // Tries to use _malloc() +ALLOC_STACK = 1; // Lives for the duration of the current function call +ALLOC_STATIC = 2; // Cannot be freed + +function alignMemory(x) { + return Math.ceil(x/QUANTUM_SIZE)*QUANTUM_SIZE; // Allocate blocks of proper minimum size + // Also keeps STACKTOP/etc. aligned +} + +PAGE_SIZE = 4096; +function alignMemoryPage(x) { + return Math.ceil(x/PAGE_SIZE)*PAGE_SIZE; +} -// Stack allocation function stackEnter() { STACK_STACK.push(STACKTOP); } @@ -101,30 +111,25 @@ 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 STACKTOP aligned - assert(STACKTOP + size < TOTAL_STACK); + size = alignMemory(size); + assert(STACKTOP + size - STACKROOT < TOTAL_STACK, "No room on stack!"); var ret = STACKTOP; STACKTOP += size; return ret; } -function unfreeableMalloc(size) { - size = Math.ceil(size/1)*1; // Allocate blocks of proper minimum size - // Also keeps HEAPTOP aligned - var ret = HEAPTOP; - HEAPTOP += size; +function staticAlloc(size) { + size = alignMemory(size); + assert(STATICTOP + size - STATICROOT < TOTAL_STATIC, "No room for static allocation!"); + var ret = STATICTOP; + STATICTOP += size; return ret; } -function unfreeableFree(ptr) { -} - -// If we don't have malloc/free implemented, use a simple implementation. This -// allows compiled C/C++ to implement its own malloc/free +// If we don't have malloc/free implemented, use a simple implementation. if (!this._malloc) { - _malloc = unfreeableMalloc; - _free = unfreeableFree; + _malloc = staticAlloc; + _free = function() { }; // leak! } // Mangled "new"s... need a heuristic for autogeneration... @@ -139,10 +144,15 @@ __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' - TOTAL_STACK = 64*1024; // Reserved room for stack + + if (!this['TOTAL_STATIC']) TOTAL_STATIC = 64*1024; // Reserved room for static allocation + STATICROOT = STATICTOP = alignMemoryPage(HEAP.length); + + if (!this['TOTAL_STACK']) TOTAL_STACK = 64*1024; // Reserved room for stack STACK_STACK = []; - STACKTOP = HEAP.length; - HEAPTOP = STACKTOP + TOTAL_STACK; + STACKROOT = STACKTOP = alignMemoryPage(STATICROOT + TOTAL_STATIC); + + HEAPTOP = alignMemoryPage(STACKROOT + TOTAL_STACK); // Start of the "processes' data segment" } // stdio.h @@ -186,7 +196,7 @@ function __formatString() { textIndex += 1; } } - return Pointer_make(ret); // Leak! + return Pointer_make(ret, 0, ALLOC_STACK); // NB: Stored on the stack } // Copies a list of num items on the HEAP into a diff --git a/src/settings.js b/src/settings.js index 815832ed..67ba8d10 100644 --- a/src/settings.js +++ b/src/settings.js @@ -24,6 +24,7 @@ RELOOP = 0; // Recreate js native loops from llvm data XXX - disabled pending op // Generated code debugging options SAFE_HEAP = 0; // Check each write to the heap against a list of blocked addresses LABEL_DEBUG = 0; // Print out labels and functions as we enter them +EXCEPTION_DEBUG = 1; // Print out exceptions in emscriptened code EXECUTION_TIMEOUT = -1; // Throw an exception after X seconds - useful to debug infinite loops // Compiler debugging options diff --git a/tests/runner.py b/tests/runner.py index 08bb8648..cdbaf43d 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -82,7 +82,7 @@ class T(unittest.TestCase): 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 + #shutil.rmtree(dirname) # TODO: leave no trace in memory. But for now nice for debugging def assertContained(self, value, string): if value not in string: diff --git a/tests/settings.py b/tests/settings.py index 92f35203..e83129de 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -20,7 +20,7 @@ COMPILER_OPTS = ['-m32'] # Need to build as 32bit arch, for now - LLVM_DIS=os.path.expanduser('~/Dev/llvm-2.7/cbuild/bin/llvm-dis') -SPIDERMONKEY_ENGINE=os.path.expanduser('~/Dev/m-c/js/src/js') +SPIDERMONKEY_ENGINE=os.path.expanduser('~/Dev/mozilla-central/js/src/js') V8_ENGINE=os.path.expanduser('~/Dev/v8/d8') # XXX Warning: Running the 'sauer' test in SpiderMonkey can lead to an extreme amount of memory being |