From 6365a007b6da30a5d50ccdba26d212644ca0a425 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Wed, 22 Mar 2017 18:35:54 -0400 Subject: [PATCH] More work on cleaning up string implementation. --- Makefile | 2 +- core/compile.c | 2 +- core/ds.c | 39 +------ core/parse.c | 6 +- core/serialize.c | 27 ++--- core/stl.c | 12 +-- core/stringcache.c | 120 --------------------- core/stringcache.h | 3 +- core/strings.c | 260 ++++++++++++++++++++++++++++++++++++--------- core/thread.c | 4 +- core/value.c | 82 +++++++------- 11 files changed, 278 insertions(+), 279 deletions(-) delete mode 100644 core/stringcache.c diff --git a/Makefile b/Makefile index bdf6e10d..9be68274 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ all: $(GST_TARGET) ##### The core vm and runtime ##### ################################### GST_CORE_SOURCES=$(addprefix core/,\ - compile.c disasm.c parse.c stl.c strings.c stringcache.c\ + compile.c disasm.c parse.c stl.c strings.c \ value.c vm.c ds.c gc.c thread.c serialize.c) GST_CORE_OBJECTS=$(patsubst %.c,%.o,$(GST_CORE_SOURCES)) $(GST_CORELIB): $(GST_CORE_OBJECTS) $(GST_HEADERS) diff --git a/core/compile.c b/core/compile.c index 34dfd02e..3acc3b4d 100644 --- a/core/compile.c +++ b/core/compile.c @@ -1010,7 +1010,7 @@ typedef Slot (*SpecialFormHelper) (GstCompiler *c, FormOptions opts, GstValue *f /* Dispatch to a special form */ static SpecialFormHelper get_special(GstValue *form) { - uint8_t *name; + const uint8_t *name; if (gst_tuple_length(form) < 1 || form[0].type != GST_SYMBOL) return NULL; name = form[0].data.string; diff --git a/core/ds.c b/core/ds.c index fef3ef54..ffb1eff7 100644 --- a/core/ds.c +++ b/core/ds.c @@ -42,7 +42,7 @@ void gst_buffer_push(Gst *vm, GstBuffer * buffer, uint8_t c) { } /* Push multiple bytes into the buffer */ -void gst_buffer_append(Gst *vm, GstBuffer *buffer, uint8_t *string, uint32_t length) { +void gst_buffer_append(Gst *vm, GstBuffer *buffer, const uint8_t *string, uint32_t length) { uint32_t newSize = buffer->count + length; if (newSize > buffer->capacity) { gst_buffer_ensure(vm, buffer, 2 * newSize); @@ -52,8 +52,8 @@ void gst_buffer_append(Gst *vm, GstBuffer *buffer, uint8_t *string, uint32_t len } /* Convert the buffer to a string */ -uint8_t *gst_buffer_to_string(Gst *vm, GstBuffer *buffer) { - return gst_load_cstring_rawlen(vm, (char *) buffer->data, buffer->count); +const uint8_t *gst_buffer_to_string(Gst *vm, GstBuffer *buffer) { + return gst_string_loadbuffer(vm, buffer->data, buffer->count); } /****/ @@ -218,39 +218,6 @@ GstValue gst_object_get(GstObject *o, GstValue key) { } } -/* Get a value of the object with a cstring key */ -GstValue gst_object_get_cstring(GstObject *obj, const char *key) { - uint32_t len; - for (len = 0; key[len]; ++len); - uint32_t hash = gst_cstring_calchash((uint8_t *)key, len); - uint32_t index = hash % obj->capacity; - GstBucket *bucket = obj->buckets[index]; - while (bucket) { - if (bucket->key.type == GST_STRING) { - uint8_t *s = bucket->key.data.string; - if (gst_string_length(s) == len) { - if (!gst_string_hash(s)) - gst_string_hash(s) = gst_string_calchash(s); - if (gst_string_hash(s) == hash) { - uint32_t i; - for (i = 0; i < len; ++i) - if (s[i] != key[i]) - goto notequal; - return bucket->value; - } - } - } -notequal: - bucket = bucket->next; - } - /* Return nil */ - { - GstValue ret; - ret.type = GST_NIL; - return ret; - } -} - /* Remove an entry from the dictionary */ GstValue gst_object_remove(Gst * vm, GstObject *o, GstValue key) { GstBucket *bucket, *previous; diff --git a/core/parse.c b/core/parse.c index c4bd7534..ba6112bc 100644 --- a/core/parse.c +++ b/core/parse.c @@ -219,8 +219,8 @@ static int check_str_const(const char *ref, const uint8_t *start, const uint8_t static GstValue build_token(GstParser *p, GstBuffer *buf) { GstValue x; GstNumber number; - uint8_t * data = buf->data; - uint8_t * back = data + buf->count; + uint8_t *data = buf->data; + uint8_t *back = data + buf->count; if (read_number(data, back, &number, 0)) { x.type = GST_NUMBER; x.data.number = number; @@ -453,7 +453,7 @@ int gst_parse_cstring(GstParser *p, const char *string) { } /* Parse a gst string */ -int gst_parse_string(GstParser *p, uint8_t *string) { +int gst_parse_string(GstParser *p, const uint8_t *string) { uint32_t i; p->status = GST_PARSER_PENDING; for (i = 0; i < gst_string_length(string); ++i) { diff --git a/core/serialize.c b/core/serialize.c index 18b7c0d9..49ca7174 100644 --- a/core/serialize.c +++ b/core/serialize.c @@ -34,7 +34,7 @@ static const char UEB[] = "unexpected end of buffer"; /* Read 4 bytes as an unsigned integer */ -static uint32_t bytes2u32(uint8_t *bytes) { +static uint32_t bytes2u32(const uint8_t *bytes) { union { uint8_t bytes[4]; uint32_t u32; @@ -44,7 +44,7 @@ static uint32_t bytes2u32(uint8_t *bytes) { } /* Read 2 bytes as unsigned short */ -static uint16_t bytes2u16(uint8_t *bytes) { +static uint16_t bytes2u16(const uint8_t *bytes) { union { uint8_t bytes[2]; uint16_t u16; @@ -54,7 +54,7 @@ static uint16_t bytes2u16(uint8_t *bytes) { } /* Read 8 bytes as a double */ -static uint32_t bytes2dbl(uint8_t *bytes) { +static uint32_t bytes2dbl(const uint8_t *bytes) { union { uint8_t bytes[8]; double dbl; @@ -69,16 +69,16 @@ static uint32_t bytes2dbl(uint8_t *bytes) { * passed by reference. */ static const char *gst_deserialize_impl( Gst *vm, - uint8_t *data, - uint8_t *end, - uint8_t **newData, + const uint8_t *data, + const uint8_t *end, + const uint8_t **newData, GstArray *visited, GstValue *out) { GstValue ret; ret.type = GST_NIL; GstValue *buffer; - uint8_t *bytebuf; + const uint8_t *bytebuf; uint32_t length, i; const char *err; @@ -135,12 +135,7 @@ static const char *gst_deserialize_impl( ret.type = data[-1] == 205 ? GST_STRING : GST_SYMBOL; read_u32(length); deser_datacheck(length); - ret.data.string = gst_alloc(vm, 2 * sizeof(uint32_t) + length + 1); - ret.data.string += 2 * sizeof(uint32_t); - gst_string_length(ret.data.string) = length; - gst_string_hash(ret.data.string) = 0; - gst_memcpy(ret.data.string, data, length); - ret.data.string[length] = 0; + ret.data.string = gst_string_loadbuffer(vm, data, length); data += length; gst_array_push(vm, visited, ret); break; @@ -151,7 +146,7 @@ static const char *gst_deserialize_impl( deser_datacheck(length); ret.data.buffer = gst_alloc(vm, sizeof(GstBuffer)); ret.data.buffer->data = gst_alloc(vm, length); - gst_memcpy(ret.data.string, data, length); + gst_memcpy(ret.data.buffer->data, data, length); ret.data.buffer->count = length; ret.data.buffer->capacity = length; data += length; @@ -391,10 +386,10 @@ static const char *gst_deserialize_impl( /* Load a value from data */ const char *gst_deserialize( Gst *vm, - uint8_t *data, + const uint8_t *data, uint32_t len, GstValue *out, - uint8_t *nextData) { + const uint8_t *nextData) { GstValue ret; const char *err; GstArray *visited = gst_array(vm, 10); diff --git a/core/stl.c b/core/stl.c index 14842ba7..ffcd42d1 100644 --- a/core/stl.c +++ b/core/stl.c @@ -13,7 +13,7 @@ int gst_stl_print(Gst *vm) { count = gst_count_args(vm); for (j = 0; j < count; ++j) { uint32_t i; - uint8_t *string = gst_to_string(vm, gst_arg(vm, j)); + const uint8_t *string = gst_to_string(vm, gst_arg(vm, j)); uint32_t len = gst_string_length(string); for (i = 0; i < len; ++i) fputc(string[i], stdout); @@ -46,7 +46,7 @@ int gst_stl_make_buffer(Gst *vm) { buf.data.buffer = gst_buffer(vm, 10); count = gst_count_args(vm); for (i = 0; i < count; ++i) { - uint8_t *string = gst_to_string(vm, gst_arg(vm, i)); + const uint8_t *string = gst_to_string(vm, gst_arg(vm, i)); gst_buffer_append(vm, buf.data.buffer, string, gst_string_length(string)); } gst_c_return(vm, buf); @@ -55,7 +55,7 @@ int gst_stl_make_buffer(Gst *vm) { /* To string */ int gst_stl_tostring(Gst *vm) { GstValue ret; - uint8_t *string = gst_to_string(vm, gst_arg(vm, 0)); + const uint8_t *string = gst_to_string(vm, gst_arg(vm, 0)); ret.type = GST_STRING; ret.data.string = string; gst_c_return(vm, ret); @@ -147,8 +147,8 @@ static int read_number(const uint8_t *string, const uint8_t *end, double *ret, i int gst_stl_parse_number(Gst *vm) { GstValue ret; double number; - uint8_t *str = gst_to_string(vm, gst_arg(vm, 0)); - uint8_t *end = str + gst_string_length(str); + const uint8_t *str = gst_to_string(vm, gst_arg(vm, 0)); + const uint8_t *end = str + gst_string_length(str); if (read_number(str, end, &number, 0)) { ret.type = GST_NUMBER; ret.data.number = number; @@ -161,7 +161,7 @@ int gst_stl_parse_number(Gst *vm) { /* Parse a source string into an AST */ int gst_stl_parse(Gst *vm) { - uint8_t *source = gst_to_string(vm, gst_arg(vm, 0)); + const uint8_t *source = gst_to_string(vm, gst_arg(vm, 0)); GstParser p; /* init state */ gst_parser(&p, vm); diff --git a/core/stringcache.c b/core/stringcache.c deleted file mode 100644 index 46c36cd7..00000000 --- a/core/stringcache.c +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include "stringcache.h" - -/* Dud pointer to serve as deletion marker */ -static uint8_t *deleted = (uint8_t *) "DELETED"; - -/* Initialize the string cache for a vm */ -void gst_stringcache_init(Gst *vm, uint32_t capacity) { - vm->strings = gst_raw_calloc(1, capacity * sizeof(uint8_t *)); - if (vm->strings == NULL) - GST_OUT_OF_MEMORY; - vm->stringsCapacity = capacity; - vm->stringsCount = 0; - vm->stringsDeleted = 0; -} - -/* Deinitialize the stringcache for a vm */ -void gst_stringcache_deinit(Gst *vm) { - gst_raw_free(vm->strings); - vm->stringsCapacity = 0; - vm->stringsCount = 0; - vm->stringsDeleted = 0; -} - -/* Find a string in the hashtable. Returns null if - * not found. */ -static uint8_t **gst_stringcache_find(Gst *vm, uint8_t *str, int *success) { - uint32_t bounds[4]; - uint32_t i, j, index, hash; - uint8_t **firstEmpty = NULL; - hash = gst_string_hash(str); - if (!hash) { - hash = gst_string_hash(str) = gst_string_calchash(str); - } - index = hash % vm->stringsCapacity; - bounds[0] = index; - bounds[1] = vm->stringsCapacity; - bounds[2] = 0; - bounds[3] = index; - for (j = 0; j < 4; j += 2) - for (i = bounds[j]; i < bounds[j+1]; ++i) { - uint8_t *testStr = vm->strings[i]; - /* Check empty spots */ - if (testStr == NULL) { - if (firstEmpty == NULL) - firstEmpty = vm->strings + i; - goto notfound; - } - if (testStr == deleted) { - if (firstEmpty == NULL) - firstEmpty = vm->strings + i; - continue; - } - if (gst_string_equal(testStr, str)) { - /* Replace first deleted */ - *success = 1; - if (firstEmpty != NULL) { - *firstEmpty = testStr; - vm->strings[i] = deleted; - return firstEmpty; - } - return vm->strings + i; - } - } - notfound: - *success = 0; - return firstEmpty; -} - -/* Resize the hashtable. */ -static void gst_stringcache_resize(Gst *vm, uint32_t newCapacity) { - uint32_t i, oldCapacity; - uint8_t **oldCache = vm->strings; - uint8_t **newCache = gst_raw_calloc(1, newCapacity * sizeof(uint8_t *)); - if (newCache == NULL) - GST_OUT_OF_MEMORY; - oldCapacity = vm->stringsCapacity; - vm->strings = newCache; - vm->stringsCapacity = newCapacity; - vm->stringsCount = 0; - vm->stringsDeleted = 0; - /* Add all of the old strings back */ - for (i = 0; i < oldCapacity; ++i) { - uint8_t *str = oldCache[i]; - if (str != NULL && str != deleted) - gst_stringcache_get(vm, str); - } - /* Free the old cache */ - gst_raw_free(oldCache); -} - -/* Get a string from the string cache */ -uint8_t *gst_stringcache_get(Gst *vm, uint8_t *str) { - int status = 0; - uint8_t **bucket = gst_stringcache_find(vm, str, &status); - if (status) { - return *bucket; - } else { - if ((vm->stringsCount + vm->stringsDeleted) * 2 > vm->stringsCapacity) { - gst_stringcache_resize(vm, vm->stringsCount * 4); - bucket = gst_stringcache_find(vm, str, &status); - } - vm->stringsCount++; - *bucket = str; - /* Mark the memory as string memory */ - gst_mem_tag(gst_string_raw(str), GST_MEMTAG_STRING); - return str; - } -} - -/* Remove a string from the cache */ -void gst_stringcache_remove(Gst *vm, uint8_t *str) { - int status = 0; - uint8_t **bucket = gst_stringcache_find(vm, str, &status); - if (status) { - vm->stringsCount--; - vm->stringsDeleted++; - *bucket = deleted; - } -} diff --git a/core/stringcache.h b/core/stringcache.h index f4c2899f..cbe2057d 100644 --- a/core/stringcache.h +++ b/core/stringcache.h @@ -9,7 +9,6 @@ void gst_stringcache_init(Gst *vm, uint32_t capacity); void gst_stringcache_deinit(Gst *vm); -uint8_t *gst_stringcache_get(Gst *vm, uint8_t *str); -void gst_stringcache_remove(Gst *vm, uint8_t *str); +void gst_stringcache_remove(Gst *vm, const uint8_t *str); #endif diff --git a/core/strings.c b/core/strings.c index bb3d0f46..70bad7f2 100644 --- a/core/strings.c +++ b/core/strings.c @@ -1,35 +1,28 @@ #include #include "stringcache.h" -uint8_t *gst_load_cstring_rawlen(Gst *vm, const char *string, uint32_t len) { - uint8_t *data = gst_alloc(vm, len + 1 + 2 * sizeof(uint32_t)); - data += 2 * sizeof(uint32_t); - gst_string_hash(data) = 0; - gst_string_length(data) = len; - gst_memcpy(data, string, len); - data[len] = 0; - /* Check string cache */ - return gst_stringcache_get(vm, data); -} +/* Dud pointer to serve as deletion marker */ +static uint8_t *deleted = (uint8_t *) ""; -/* Load a c string into a GST string */ -GstValue gst_load_cstring(Gst *vm, const char *string) { - GstValue ret; - ret.type = GST_STRING; - ret.data.string = gst_load_cstring_rawlen(vm, string, strlen(string)); - return ret; -} - -/* Load a c string into a GST symbol */ -GstValue gst_load_csymbol(Gst *vm, const char *string) { - GstValue ret; - ret.type = GST_SYMBOL; - ret.data.string = gst_load_cstring_rawlen(vm, string, strlen(string)); - return ret; +/* Check if string and cstring are equal */ +/* To check if strings are equal externally, one can + * just use == */ +static int gst_cstring_equal(const uint8_t *lhs, const uint8_t *rhs, uint32_t rlen, uint32_t rhash) { + uint32_t lhash, len, i; + /* Check lengths */ + len = gst_string_length(lhs); + if (len != rlen) return 0; + /* Check hashes */ + lhash = gst_string_hash(lhs); + if (lhash != rhash) return 0; + for (i = 0; i < len; ++i) + if (lhs[i] != rhs[i]) + return 0; + return 1; } /* Simple hash function (djb2) */ -uint32_t gst_cstring_calchash(const uint8_t *str, uint32_t len) { +static uint32_t gst_string_calchash(const uint8_t *str, uint32_t len) { const uint8_t *end = str + len; uint32_t hash = 5381; while (str < end) @@ -37,31 +30,202 @@ uint32_t gst_cstring_calchash(const uint8_t *str, uint32_t len) { return hash; } -/* GST string version */ -uint32_t gst_string_calchash(const uint8_t *str) { - return gst_cstring_calchash(str, gst_string_length(str)); +/* Find a string in the hashtable. Returns null if + * not found. */ +static const uint8_t **gst_stringcache_find( + Gst *vm, + const uint8_t *str, + uint32_t len, + uint32_t hash, + int *success) { + uint32_t bounds[4]; + uint32_t i, j, index; + const uint8_t **firstEmpty = NULL; + index = hash % vm->stringsCapacity; + bounds[0] = index; + bounds[1] = vm->stringsCapacity; + bounds[2] = 0; + bounds[3] = index; + for (j = 0; j < 4; j += 2) + for (i = bounds[j]; i < bounds[j+1]; ++i) { + const uint8_t *testStr = vm->strings[i]; + /* Check empty spots */ + if (testStr == NULL) { + if (firstEmpty == NULL) + firstEmpty = vm->strings + i; + goto notfound; + } + if (testStr == deleted) { + if (firstEmpty == NULL) + firstEmpty = vm->strings + i; + continue; + } + if (gst_cstring_equal(testStr, str, len, hash)) { + /* Replace first deleted */ + *success = 1; + if (firstEmpty != NULL) { + *firstEmpty = testStr; + vm->strings[i] = deleted; + return firstEmpty; + } + return vm->strings + i; + } + } + notfound: + *success = 0; + return firstEmpty; } -/* Check if two strings are equal. Does not check the string cache. */ -int gst_string_equal(const uint8_t *lhs, const uint8_t *rhs) { - uint32_t hash_l, hash_r, len, i; - if (lhs == rhs) - return 1; - /* Check lengths */ - len = gst_string_length(lhs); - if (len != gst_string_length(rhs)) return 0; - /* Check hashes */ - hash_l = gst_string_hash(lhs); - hash_r = gst_string_hash(rhs); - if (!hash_l) - hash_l = gst_string_hash(lhs) = gst_string_calchash(lhs); - if (!hash_r) - hash_r = gst_string_hash(rhs) = gst_string_calchash(rhs); - if (hash_l != hash_r) return 0; - for (i = 0; i < len; ++i) - if (lhs[i] != rhs[i]) - return 0; - return 1; +/* Resize the hashtable. */ +static void gst_stringcache_resize(Gst *vm, uint32_t newCapacity) { + uint32_t i, oldCapacity; + const uint8_t **oldCache = vm->strings; + const uint8_t **newCache = gst_raw_calloc(1, newCapacity * sizeof(uint8_t *)); + if (newCache == NULL) + GST_OUT_OF_MEMORY; + oldCapacity = vm->stringsCapacity; + vm->strings = newCache; + vm->stringsCapacity = newCapacity; + vm->stringsDeleted = 0; + /* Add all of the old strings back */ + for (i = 0; i < oldCapacity; ++i) { + int status; + const uint8_t **bucket; + const uint8_t *str = oldCache[i]; + if (str != NULL && str != deleted) { + bucket = gst_stringcache_find(vm, str, + gst_string_length(str), + gst_string_hash(str), &status); + if (status || bucket == NULL) { + /* there was a problem with the algorithm. */ + break; + } + *bucket = str; + } + } + /* Free the old cache */ + gst_raw_free(oldCache); +} + +/****/ +/* Internal API */ +/****/ + +/* Initialize the string cache for a vm */ +void gst_stringcache_init(Gst *vm, uint32_t capacity) { + vm->strings = gst_raw_calloc(1, capacity * sizeof(uint8_t *)); + if (vm->strings == NULL) + GST_OUT_OF_MEMORY; + vm->stringsCapacity = capacity; + vm->stringsCount = 0; + vm->stringsDeleted = 0; +} + +/* Deinitialize the stringcache for a vm */ +void gst_stringcache_deinit(Gst *vm) { + gst_raw_free(vm->strings); + vm->stringsCapacity = 0; + vm->stringsCount = 0; + vm->stringsDeleted = 0; +} + +/* Remove a string from the cache */ +void gst_stringcache_remove(Gst *vm, const uint8_t *str) { + int status = 0; + const uint8_t **bucket = gst_stringcache_find(vm, str, + gst_string_length(str), + gst_string_hash(str), + &status); + if (status) { + vm->stringsCount--; + vm->stringsDeleted++; + *bucket = deleted; + } +} + +/****/ +/* Public C API */ +/****/ + +/* Begin creation of a string */ +uint8_t *gst_string_begin(Gst *vm, uint32_t len) { + uint8_t *data = gst_alloc(vm, len + 1 + 2 * sizeof(uint32_t)); + data += 2 * sizeof(uint32_t); + gst_string_length(data) = len; + data[len] = 0; + return data; +} + +/* Finish building the string. Calculates the hash and deduplicates it */ +const uint8_t *gst_string_end(Gst *vm, uint8_t *str) { + int status = 0; + const uint8_t **bucket; + uint32_t hash, len; + len = gst_string_length(str); + hash = gst_string_hash(str) = gst_string_calchash(str, len); + bucket = gst_stringcache_find(vm, str, len, hash, &status); + if (status) { + return *bucket; + } else { + if ((vm->stringsCount + vm->stringsDeleted) * 2 > vm->stringsCapacity) { + gst_stringcache_resize(vm, vm->stringsCount * 4); + bucket = gst_stringcache_find(vm, str, len, hash, &status); + } + /* Mark the memory as string memory */ + gst_mem_tag(gst_string_raw(str), GST_MEMTAG_STRING); + vm->stringsCount++; + *bucket = str; + return str; + } +} + +/* Loads a constant buffer as a string into a gst vm */ +const uint8_t *gst_string_loadbuffer(Gst *vm, const uint8_t *buf, uint32_t len) { + int status = 0; + const uint8_t **bucket; + uint32_t hash; + hash = gst_string_calchash(buf, len); + bucket = gst_stringcache_find(vm, buf, len, hash, &status); + if (status) { + return *bucket; + } else { + uint8_t *str; + if ((vm->stringsCount + vm->stringsDeleted) * 2 > vm->stringsCapacity) { + gst_stringcache_resize(vm, vm->stringsCount * 4); + bucket = gst_stringcache_find(vm, buf, len, hash, &status); + } + vm->stringsCount++; + str = gst_string_begin(vm, len); + gst_memcpy(str, buf, len); + gst_string_hash(str) = hash; + /* Mark the memory as string memory */ + gst_mem_tag(gst_string_raw(str), GST_MEMTAG_STRING); + *bucket = str; + return str; + } +} + +/* Converts a c style string to a gst string */ +const uint8_t *gst_cstring_to_string(Gst *vm, const char *cstring) { + uint32_t len = 0; + while (cstring[len]) ++len; + return gst_string_loadbuffer(vm, (const uint8_t *)cstring, len); +} + +/* Load a c string into a GST string */ +GstValue gst_load_cstring(Gst *vm, const char *string) { + GstValue ret; + ret.type = GST_STRING; + ret.data.string = gst_cstring_to_string(vm, string); + return ret; +} + +/* Load a c string into a GST symbol */ +GstValue gst_load_csymbol(Gst *vm, const char *string) { + GstValue ret; + ret.type = GST_SYMBOL; + ret.data.string = gst_cstring_to_string(vm, string); + return ret; } /* Compares two strings */ diff --git a/core/thread.c b/core/thread.c index a461e870..db64dcc0 100644 --- a/core/thread.c +++ b/core/thread.c @@ -105,12 +105,12 @@ GstValue *gst_thread_expand_callable(Gst *vm, GstThread *thread, GstValue callee meta = callee.data.object->meta; if (meta == NULL) return NULL; gst_thread_push(vm, thread, callee); - callee = gst_object_get_cstring(meta, "call"); + callee = gst_object_get(meta, gst_load_cstring(vm, "call")); continue; case GST_USERDATA: meta = ((GstUserdataHeader *)callee.data.pointer - 1)->meta; gst_thread_push(vm, thread, callee); - callee = gst_object_get_cstring(meta, "call"); + callee = gst_object_get(meta, gst_load_cstring(vm, "call")); continue; } } diff --git a/core/value.c b/core/value.c index de3393a3..d28a2b1f 100644 --- a/core/value.c +++ b/core/value.c @@ -6,90 +6,86 @@ int gst_truthy(GstValue v) { return v.type != GST_NIL && !(v.type == GST_BOOLEAN && !v.data.boolean); } -static uint8_t * number_to_string(Gst *vm, GstNumber x) { - static const uint32_t SIZE = 20; - uint8_t *data = gst_alloc(vm, SIZE + 1 + 2 * sizeof(uint32_t)); - data += 2 * sizeof(uint32_t); +/* Temporary buffer size */ +#define GST_BUFSIZE 36 + +static const uint8_t *number_to_string(Gst *vm, GstNumber x) { + uint8_t buf[GST_BUFSIZE]; /* TODO - not depend on stdio */ - snprintf((char *) data, SIZE, "%.21g", x); - gst_string_hash(data) = 0; - gst_string_length(data) = strlen((char *) data); - return data; + int count = snprintf((char *) buf, GST_BUFSIZE, "%.21g", x); + return gst_string_loadbuffer(vm, buf, (uint32_t) count); } static const char *HEX_CHARACTERS = "0123456789abcdef"; #define HEX(i) (((uint8_t *) HEX_CHARACTERS)[(i)]) -/* Returns a string description for a pointer */ -static uint8_t *string_description(Gst *vm, const char *title, uint32_t titlelen, void *pointer) { - uint32_t len = 5 + titlelen + sizeof(void *) * 2; +/* Returns a string description for a pointer. Max titlelen is GST_BUFSIZE + * - 5 - 2 * sizeof(void *). */ +static const uint8_t *string_description(Gst *vm, const char *title, void *pointer) { + uint8_t buf[GST_BUFSIZE]; + uint8_t *c = buf; uint32_t i; - uint8_t *data = gst_alloc(vm, len + 1 + 2 * sizeof(uint32_t)); - uint8_t *c; union { uint8_t bytes[sizeof(void *)]; void *p; - } buf; - buf.p = pointer; - data += 2 * sizeof(uint32_t); - c = data; + } pbuf; + + pbuf.p = pointer; *c++ = '<'; - for (i = 0; i < titlelen; ++i) { + for (i = 0; title[i]; ++i) *c++ = ((uint8_t *)title) [i]; - } *c++ = ' '; *c++ = '0'; *c++ = 'x'; for (i = sizeof(void *); i > 0; --i) { - uint8_t byte = buf.bytes[i - 1]; + uint8_t byte = pbuf.bytes[i - 1]; if (!byte) continue; *c++ = HEX(byte >> 4); *c++ = HEX(byte & 0xF); } *c++ = '>'; - gst_string_hash(data) = 0; - gst_string_length(data) = c - data; - *c = 0; - return data; + return gst_string_loadbuffer(vm, buf, c - buf); } +#undef GST_BUFSIZE + /* Returns a string pointer or NULL if could not allocate memory. */ -uint8_t *gst_to_string(Gst *vm, GstValue x) { +const uint8_t *gst_to_string(Gst *vm, GstValue x) { switch (x.type) { case GST_NIL: - return gst_load_cstring_rawlen(vm, "nil", 3); + return gst_cstring_to_string(vm, "nil"); case GST_BOOLEAN: if (x.data.boolean) { - return gst_load_cstring_rawlen(vm, "true", 4); + return gst_cstring_to_string(vm, "true"); } else { - return gst_load_cstring_rawlen(vm, "false", 5); + return gst_cstring_to_string(vm, "false"); } case GST_NUMBER: return number_to_string(vm, x.data.number); case GST_ARRAY: - return string_description(vm, "array", 5, x.data.pointer); + return string_description(vm, "array", x.data.pointer); case GST_TUPLE: - return string_description(vm, "tuple", 5, x.data.pointer); + return string_description(vm, "tuple", x.data.pointer); case GST_OBJECT: - return string_description(vm, "object", 6, x.data.pointer); + return string_description(vm, "object", x.data.pointer); case GST_STRING: return x.data.string; case GST_SYMBOL: - return string_description(vm, "symbol", 6, x.data.pointer); + return string_description(vm, "symbol", x.data.pointer); case GST_BYTEBUFFER: - return string_description(vm, "buffer", 6, x.data.pointer); + return string_description(vm, "buffer", x.data.pointer); case GST_CFUNCTION: - return string_description(vm, "cfunction", 9, x.data.pointer); + return string_description(vm, "cfunction", x.data.pointer); case GST_FUNCTION: - return string_description(vm, "function", 8, x.data.pointer); + return string_description(vm, "function", x.data.pointer); case GST_THREAD: - return string_description(vm, "thread", 6, x.data.pointer); + return string_description(vm, "thread", x.data.pointer); case GST_USERDATA: - return string_description(vm, "userdata", 8, x.data.pointer); + return string_description(vm, "userdata", x.data.pointer); case GST_FUNCENV: - return string_description(vm, "funcenv", 7, x.data.pointer); + return string_description(vm, "funcenv", x.data.pointer); case GST_FUNCDEF: - return string_description(vm, "funcdef", 7, x.data.pointer); + return string_description(vm, "funcdef", x.data.pointer); } return NULL; } @@ -173,10 +169,7 @@ uint32_t gst_hash(GstValue x) { /* String hashes */ case GST_STRING: case GST_SYMBOL: - /* Assume 0 is not hashed. */ hash = gst_string_hash(x.data.string); - if (!hash) - hash = gst_string_hash(x.data.string) = gst_string_calchash(x.data.string); break; case GST_TUPLE: if (gst_tuple_hash(x.data.tuple)) @@ -418,8 +411,9 @@ int gst_length(Gst *vm, GstValue x, GstValue *len) { case GST_OBJECT: /* TODO - Check for class override */ if (x.data.object->meta != NULL) { - GstValue check = gst_object_get_cstring( - x.data.object->meta, "length"); + GstValue check = gst_object_get( + x.data.object->meta, + gst_load_cstring(vm, "length")); if (check.type != GST_NIL) { int status = gst_call(vm, check, 1, &x); if (status == GST_RETURN_OK)