aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Mitchener <bruce.mitchener@gmail.com>2013-02-01 02:39:12 +0700
committerBruce Mitchener <bruce.mitchener@gmail.com>2013-02-01 09:05:24 +0700
commitdefdd23b213d8b4ad79ec1c263d19380fbaa2b62 (patch)
tree48753980024850139ba6f0a51f92a9c127c88427
parentce3519e96e085b411a9d31a3aa21a9aecbc3ce38 (diff)
Add support for GC_REALLOC().
-rw-r--r--src/library_gc.js42
-rw-r--r--system/include/gc.h3
-rwxr-xr-xtests/runner.py10
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)
*