aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jsifier.js13
-rw-r--r--src/library.js17
-rw-r--r--src/postamble.js6
-rw-r--r--src/preamble.js60
-rw-r--r--src/settings.js1
-rw-r--r--tests/runner.py2
-rw-r--r--tests/settings.py2
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