diff options
-rw-r--r-- | src/compiler.js | 1 | ||||
-rw-r--r-- | src/jsifier.js | 6 | ||||
-rw-r--r-- | src/library.js | 12 | ||||
-rw-r--r-- | src/postamble.js | 6 | ||||
-rw-r--r-- | src/preamble.js | 46 | ||||
-rw-r--r-- | src/runtime.js | 62 | ||||
-rw-r--r-- | src/settings.js | 2 |
7 files changed, 86 insertions, 49 deletions
diff --git a/src/compiler.js b/src/compiler.js index 54e54b5c..ba36f215 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -17,6 +17,7 @@ load('parseTools.js'); load('intertyper.js'); load('analyzer.js'); load('jsifier.js'); +load('runtime.js'); //=============================== // Main diff --git a/src/jsifier.js b/src/jsifier.js index b4b0952f..10f3851f 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -241,7 +241,7 @@ function JSify(data) { }).filter(function(param) { return param != null });; func.JS = '\nfunction ' + func.ident + '(' + params.join(', ') + ') {\n'; - func.JS += ' stackEnter();\n'; + func.JS += ' ' + RuntimeGenerator.stackEnter() + '\n'; if (LABEL_DEBUG) func.JS += " print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n"; if (true) { // TODO: optimize away when not needed @@ -511,7 +511,7 @@ function JSify(data) { return ret; }); makeFuncLineZyme('return', function(item) { - var ret = 'stackExit();\n'; + var ret = RuntimeGenerator.stackExit() + '\n'; if (LABEL_DEBUG) ret += "INDENT = INDENT.substr(0, INDENT.length-2);\n"; ret += 'return'; if (item.value) { @@ -766,6 +766,6 @@ function JSify(data) { substrate.addItems(data.functionStubs, 'FunctionStub'); var params = { 'QUANTUM_SIZE': QUANTUM_SIZE }; - return preprocess(read('preamble.js') + finalCombiner(substrate.solve()) + read('postamble.js'), params); + return preprocess(read('preamble.js') + getRuntime() + finalCombiner(substrate.solve()) + read('postamble.js'), params); } diff --git a/src/library.js b/src/library.js index 68ad805a..08d62309 100644 --- a/src/library.js +++ b/src/library.js @@ -200,18 +200,18 @@ var Library = { // 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. + // unfreeable allocations - the HEAP is ours, from STATICTOP 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) { - HEAPTOP = alignMemoryPage(HEAPTOP); - self.HEAPTOP = HEAPTOP; + if (!self.STATICTOP) { + STATICTOP = alignMemoryPage(STATICTOP); + self.STATICTOP = STATICTOP; self.DATASIZE = 0; } else { - assert(self.HEAPTOP == HEAPTOP, "Noone should touch the heap!"); + assert(self.STATICTOP == STATICTOP, "Noone should touch the heap!"); } - var ret = HEAPTOP + self.DATASIZE; + var ret = STATICTOP + self.DATASIZE; self.DATASIZE += alignMemoryPage(bytes); return ret; // previous break location }, diff --git a/src/postamble.js b/src/postamble.js index 2b97abdc..1329a1a4 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_STATIC) ]; + var argv = [Pointer_make(intArrayFromString("/bin/this.program"), null) ]; pad(); for (var i = 0; i < argc-1; i = i + 1) { - argv.push(Pointer_make(intArrayFromString(args[i]), null, ALLOC_STATIC)); + argv.push(Pointer_make(intArrayFromString(args[i]), null)); pad(); } - argv = Pointer_make(argv, null, ALLOC_STATIC); + argv = Pointer_make(argv, null); __globalConstructor__(); diff --git a/src/preamble.js b/src/preamble.js index 4f7fef93..33c9515d 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -52,6 +52,11 @@ function Pointer_niceify(ptr) { // If just a slab is given, will allocate room for it and copy it there. In // other words, do whatever is necessary in order to return a pointer, that // points to the slab (and possibly position) we are given. + +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 Pointer_make(slab, pos, allocator) { pos = pos ? pos : 0; if (slab === HEAP) return pos; @@ -92,42 +97,11 @@ function Pointer_stringify(ptr) { // Memory management -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; } -function stackEnter() { - STACK_STACK.push(STACKTOP); -} -function stackExit() { - STACKTOP = STACK_STACK.pop(); -} -function stackAlloc(size) { - size = alignMemory(size); - assert(STACKTOP + size - STACKROOT < TOTAL_STACK, "No room on stack!"); - var ret = STACKTOP; - STACKTOP += size; - return ret; -} - -function staticAlloc(size) { - size = alignMemory(size); - assert(STATICTOP + size - STATICROOT < TOTAL_STATIC, "No room for static allocation!"); - var ret = STATICTOP; - STATICTOP += size; - return ret; -} - // If we don't have malloc/free implemented, use a simple implementation. if (!this._malloc) { _malloc = staticAlloc; @@ -147,14 +121,12 @@ function __initializeRuntime__() { HEAP = intArrayFromString('(null)'); // So printing %s of NULL gives '(null)' // Also this ensures we leave 0 as an invalid address, 'NULL' - if (!this['TOTAL_STATIC']) TOTAL_STATIC = 64*1024*100; // Reserved room for static allocation - STATICROOT = STATICTOP = alignMemoryPage(HEAP.length); - - if (!this['TOTAL_STACK']) TOTAL_STACK = 64*1024*10; // Reserved room for stack STACK_STACK = []; - STACKROOT = STACKTOP = alignMemoryPage(STATICROOT + TOTAL_STATIC); + STACK_ROOT = STACKTOP = alignMemoryPage(10); + if (!this['TOTAL_STACK']) TOTAL_STACK = 64*1024*100; // Reserved room for stack + STACK_MAX = STACK_ROOT + TOTAL_STACK; - HEAPTOP = alignMemoryPage(STACKROOT + TOTAL_STACK); // Start of the "processes' data segment" + STATICTOP = alignMemoryPage(STACK_MAX); } // stdio.h diff --git a/src/runtime.js b/src/runtime.js new file mode 100644 index 00000000..541f4756 --- /dev/null +++ b/src/runtime.js @@ -0,0 +1,62 @@ +// Generates code that can be placed inline in generated code. +// This is not the cleanest way to write this kind of code - it is +// optimized for generating fast inline code. +RuntimeGenerator = { + alloc: function(target, size, type) { + var ret = target + ' = ' + type + 'TOP; ' + type + 'TOP += ' + size + ';'; + if (QUANTUM_SIZE > 1) { + ret += RuntimeGenerator.alignMemory(type + 'TOP'); + } + return ret; + }, + + // An allocation that lives as long as the current function call + stackAlloc: function(target, size) { + var ret = RuntimeGenerator.alloc(target, size, 'STACK'); + if (GUARD_STACK) { + ret += ' assert(STACKTOP < STACK_ROOT + STACK_MAX);'; + } + return ret; + }, + + stackEnter: function() { + return 'STACK_STACK.push(STACKTOP);'; + }, + + stackExit: function() { + return 'STACKTOP = STACK_STACK.pop();'; + }, + + // An allocation that cannot be free'd + staticAlloc: function(target, size) { + return RuntimeGenerator.alloc(target, size, 'STATIC'); + }, + + alignMemory: function(target) { + return target + ' = Math.ceil(' + target + '/QUANTUM_SIZE)*QUANTUM_SIZE;'; + }, +}; + +function unInline(name_, params) { + var src = '(function ' + name_ + '(' + params + ') { var ret; ' + RuntimeGenerator[name_].apply(null, ['ret'].concat(params)) + ' return ret; })'; + print('src: ' + src); + return eval(src); +} + +// Uses the RuntimeGenerator during compilation, in order to +// 1. Let the compiler access and run those functions during compilation +// 2. We expose the entire Runtime object to generated code, so it can +// use that functionality in a non-inline manner. +Runtime = { + stackAlloc: unInline('stackAlloc', ['size']), + staticAlloc: unInline('staticAlloc', ['size']), +}; + +function getRuntime() { + var ret = ''; + for (i in Runtime) { + ret += Runtime[i].toString() + '\n'; + } + return ret; +} + diff --git a/src/settings.js b/src/settings.js index 9f6baa40..660671fd 100644 --- a/src/settings.js +++ b/src/settings.js @@ -18,6 +18,8 @@ GUARD_SIGNS = 1; // Whether we make sure to convert unsigned values to signed va // needed in some kinds of code. GUARD_LABELS = 0; // Whether we should throw if we encounter a bad __label__, i.e., // if code flow runs into a fault +GUARD_STACK = 1; // Whether we should check that each allocation to the stack does not + // exceed it's size // Code embetterments OPTIMIZE = 0; // Optimize llvm operations into js commands |