diff --git a/AUTHORS b/AUTHORS index 0367593c..de37a7b8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -26,4 +26,6 @@ Charlotte Koch Michel Hermier Taylor Hoff ruby0x1 +Kolja Kube Alexander Klingenbeck + diff --git a/doc/site/embedding/configuring-the-vm.markdown b/doc/site/embedding/configuring-the-vm.markdown index 39b6f425..9ea68a34 100644 --- a/doc/site/embedding/configuring-the-vm.markdown +++ b/doc/site/embedding/configuring-the-vm.markdown @@ -182,7 +182,7 @@ These fields control how the VM allocates and manages memory. This lets you provide a custom memory allocation function. Its signature is:
-void* reallocate(void* memory, size_t newSize)
+void* reallocate(void* memory, size_t newSize, void* userData)
 
Wren uses this one function to allocate, grow, shrink, and deallocate memory. diff --git a/src/include/wren.h b/src/include/wren.h index 0dddc430..69fa1099 100644 --- a/src/include/wren.h +++ b/src/include/wren.h @@ -47,7 +47,7 @@ typedef struct WrenHandle WrenHandle; // // - To free memory, [memory] will be the memory to free and [newSize] will be // zero. It should return NULL. -typedef void* (*WrenReallocateFn)(void* memory, size_t newSize); +typedef void* (*WrenReallocateFn)(void* memory, size_t newSize, void* userData); // A function callable from Wren code, but implemented in C. typedef void (*WrenForeignMethodFn)(WrenVM* vm); diff --git a/src/vm/wren_value.c b/src/vm/wren_value.c index 705987c8..d475b88b 100644 --- a/src/vm/wren_value.c +++ b/src/vm/wren_value.c @@ -975,7 +975,8 @@ void wrenGrayObj(WrenVM* vm, Obj* obj) { vm->grayCapacity = vm->grayCount * 2; vm->gray = (Obj**)vm->config.reallocateFn(vm->gray, - vm->grayCapacity * sizeof(Obj*)); + vm->grayCapacity * sizeof(Obj*), + vm->config.userData); } vm->gray[vm->grayCount++] = obj; diff --git a/src/vm/wren_vm.c b/src/vm/wren_vm.c index b77a1216..a63f973e 100644 --- a/src/vm/wren_vm.c +++ b/src/vm/wren_vm.c @@ -25,7 +25,7 @@ // may return a non-NULL pointer which must not be dereferenced but nevertheless // should be freed. To prevent that, we avoid calling realloc() with a zero // size. -static void* defaultReallocate(void* ptr, size_t newSize) +static void* defaultReallocate(void* ptr, size_t newSize, void* _) { if (newSize == 0) { @@ -54,9 +54,13 @@ void wrenInitConfiguration(WrenConfiguration* config) WrenVM* wrenNewVM(WrenConfiguration* config) { WrenReallocateFn reallocate = defaultReallocate; - if (config != NULL) reallocate = config->reallocateFn; + void* userData = NULL; + if (config != NULL) { + reallocate = config->reallocateFn; + userData = config->userData; + } - WrenVM* vm = (WrenVM*)reallocate(NULL, sizeof(*vm)); + WrenVM* vm = (WrenVM*)reallocate(NULL, sizeof(*vm), userData); memset(vm, 0, sizeof(WrenVM)); // Copy the configuration if given one. @@ -73,7 +77,7 @@ WrenVM* wrenNewVM(WrenConfiguration* config) vm->grayCount = 0; // TODO: Tune this. vm->grayCapacity = 4; - vm->gray = (Obj**)reallocate(NULL, vm->grayCapacity * sizeof(Obj*)); + vm->gray = (Obj**)reallocate(NULL, vm->grayCapacity * sizeof(Obj*), userData); vm->nextGC = vm->config.initialHeapSize; wrenSymbolTableInit(&vm->methodNames); @@ -97,7 +101,7 @@ void wrenFreeVM(WrenVM* vm) } // Free up the GC gray set. - vm->gray = (Obj**)vm->config.reallocateFn(vm->gray, 0); + vm->gray = (Obj**)vm->config.reallocateFn(vm->gray, 0, vm->config.userData); // Tell the user if they didn't free any handles. We don't want to just free // them here because the host app may still have pointers to them that they @@ -220,7 +224,7 @@ void* wrenReallocate(WrenVM* vm, void* memory, size_t oldSize, size_t newSize) if (newSize > 0 && vm->bytesAllocated > vm->nextGC) wrenCollectGarbage(vm); #endif - return vm->config.reallocateFn(memory, newSize); + return vm->config.reallocateFn(memory, newSize, vm->config.userData); } // Captures the local variable [local] into an [Upvalue]. If that local is diff --git a/test/api/user_data.c b/test/api/user_data.c index 676fddf5..7c1a426d 100644 --- a/test/api/user_data.c +++ b/test/api/user_data.c @@ -5,6 +5,18 @@ static const char* data = "my user data"; static const char* otherData = "other user data"; +void* testReallocateFn(void* ptr, size_t newSize, void* userData) { + if (strcmp(userData, data) != 0) return NULL; + + if (newSize == 0) + { + free(ptr); + return NULL; + } + + return realloc(ptr, newSize); +} + static void test(WrenVM* vm) { WrenConfiguration configuration; @@ -17,6 +29,7 @@ static void test(WrenVM* vm) return; } + configuration.reallocateFn = testReallocateFn; configuration.userData = (void*)data; WrenVM* otherVM = wrenNewVM(&configuration);