diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-05-15 13:37:09 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-05-15 13:37:09 -0700 |
commit | 46f641bf1e97000a774a5747128c965ea9d425be (patch) | |
tree | e0593c70c0aa6ed71b4a90895ced5d9f41b5a160 | |
parent | 1a55bf326caa5e2a8f3a1d3a0494f3a44a10f47d (diff) |
working early gc test
-rw-r--r-- | src/library_gc.js | 9 | ||||
-rw-r--r-- | system/include/gc.h | 10 | ||||
-rwxr-xr-x | tests/runner.py | 51 |
3 files changed, 62 insertions, 8 deletions
diff --git a/src/library_gc.js b/src/library_gc.js index 7683eda7..d9bb895b 100644 --- a/src/library_gc.js +++ b/src/library_gc.js @@ -1,6 +1,7 @@ if (GC_SUPPORT) { var LibraryGC = { + $GC__deps: ['sbrk'], $GC: { ALLOCATIONS_TO_GC: 1*1024*1024, @@ -28,7 +29,7 @@ if (GC_SUPPORT) { if (!bytes) return 0; var ptr; if (clear) { - ptr = _calloc(bytes); + ptr = _calloc(1, bytes); } else { ptr = _malloc(bytes); } @@ -42,7 +43,7 @@ if (GC_SUPPORT) { free: function(ptr) { // does not check if anything refers to it, this is a forced free var finalizer = GC.finalizers[ptr]; if (finalizer) { - Runtime.getFuncWrapper(finalizer)(GC.finalizerArgs[ptr]); + Runtime.getFuncWrapper(finalizer)(ptr, GC.finalizerArgs[ptr]); GC.finalizers[ptr] = 0; } _free(ptr); @@ -80,7 +81,7 @@ if (GC_SUPPORT) { }, scan: function(start, end) { // scans a memory region and adds new reachable objects - for (var i = start; i < sbrk.end; i += {{{ Runtime.getNativeTypeSize('void*') }}}) { + for (var i = start; i < end; i += {{{ Runtime.getNativeTypeSize('void*') }}}) { var ptr = {{{ makeGetValue('i', '0', 'void*') }}}; if (GC.sizes[ptr] && !GC.reachable[ptr]) { GC.reachable[ptr] = 1; @@ -96,7 +97,7 @@ if (GC_SUPPORT) { GC.reachableList = []; // each reachable is added once to this. XXX // static data areas var staticStart = STACK_MAX; - var staticEnd = sbrk.DYNAMIC_START || STATICTOP; // after DYNAMIC_START, sbrk manages it (but it might not exist yet) + var staticEnd = _sbrk.DYNAMIC_START || STATICTOP; // after DYNAMIC_START, sbrk manages it (but it might not exist yet) GC.scan(staticStart, staticEnd); // TODO: scan stack and registers. Currently we assume we run from a timeout or such, so no stack/regs // stack: STACK_ROOT to STACKTOP diff --git a/system/include/gc.h b/system/include/gc.h index 773098ff..baeaf2b5 100644 --- a/system/include/gc.h +++ b/system/include/gc.h @@ -2,16 +2,18 @@ * Boehm-compatible GC API */ +#include <stdlib.h> + #ifdef __cplusplus extern "C" { #endif void __attribute__((used)) __GC_KEEPALIVE__() { // Force inclusion of necessary dlmalloc functions - static times = 1; + static int times = 1; void *x = malloc(times); free(x); - x = calloc(times); + x = calloc(times, 1); free(x); times++; } @@ -29,8 +31,8 @@ void *GC_MALLOC_ATOMIC(int bytes); void GC_FREE(void *ptr); /* Register a finalizer. func(ptr, arg) will be called. The old values are saved in old_func, old_arg */ -void GC_REGISTER_FINALIZER_NO_ORDER((void*)ptr, void (*func)(), void *arg, - void *(*old_func)(), void *old_arg); +void GC_REGISTER_FINALIZER_NO_ORDER(void *ptr, void (*func)(void *, void *), void *arg, + void *(*old_func)(void *, void *), void *old_arg); /* Non-Boehm additions */ diff --git a/tests/runner.py b/tests/runner.py index 49d4159a..da04aafd 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -6094,6 +6094,57 @@ def process(filename): ''' self.do_run(src, 'hello, world!\ncleanup\nExit Status: 118') + def test_gc(self): + Settings.GC_SUPPORT = 1 + + src = r''' + #include <stdio.h> + #include <gc.h> + #include <assert.h> + + void *global; + + void finalizer(void *ptr, void *arg) { + printf("finalizing (global == %d)\n", ptr == global); + } + + void finalizer2(void *ptr, void *arg) { + printf("finalizing2 (global == %d)\n", ptr == global); + } + + int main() { + GC_INIT(); + + global = GC_MALLOC(1024); // rooted since in a static allocation + GC_REGISTER_FINALIZER_NO_ORDER(global, finalizer, 0, 0, 0); + printf("alloc %p\n", global); + + void *local = GC_MALLOC(1024); // not rooted since stack is not scanned + GC_REGISTER_FINALIZER_NO_ORDER(local, finalizer, 0, 0, 0); + printf("alloc %p\n", local); + + assert((char*)local - (char*)global >= 1024 || (char*)global - (char*)local >= 1024); + + void *local2 = GC_MALLOC(1024); // no finalizer + printf("alloc %p\n", local2); + + void *local3 = GC_MALLOC(1024); // with finalizable2 + GC_REGISTER_FINALIZER_NO_ORDER(local3, finalizer2, 0, 0, 0); + printf("alloc %p\n", local); + + void *local4 = GC_MALLOC(1024); // yet another + GC_REGISTER_FINALIZER_NO_ORDER(local4, finalizer2, 0, 0, 0); + printf("alloc %p\n", local); + + printf("*\n"); + GC_FORCE_COLLECT(); + printf("*\n"); + + GC_FREE(global); + global = 0; + } + ''' + self.do_run(src, '*\nfinalizing (global == 0)\nfinalizing2 (global == 0)\nfinalizing2 (global == 0)\n*\nfinalizing (global == 1)\n') # Generate tests for everything def make_run(fullname, name=-1, compiler=-1, llvm_opts=0, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None): |