aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoralon@honor <none@none>2010-10-06 20:02:30 -0700
committeralon@honor <none@none>2010-10-06 20:02:30 -0700
commit99f96653a706fc61d4be31ce8b45cd6d74c06c6a (patch)
tree8a997d03444ba0ee55d6ec8e68dbeb799be68915 /src
parent0390eea0b6d157be7d7e2ae0e388e16a3db92581 (diff)
Runtime system, and inlining of stackEnter/Exit
Diffstat (limited to 'src')
-rw-r--r--src/compiler.js1
-rw-r--r--src/jsifier.js6
-rw-r--r--src/library.js12
-rw-r--r--src/postamble.js6
-rw-r--r--src/preamble.js46
-rw-r--r--src/runtime.js62
-rw-r--r--src/settings.js2
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