diff options
author | Bruce Mitchener <bruce.mitchener@gmail.com> | 2013-02-01 02:39:12 +0700 |
---|---|---|
committer | Bruce Mitchener <bruce.mitchener@gmail.com> | 2013-02-01 09:05:24 +0700 |
commit | defdd23b213d8b4ad79ec1c263d19380fbaa2b62 (patch) | |
tree | 48753980024850139ba6f0a51f92a9c127c88427 | |
parent | ce3519e96e085b411a9d31a3aa21a9aecbc3ce38 (diff) |
Add support for GC_REALLOC().
-rw-r--r-- | src/library_gc.js | 42 | ||||
-rw-r--r-- | system/include/gc.h | 3 | ||||
-rwxr-xr-x | tests/runner.py | 10 |
3 files changed, 53 insertions, 2 deletions
diff --git a/src/library_gc.js b/src/library_gc.js index ed40fa6c..42f98b52 100644 --- a/src/library_gc.js +++ b/src/library_gc.js @@ -3,7 +3,7 @@ if (GC_SUPPORT) { EXPORTED_FUNCTIONS['_calloc'] = 1; var LibraryGC = { - $GC__deps: ['sbrk'], + $GC__deps: ['sbrk', 'realloc'], $GC: { ALLOCATIONS_TO_GC: 1*1024*1024, @@ -53,6 +53,41 @@ if (GC_SUPPORT) { return ptr; }, + realloc: function(ptr, newBytes) { + if (newBytes != 0) { + var oldBytes = GC.sizes[ptr]; + var newPtr = _realloc(ptr, newBytes); + if (newBytes > oldBytes) { + _memset(newPtr + oldBytes, 0, newBytes - oldBytes); + } + delete GC.sizes[ptr]; + GC.sizes[newPtr] = newBytes; + scannable = GC.scannables[ptr]; + delete GC.scannables[ptr]; + GC.scannables[newPtr] = scannable; + var finalizer = GC.finalizers[ptr]; + if (finalizer) { + delete GC.finalizers[ptr]; + GC.finalizers[newPtr] = finalizer; + } + var finalizerArgs = GC.finalizerArgs[ptr]; + if (finalizerArgs) { + delete GC.finalizerArgs[ptr]; + GC.finalizerArgs[newPtr] = finalizerArgs; + } + var uncollectable = GC.uncollectables[ptr]; + if (uncollectable) { + delete GC.uncollectables[ptr]; + GC.uncollectables[newPtr] = true; + } + GC.totalAllocations += (newBytes - oldBytes); + return newPtr; + } else { + GC.free(ptr); + return 0; + } + }, + free: function(ptr) { // does not check if anything refers to it, this is a forced free var finalizer = GC.finalizers[ptr]; if (finalizer) { @@ -157,6 +192,11 @@ if (GC_SUPPORT) { return GC.malloc(bytes, true, true, false); }, + GC_REALLOC__deps: ['$GC'], + GC_REALLOC: function(ptr, newBytes) { + return GC.realloc(ptr, newBytes); + }, + GC_FREE__deps: ['$GC'], GC_FREE: function(ptr) { GC.free(ptr); diff --git a/system/include/gc.h b/system/include/gc.h index e4593c51..1a236f3d 100644 --- a/system/include/gc.h +++ b/system/include/gc.h @@ -32,6 +32,9 @@ void *GC_MALLOC_ATOMIC(int bytes); /* Allocate memory that might container pointers but that can't be collected. */ void *GC_MALLOC_UNCOLLECTABLE(int bytes); +/* Reallocate a GC managed memory block to a new size. */ +void *GC_REALLOC(void *ptr, int newBytes); + /* Explicitly deallocate an object. Dangerous as it forces a free and does not check if the object is reffed. */ void GC_FREE(void *ptr); diff --git a/tests/runner.py b/tests/runner.py index 6d1a3cba..28675e9b 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7893,7 +7893,7 @@ def process(filename): int main() { GC_INIT(); - void *local, *local2, *local3, *local4, *local5; + void *local, *local2, *local3, *local4, *local5, *local6; // Hold on to global, drop locals @@ -7942,6 +7942,13 @@ def process(filename): // This should never trigger since local5 is uncollectable GC_REGISTER_FINALIZER_NO_ORDER(local5, finalizer, (void*)5, 0, 0); + local4 = GC_REALLOC(local4, 24); + + local6 = GC_MALLOC(12); + GC_REGISTER_FINALIZER_NO_ORDER(local6, finalizer, (void*)6, 0, 0); + // This should be the same as a free + GC_REALLOC(local6, 0); + void **globalData = (void**)global; globalData[0] = local; globalData[1] = local2; @@ -7977,6 +7984,7 @@ finalizing2 2 (global == 0) finalizing2 3 (global == 0) * finalizing 0 (global == 1) +finalizing 6 (global == 0) object scan test test finalizing 4 (global == 0) * |