Found and fixed some obscure leaks in 'Toy_Scope'
This commit is contained in:
+1
-36
@@ -1,5 +1,5 @@
|
||||
#include "bucket_inspector.h"
|
||||
// #include <toy_string.h>
|
||||
#include <toy_string.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -13,40 +13,6 @@ int inspect_bucket(Toy_Bucket** bucketHandle) {
|
||||
unsigned char* ptr = iter->data;
|
||||
|
||||
|
||||
while ((ptr - iter->data < iter->count) && *((int*)ptr) != 0) { //for each partition
|
||||
if ( ( *((int*)ptr) & 1) == 0) { //is this partition still in use?
|
||||
occupied++;
|
||||
}
|
||||
else {
|
||||
released++;
|
||||
}
|
||||
|
||||
//jump distance: ((*((int*)ptr) | 1) ^ 1) + 4
|
||||
// printf(" jump %d, ", ((*((int*)ptr) | 1) ^ 1) + 4);
|
||||
ptr += ((*((int*)ptr) | 1) ^ 1) + 4; //OR + XOR to remove the 'free' flag from the size
|
||||
}
|
||||
|
||||
printf("Bucket link %d: count %u, %d occupied, %d released\n", depth, iter->count, occupied, released);
|
||||
|
||||
depth++;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
/*
|
||||
int inspect_bucket_for_strings(Toy_Bucket** bucketHandle) {
|
||||
int depth = 0;
|
||||
|
||||
//for each bucket
|
||||
for (Toy_Bucket* iter = (*bucketHandle); iter != NULL; iter = iter->next) {
|
||||
int occupied = 0;
|
||||
int released = 0;
|
||||
unsigned char* ptr = iter->data;
|
||||
|
||||
|
||||
while ((ptr - iter->data < iter->count) && *((int*)ptr) != 0) { //for each partition
|
||||
if ( ( *((int*)ptr) & 1) == 0) { //is this partition still in use?
|
||||
occupied++;
|
||||
@@ -79,4 +45,3 @@ int inspect_bucket_for_strings(Toy_Bucket** bucketHandle) {
|
||||
|
||||
return depth;
|
||||
}
|
||||
*/
|
||||
@@ -2,5 +2,4 @@
|
||||
|
||||
#include "toy_bucket.h"
|
||||
|
||||
int inspect_bucket(Toy_Bucket** bucketHandle);
|
||||
// int inspect_bucket_for_strings(Toy_Bucket** bucketHandle);
|
||||
int inspect_bucket(Toy_Bucket** bucketHandle);
|
||||
+4
-4
@@ -280,14 +280,14 @@ static void debugScopePrint(Toy_Scope* scope, int depth) {
|
||||
|
||||
printf("\n" TOY_CC_NOTICE "Scope Dump [%d]" TOY_CC_RESET "\n" TOY_CC_NOTICE "%-20s%-20s%-20s" TOY_CC_RESET "\n", depth, "type", "name", "value");
|
||||
for (unsigned int i = 0; i < scope->capacity; i++) {
|
||||
if (scope->data[i].key.info.length == 0) {
|
||||
if (scope->data[i].key == NULL || scope->data[i].key->info.length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Toy_String k = scope->data[i].key;
|
||||
Toy_String* k = scope->data[i].key;
|
||||
Toy_Value v = scope->data[i].value;
|
||||
|
||||
printf("%-10s%-10s%-20s", Toy_getValueTypeAsCString(scope->data[i].type), scope->data[i].constant ? "const" : "", k.leaf.data);
|
||||
printf("%-10s%-10s%-20s", Toy_getValueTypeAsCString(scope->data[i].type), scope->data[i].constant ? "const" : "", k != NULL ? k->leaf.data : "");
|
||||
|
||||
//print value
|
||||
Toy_String* string = Toy_stringifyValue(&stringBucket, Toy_unwrapValue(v));
|
||||
@@ -321,7 +321,7 @@ int repl(const char* filepath, bool verbose) {
|
||||
char inputBuffer[INPUT_BUFFER_SIZE];
|
||||
memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
|
||||
|
||||
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); //TODO: gc this
|
||||
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
|
||||
@@ -56,13 +56,9 @@ void initStandardLibrary(Toy_VM* vm) {
|
||||
|
||||
//declare each pair
|
||||
for (int i = 0; callbackPairs[i].name; i++) {
|
||||
//cheat
|
||||
Toy_String key = (Toy_String){
|
||||
.leaf = { ._padding = { .type = TOY_STRING_LEAF, .length = strlen(callbackPairs[i].name), .refCount = 1, .cachedHash = 0 }, .data = callbackPairs[i].name }
|
||||
};
|
||||
|
||||
Toy_String* key = Toy_createStringLength(&vm->memoryBucket, callbackPairs[i].name, strlen(callbackPairs[i].name));
|
||||
Toy_Function* fn = Toy_createFunctionFromCallback(&(vm->memoryBucket), callbackPairs[i].callback);
|
||||
|
||||
Toy_declareScope(vm->scope, &key, TOY_VALUE_FUNCTION, TOY_VALUE_FROM_FUNCTION(fn), true);
|
||||
Toy_declareScope(vm->scope, key, TOY_VALUE_FUNCTION, TOY_VALUE_FROM_FUNCTION(fn), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ c, d = swap(a, b);
|
||||
*/
|
||||
|
||||
|
||||
{ var str = "Hello"; var i = 0; while (i < 10_000) { str = str .. " World"; i++; } }
|
||||
{ var str = "Hello"; var i = 0; while (i < 100) { str = str .. " World"; i++; } }
|
||||
|
||||
|
||||
+16
-21
@@ -19,12 +19,12 @@ static Toy_ScopeEntry* lookupScopeEntryPtr(Toy_Scope* scope, Toy_String* key, un
|
||||
|
||||
while (true) {
|
||||
//found the entry
|
||||
if (Toy_compareStrings(&(scope->data[probe].key), key) == 0) {
|
||||
if (scope->data[probe].key != NULL && Toy_compareStrings(scope->data[probe].key, key) == 0) {
|
||||
return &(scope->data[probe]);
|
||||
}
|
||||
|
||||
//if its an empty slot (didn't find it here)
|
||||
if (scope->data[probe].key.info.length == 0) {
|
||||
if (scope->data[probe].key == NULL) {
|
||||
return recursive ? lookupScopeEntryPtr(scope->next, key, hash, recursive) : NULL;
|
||||
}
|
||||
|
||||
@@ -36,12 +36,12 @@ static Toy_ScopeEntry* lookupScopeEntryPtr(Toy_Scope* scope, Toy_String* key, un
|
||||
static void probeAndInsert(Toy_Scope* scope, Toy_String* key, Toy_Value value, Toy_ValueType type, bool constant) {
|
||||
//make the entry
|
||||
unsigned int probe = Toy_hashString(key) % scope->capacity;
|
||||
Toy_ScopeEntry entry = (Toy_ScopeEntry){ .key = *key, .value = value, .type = type, .constant = constant, .psl = 1 };
|
||||
Toy_ScopeEntry entry = (Toy_ScopeEntry){ .key = key, .value = value, .type = type, .constant = constant, .psl = 1 };
|
||||
|
||||
//probe
|
||||
while (true) {
|
||||
//if we're overriding an existing value
|
||||
if (Toy_compareStrings(&(scope->data[probe].key), &(entry.key)) == 0) {
|
||||
if (scope->data[probe].key != NULL && Toy_compareStrings(scope->data[probe].key, entry.key) == 0) {
|
||||
scope->data[probe] = entry;
|
||||
scope->maxPsl = entry.psl > scope->maxPsl ? entry.psl : scope->maxPsl;
|
||||
return;
|
||||
@@ -94,8 +94,8 @@ static Toy_ScopeEntry* adjustScopeEntries(Toy_Scope* scope, unsigned int newCapa
|
||||
|
||||
//for each existing entry in the old array, copy it into the new array
|
||||
for (unsigned int i = 0; i < oldCapacity; i++) {
|
||||
if (oldEntries[i].key.info.length > 0) {
|
||||
probeAndInsert(scope, &(oldEntries[i].key), oldEntries[i].value, oldEntries[i].type, oldEntries[i].constant);
|
||||
if (oldEntries[i].key != NULL && oldEntries[i].key->info.length > 0) {
|
||||
probeAndInsert(scope, oldEntries[i].key, oldEntries[i].value, oldEntries[i].type, oldEntries[i].constant);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,10 @@ Toy_Scope* Toy_popScope(Toy_Scope* scope) {
|
||||
}
|
||||
|
||||
Toy_private_decrementScopeRefCount(scope);
|
||||
return scope->next;
|
||||
|
||||
Toy_Scope* next = scope->next;
|
||||
Toy_releaseBucketPartition((void*)scope);
|
||||
return next;
|
||||
}
|
||||
|
||||
void Toy_declareScope(Toy_Scope* scope, Toy_String* key, Toy_ValueType type, Toy_Value value, bool constant) {
|
||||
@@ -229,29 +232,21 @@ void Toy_private_incrementScopeRefCount(Toy_Scope* scope) {
|
||||
}
|
||||
|
||||
void Toy_private_decrementScopeRefCount(Toy_Scope* scope) {
|
||||
Toy_Scope* iter = scope;
|
||||
|
||||
while (iter) {
|
||||
for (Toy_Scope* iter = scope; iter != NULL; iter = iter->next) {
|
||||
iter->refCount--;
|
||||
|
||||
//clean up our insides if needed
|
||||
if (iter->refCount == 0) {
|
||||
//free the scope entries when this scope is no longer needed
|
||||
//free the data
|
||||
if (iter->data != NULL) {
|
||||
for (unsigned int i = 0; i < iter->capacity; i++) {
|
||||
if (iter->data[i].psl > 0) {
|
||||
Toy_freeString(&(iter->data[i].key));
|
||||
if (iter->data[i].key != NULL) {
|
||||
Toy_freeString(iter->data[i].key);
|
||||
Toy_freeValue(iter->data[i].value);
|
||||
}
|
||||
}
|
||||
free(iter->data);
|
||||
}
|
||||
|
||||
//free the scope itself, fixing the iterator for the next loop
|
||||
Toy_Scope* empty = iter;
|
||||
iter = iter->next;
|
||||
Toy_releaseBucketPartition((void*)empty);
|
||||
}
|
||||
else {
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
//keys are leaf-only strings
|
||||
typedef struct Toy_ScopeEntry {
|
||||
Toy_String key;
|
||||
Toy_String* key;
|
||||
Toy_Value value;
|
||||
Toy_ValueType type;
|
||||
unsigned int psl; //psl '0' means empty
|
||||
|
||||
Reference in New Issue
Block a user