1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-28 11:09:54 +00:00

Retabbed things

This commit is contained in:
Calvin Rose 2017-03-15 01:26:45 -04:00
parent 9f09a19feb
commit ba82ba414a
5 changed files with 364 additions and 364 deletions

306
dict.c
View File

@ -11,25 +11,25 @@
static GstValue *gst_object_bag_find(GstDict *obj, GstValue key) { static GstValue *gst_object_bag_find(GstDict *obj, GstValue key) {
GstValue *start = obj->data; GstValue *start = obj->data;
GstValue *end = obj->data + obj->count * 2; GstValue *end = obj->data + obj->count * 2;
while (start < end) { while (start < end) {
if (gst_equals(*start, key)) if (gst_equals(*start, key))
return start; return start;
start += 2; start += 2;
} }
return NULL; return NULL;
} }
/* Check for string equality */ /* Check for string equality */
static int str_equal_value(GstValue v, const char *str, uint32_t len, uint32_t hash) { static int str_equal_value(GstValue v, const char *str, uint32_t len, uint32_t hash) {
uint32_t i; uint32_t i;
if (v.type != GST_STRING) return 0; if (v.type != GST_STRING) return 0;
if (gst_string_length(str) != len) return 0; if (gst_string_length(str) != len) return 0;
if (!gst_string_hash(str)) if (!gst_string_hash(str))
gst_string_hash(str) = gst_string_calchash((uint8_t *)str); gst_string_hash(str) = gst_string_calchash((uint8_t *)str);
if (gst_string_hash(str) != hash) return 0; if (gst_string_hash(str) != hash) return 0;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
if (str[1] != v.data.string[i]) return 0; if (str[1] != v.data.string[i]) return 0;
return 1; return 1;
} }
/* Find key value pair with c string key */ /* Find key value pair with c string key */
@ -39,53 +39,53 @@ static GstValue *gst_object_bag_findcstring(GstDict *obj, const char *key) {
hash = gst_cstring_calchash((uint8_t *)key, len); hash = gst_cstring_calchash((uint8_t *)key, len);
GstValue *start = obj->data; GstValue *start = obj->data;
GstValue *end = obj->data + obj->count * 2; GstValue *end = obj->data + obj->count * 2;
while (start < end) { while (start < end) {
if (start->type == GST_STRING) { if (start->type == GST_STRING) {
uint8_t *str = start->data.string; uint8_t *str = start->data.string;
if (gst_string_length(str) == len) { if (gst_string_length(str) == len) {
if (!gst_string_hash(str)) if (!gst_string_hash(str))
gst_string_hash(str) = gst_string_calchash(str); gst_string_hash(str) = gst_string_calchash(str);
if (gst_string_hash(str) == hash) { if (gst_string_hash(str) == hash) {
return start return start
} }
} }
} }
start += 2; start += 2;
} }
return NULL; return NULL;
} }
/* Remove a key from a bag */ /* Remove a key from a bag */
static void gst_object_bag_remove(GstDict *obj, GstValue key) { static void gst_object_bag_remove(GstDict *obj, GstValue key) {
GstValue *kv = gst_object_bag_find(obj, key); GstValue *kv = gst_object_bag_find(obj, key);
if (kv != NULL) { if (kv != NULL) {
GstValue *lastKv = obj->data + --obj->count * 2; GstValue *lastKv = obj->data + --obj->count * 2;
kv[0] = lastKv[0]; kv[0] = lastKv[0];
kv[1] = lastKv[1]; kv[1] = lastKv[1];
} }
} }
/* Add a key to a bag */ /* Add a key to a bag */
static void gst_object_bag_put(Gst *vm, GstDict *obj, GstValue key, GstValue value) { static void gst_object_bag_put(Gst *vm, GstDict *obj, GstValue key, GstValue value) {
GstValue *kv = gst_object_bag_find(obj, key); GstValue *kv = gst_object_bag_find(obj, key);
if (kv != NULL) { if (kv != NULL) {
/* Replace value */ /* Replace value */
kv[1] = value; kv[1] = value;
} else { } else {
/* Check for need to resize */ /* Check for need to resize */
if (obj->count + 1 > obj->capacity) { if (obj->count + 1 > obj->capacity) {
uint32_t newCap = 2 * obj->count + 2; uint32_t newCap = 2 * obj->count + 2;
GstValue *newData = gst_alloc(vm, sizeof(GstValue) * 2 * newCap); GstValue *newData = gst_alloc(vm, sizeof(GstValue) * 2 * newCap);
gst_memcpy(newData, obj->data, obj->count * 2 * sizeof(GstValue)); gst_memcpy(newData, obj->data, obj->count * 2 * sizeof(GstValue));
obj->data = newData; obj->data = newData;
obj->capacity = newCap; obj->capacity = newCap;
} }
/* Push to end */ /* Push to end */
kv = obj->data + obj->count * 2; kv = obj->data + obj->count * 2;
kv[0] = key; kv[0] = key;
kv[1] = value; kv[1] = value;
++obj->count; ++obj->count;
} }
} }
/****/ /****/
@ -94,58 +94,58 @@ static void gst_object_bag_put(Gst *vm, GstDict *obj, GstValue key, GstValue val
/* Add a key value pair to a given array. Returns if key successfully added. */ /* Add a key value pair to a given array. Returns if key successfully added. */
static void hash_putkv(GstValue *data, uint32_t cap, GstValue key, GstValue value) { static void hash_putkv(GstValue *data, uint32_t cap, GstValue key, GstValue value) {
GstValue *end = data + 2 * cap; GstValue *end = data + 2 * cap;
GstValue *start = data + (gst_hash(key) % cap) * 2; GstValue *start = data + (gst_hash(key) % cap) * 2;
GstValue *bucket; GstValue *bucket;
/* Check second half of array */ /* Check second half of array */
for (bucket = start; bucket < end; bucket += 2) { for (bucket = start; bucket < end; bucket += 2) {
if (bucket[0].type == GST_NIL) { if (bucket[0].type == GST_NIL) {
bucket[0] = key; bucket[0] = key;
bucket[1] = value; bucket[1] = value;
return; return;
} }
} }
/* Check first half of array */ /* Check first half of array */
for (bucket = data; bucket < start; bucket += 2) { for (bucket = data; bucket < start; bucket += 2) {
if (bucket[0].type == GST_NIL) { if (bucket[0].type == GST_NIL) {
bucket[0] = key; bucket[0] = key;
bucket[1] = value; bucket[1] = value;
return; return;
} }
} }
/* Should never reach here - data would be full */ /* Should never reach here - data would be full */
} }
/* Find a bucket in the hastable */ /* Find a bucket in the hastable */
static GstValue *hash_findkv(GstValue *data, uint32_t cap, GstValue key, GstValue **out) { static GstValue *hash_findkv(GstValue *data, uint32_t cap, GstValue key, GstValue **out) {
GstValue *end = data + 2 * cap; GstValue *end = data + 2 * cap;
GstValue *start = data + (gst_hash(key) % cap) * 2; GstValue *start = data + (gst_hash(key) % cap) * 2;
GstValue *bucket; GstValue *bucket;
/* Check second half of array */ /* Check second half of array */
for (bucket = start; bucket < end; bucket += 2) for (bucket = start; bucket < end; bucket += 2)
if (bucket[0].type == GST_NIL) if (bucket[0].type == GST_NIL)
if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */
continue; continue;
else { else {
*out = bucket; *out = bucket;
return NULL; return NULL;
} }
else if (gst_equals(bucket[0], key)) else if (gst_equals(bucket[0], key))
return bucket; return bucket;
/* Check first half of array */ /* Check first half of array */
for (bucket = data; bucket < start; bucket += 2) for (bucket = data; bucket < start; bucket += 2)
if (bucket[0].type == GST_NIL) if (bucket[0].type == GST_NIL)
if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */
continue; continue;
else { else {
*out = bucket; *out = bucket;
return NULL; return NULL;
} }
else if (gst_equals(bucket[0], key)) else if (gst_equals(bucket[0], key))
return bucket; return bucket;
/* Should never reach here - data would be full */ /* Should never reach here - data would be full */
*out = bucket; *out = bucket;
return NULL; return NULL;
} }
/* Resize internal hashtable. Also works if currently a bag. */ /* Resize internal hashtable. Also works if currently a bag. */
@ -155,32 +155,32 @@ static void gst_object_rehash(Gst *vm, GstDict *obj, uint32_t capacity) {
toEnd = toData + 2 * capacity; toEnd = toData + 2 * capacity;
fromBucket = obj->data; fromBucket = obj->data;
fromEnd = fromBucket + obj->count * 2; fromEnd = fromBucket + obj->count * 2;
for (; fromBucket < fromEnd; fromBucket += 2) { for (; fromBucket < fromEnd; fromBucket += 2) {
if (fromBucket[0].type == GST_NIL) continue; if (fromBucket[0].type == GST_NIL) continue;
toStart = toData + (gst_hash(fromBucket[0]) % capacity) * 2; toStart = toData + (gst_hash(fromBucket[0]) % capacity) * 2;
/* Check second half of array */ /* Check second half of array */
for (toBucket = toStart; toBucket < toEnd; toBucket += 2) { for (toBucket = toStart; toBucket < toEnd; toBucket += 2) {
if (toBucket[0].type == GST_NIL) { if (toBucket[0].type == GST_NIL) {
toBucket[0] = fromBucket[0]; toBucket[0] = fromBucket[0];
toBucket[1] = fromBucket[1]; toBucket[1] = fromBucket[1];
goto finish_put; goto finish_put;
} }
} }
/* Check first half of array */ /* Check first half of array */
for (toBucket = toData; toBucket < toStart; toBucket += 2) { for (toBucket = toData; toBucket < toStart; toBucket += 2) {
if (toBucket[0].type == GST_NIL) { if (toBucket[0].type == GST_NIL) {
toBucket[0] = fromBucket[0]; toBucket[0] = fromBucket[0];
toBucket[1] = fromBucket[1]; toBucket[1] = fromBucket[1];
goto finish_put; goto finish_put;
} }
} }
/* Error if we got here - backing array to small. */ /* Error if we got here - backing array to small. */
; ;
/* Continue. */ /* Continue. */
finish_put: continue; finish_put: continue;
} }
obj->capacity = capacity; obj->capacity = capacity;
obj->data = toData; obj->data = toData;
} }
/****/ /****/
@ -202,16 +202,16 @@ GstDict *gst_dict(Gst *vm, uint32_t capacity) {
GstValue gst_dict_get(GstDict *dict, GstValue key) { GstValue gst_dict_get(GstDict *dict, GstValue key) {
GstValue *bucket *notused; GstValue *bucket *notused;
if (dict->flags & GST_OBJECT_FLAG_ISBAG) { if (dict->flags & GST_OBJECT_FLAG_ISBAG) {
bucket = gst_object_bag_find(dict, key); bucket = gst_object_bag_find(dict, key);
} else { } else {
bucket = hash_findkv(obj->data, obj->capacity, key, &notused); bucket = hash_findkv(obj->data, obj->capacity, key, &notused);
} }
if (bucket != NULL) { if (bucket != NULL) {
return bucket[1]; return bucket[1];
} else { } else {
GstValue ret; GstValue ret;
ret.type = GST_NIL; ret.type = GST_NIL;
return ret; return ret;
} }
} }
@ -223,42 +223,42 @@ void gst_dict_put(Gst *vm, GstDict *obj, GstValue key, GstValue value) {
if (obj->flags & GST_OBJECT_FLAG_ISBAG) { if (obj->flags & GST_OBJECT_FLAG_ISBAG) {
if (obj->count > GST_OBJECT_BAG_THRESHOLD) { if (obj->count > GST_OBJECT_BAG_THRESHOLD) {
/* Change to hashtable */ /* Change to hashtable */
obj->flags |= GST_OBJECT_FLAG_ISBAG; obj->flags |= GST_OBJECT_FLAG_ISBAG;
gst_object_rehash(vm, obj, 4 * obj->count); gst_object_rehash(vm, obj, 4 * obj->count);
goto put_hash; goto put_hash;
} }
gst_object_bag_put(vm, obj, key, value); gst_object_bag_put(vm, obj, key, value);
} else { } else {
GstValue *bucket, *out; GstValue *bucket, *out;
put_hash: put_hash:
bucket = hash_findkv(obj->data, obj->capacity, key, &out); bucket = hash_findkv(obj->data, obj->capacity, key, &out);
if (bucket != NULL) { if (bucket != NULL) {
bucket[1] = value; bucket[1] = value;
} else { } else {
/* Check for resize */ /* Check for resize */
if (obj->count + 1 > obj->capacity) { if (obj->count + 1 > obj->capacity) {
gst_object_rehash(vm, obj, 2 * (obj->count + 1)); gst_object_rehash(vm, obj, 2 * (obj->count + 1));
bucket = hash_findkv(obj->data, obj->capacity, key, &out); bucket = hash_findkv(obj->data, obj->capacity, key, &out);
} }
out[0] = key; out[0] = key;
out[1] = value; out[1] = value;
++obj->count; ++obj->count;
} }
} }
} }
/* Remove item from dictionary */ /* Remove item from dictionary */
void gst_dict_remove(GstDict *obj, GstValue key) { void gst_dict_remove(GstDict *obj, GstValue key) {
if (obj->flags & GST_OBJECT_FLAG_ISBAG) { if (obj->flags & GST_OBJECT_FLAG_ISBAG) {
gst_object_bag_remove(obj, key); gst_object_bag_remove(obj, key);
} else { } else {
GstValue *bucket, *out; GstValue *bucket, *out;
bucket = hash_findkv(obj->data, obj->capacity, key, &out); bucket = hash_findkv(obj->data, obj->capacity, key, &out);
if (bucket != NULL) { if (bucket != NULL) {
--obj->count; --obj->count;
bucket[0].type = GST_NIL; bucket[0].type = GST_NIL;
bucket[1].type = GST_BOOLEAN; bucket[1].type = GST_BOOLEAN;
} }
} }
} }

2
ds.c
View File

@ -229,7 +229,7 @@ GstValue gst_object_get(GstObject *o, GstValue key) {
/* Get a value of the object with a cstring key */ /* Get a value of the object with a cstring key */
GstValue gst_object_get_cstring(GstObject *obj, const char *key) { GstValue gst_object_get_cstring(GstObject *obj, const char *key) {
uint32_t len; uint32_t len;
for (len = 0; key[len]; ++len); for (len = 0; key[len]; ++len);
uint32_t hash = gst_cstring_calchash((uint8_t *)key, len); uint32_t hash = gst_cstring_calchash((uint8_t *)key, len);
uint32_t index = hash % obj->capacity; uint32_t index = hash % obj->capacity;
GstBucket *bucket = obj->buckets[index]; GstBucket *bucket = obj->buckets[index];

90
gc.c
View File

@ -45,11 +45,11 @@ static void gst_mark_funcdef(Gst *vm, GstFuncDef *def) {
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
/* If the literal is a NIL type, it actually /* If the literal is a NIL type, it actually
* contains a FuncDef */ * contains a FuncDef */
if (def->literals[i].type == GST_NIL) { if (def->literals[i].type == GST_NIL) {
gst_mark_funcdef(vm, (GstFuncDef *) def->literals[i].data.pointer); gst_mark_funcdef(vm, (GstFuncDef *) def->literals[i].data.pointer);
} else { } else {
gst_mark(vm, def->literals + i); gst_mark(vm, def->literals + i);
} }
} }
} }
} }
@ -141,31 +141,31 @@ void gst_mark(Gst *vm, GstValue *x) {
gc_header(x->data.object)->color = vm->black; gc_header(x->data.object)->color = vm->black;
gc_header(x->data.object->buckets)->color = vm->black; gc_header(x->data.object->buckets)->color = vm->black;
for (i = 0; i < x->data.object->capacity; ++i) { for (i = 0; i < x->data.object->capacity; ++i) {
bucket = x->data.object->buckets[i]; bucket = x->data.object->buckets[i];
while (bucket) { while (bucket) {
gc_header(bucket)->color = vm->black; gc_header(bucket)->color = vm->black;
gst_mark(vm, &bucket->key); gst_mark(vm, &bucket->key);
gst_mark(vm, &bucket->value); gst_mark(vm, &bucket->value);
bucket = bucket->next; bucket = bucket->next;
} }
} }
if (x->data.object->meta != NULL) { if (x->data.object->meta != NULL) {
GstValue temp; GstValue temp;
temp.type = GST_OBJECT; temp.type = GST_OBJECT;
temp.data.object = x->data.object->meta; temp.data.object = x->data.object->meta;
gst_mark(vm, &temp); gst_mark(vm, &temp);
} }
} }
break; break;
case GST_USERDATA: case GST_USERDATA:
if (gc_header(x->data.string - sizeof(GstUserdataHeader))->color != vm->black) { if (gc_header(x->data.string - sizeof(GstUserdataHeader))->color != vm->black) {
GstUserdataHeader *userHeader = (GstUserdataHeader *)x->data.string - 1; GstUserdataHeader *userHeader = (GstUserdataHeader *)x->data.string - 1;
gc_header(userHeader)->color = vm->black; gc_header(userHeader)->color = vm->black;
GstValue temp; GstValue temp;
temp.type = GST_OBJECT; temp.type = GST_OBJECT;
temp.data.object = userHeader->meta; temp.data.object = userHeader->meta;
gst_mark(vm, &temp); gst_mark(vm, &temp);
} }
} }
} }
@ -254,20 +254,20 @@ void gst_clear_memory(Gst *vm) {
/* Header for managed memory blocks */ /* Header for managed memory blocks */
struct MMHeader { struct MMHeader {
struct MMHeader *next; struct MMHeader *next;
struct MMHeader *previous; struct MMHeader *previous;
}; };
/* Initialize managed memory */ /* Initialize managed memory */
void gst_mm_init(GstManagedMemory *mm) { void gst_mm_init(GstManagedMemory *mm) {
*mm = NULL; *mm = NULL;
} }
/* Allocate some managed memory */ /* Allocate some managed memory */
void *gst_mm_alloc(GstManagedMemory *mm, uint32_t size) { void *gst_mm_alloc(GstManagedMemory *mm, uint32_t size) {
struct MMHeader *mem = gst_raw_alloc(size + sizeof(struct MMHeader)); struct MMHeader *mem = gst_raw_alloc(size + sizeof(struct MMHeader));
if (mem == NULL) if (mem == NULL)
return NULL; return NULL;
mem->next = *mm; mem->next = *mm;
mem->previous = NULL; mem->previous = NULL;
*mm = mem; *mm = mem;
@ -276,9 +276,9 @@ void *gst_mm_alloc(GstManagedMemory *mm, uint32_t size) {
/* Intialize zeroed managed memory */ /* Intialize zeroed managed memory */
void *gst_mm_zalloc(GstManagedMemory *mm, uint32_t size) { void *gst_mm_zalloc(GstManagedMemory *mm, uint32_t size) {
struct MMHeader *mem = gst_raw_calloc(1, size + sizeof(struct MMHeader)); struct MMHeader *mem = gst_raw_calloc(1, size + sizeof(struct MMHeader));
if (mem == NULL) if (mem == NULL)
return NULL; return NULL;
mem->next = *mm; mem->next = *mm;
mem->previous = NULL; mem->previous = NULL;
*mm = mem; *mm = mem;
@ -287,32 +287,32 @@ void *gst_mm_zalloc(GstManagedMemory *mm, uint32_t size) {
/* Free a memory block used in managed memory */ /* Free a memory block used in managed memory */
void gst_mm_free(GstManagedMemory *mm, void *block) { void gst_mm_free(GstManagedMemory *mm, void *block) {
struct MMHeader *mem = (struct MMHeader *)(((char *)block) - sizeof(struct MMHeader)); struct MMHeader *mem = (struct MMHeader *)(((char *)block) - sizeof(struct MMHeader));
if (mem->previous != NULL) { if (mem->previous != NULL) {
mem->previous->next = mem->next; mem->previous->next = mem->next;
} else { } else {
*mm = mem->next; *mm = mem->next;
} }
gst_raw_free(mem); gst_raw_free(mem);
} }
/* Free all memory in managed memory */ /* Free all memory in managed memory */
void gst_mm_clear(GstManagedMemory *mm) { void gst_mm_clear(GstManagedMemory *mm) {
struct MMHeader *block = (struct MMHeader *)(*mm); struct MMHeader *block = (struct MMHeader *)(*mm);
struct MMHeader *next; struct MMHeader *next;
while (block != NULL) { while (block != NULL) {
next = block->next; next = block->next;
free(block); free(block);
block = next; block = next;
}; };
*mm = NULL; *mm = NULL;
} }
/* Analog to realloc */ /* Analog to realloc */
void *gst_mm_realloc(GstManagedMemory *mm, void *block, uint32_t nsize) { void *gst_mm_realloc(GstManagedMemory *mm, void *block, uint32_t nsize) {
struct MMHeader *mem = gst_raw_realloc(block, nsize + sizeof(struct MMHeader)); struct MMHeader *mem = gst_raw_realloc(block, nsize + sizeof(struct MMHeader));
if (mem == NULL) if (mem == NULL)
return NULL; return NULL;
mem->next = *mm; mem->next = *mm;
mem->previous = NULL; mem->previous = NULL;
*mm = mem; *mm = mem;

216
thread.c
View File

@ -7,80 +7,80 @@
/* Create a new thread */ /* Create a new thread */
GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) { GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) {
GstThread *thread = gst_alloc(vm, sizeof(GstThread)); GstThread *thread = gst_alloc(vm, sizeof(GstThread));
GstValue *data, *stack; GstValue *data, *stack;
if (capacity < GST_FRAME_SIZE) capacity = GST_FRAME_SIZE; if (capacity < GST_FRAME_SIZE) capacity = GST_FRAME_SIZE;
data = gst_alloc(vm, sizeof(GstValue) * capacity); data = gst_alloc(vm, sizeof(GstValue) * capacity);
thread->capacity = capacity; thread->capacity = capacity;
thread->count = GST_FRAME_SIZE; thread->count = GST_FRAME_SIZE;
thread->data = data; thread->data = data;
thread->status = GST_THREAD_PENDING; thread->status = GST_THREAD_PENDING;
stack = data + GST_FRAME_SIZE; stack = data + GST_FRAME_SIZE;
gst_frame_size(stack) = 0; gst_frame_size(stack) = 0;
gst_frame_prevsize(stack) = 0; gst_frame_prevsize(stack) = 0;
gst_frame_ret(stack) = 0; gst_frame_ret(stack) = 0;
gst_frame_errloc(stack) = 0; gst_frame_errloc(stack) = 0;
gst_frame_pc(stack) = NULL; gst_frame_pc(stack) = NULL;
gst_frame_env(stack) = NULL; gst_frame_env(stack) = NULL;
gst_frame_errjmp(stack) = NULL; gst_frame_errjmp(stack) = NULL;
gst_thread_expand_callable(vm, thread, callee); gst_thread_expand_callable(vm, thread, callee);
gst_thread_endframe(vm, thread); gst_thread_endframe(vm, thread);
return thread; return thread;
} }
/* Ensure that the thread has enough EXTRA capacity */ /* Ensure that the thread has enough EXTRA capacity */
void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra) { void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra) {
GstValue *newData, *stack; GstValue *newData, *stack;
uint32_t usedCapacity, neededCapacity, newCapacity; uint32_t usedCapacity, neededCapacity, newCapacity;
stack = thread->data + thread->count; stack = thread->data + thread->count;
usedCapacity = thread->count + gst_frame_size(stack) + GST_FRAME_SIZE; usedCapacity = thread->count + gst_frame_size(stack) + GST_FRAME_SIZE;
neededCapacity = usedCapacity + extra; neededCapacity = usedCapacity + extra;
if (thread->capacity >= neededCapacity) return; if (thread->capacity >= neededCapacity) return;
newCapacity = 2 * neededCapacity; newCapacity = 2 * neededCapacity;
newData = gst_alloc(vm, sizeof(GstValue) * newCapacity); newData = gst_alloc(vm, sizeof(GstValue) * newCapacity);
gst_memcpy(newData, thread->data, sizeof(GstValue) * usedCapacity); gst_memcpy(newData, thread->data, sizeof(GstValue) * usedCapacity);
thread->data = newData; thread->data = newData;
thread->capacity = newCapacity; thread->capacity = newCapacity;
} }
/* Push a value on the current stack frame*/ /* Push a value on the current stack frame*/
void gst_thread_push(Gst *vm, GstThread *thread, GstValue x) { void gst_thread_push(Gst *vm, GstThread *thread, GstValue x) {
GstValue *stack; GstValue *stack;
gst_thread_ensure_extra(vm, thread, 1); gst_thread_ensure_extra(vm, thread, 1);
stack = thread->data + thread->count; stack = thread->data + thread->count;
stack[gst_frame_size(stack)++] = x; stack[gst_frame_size(stack)++] = x;
} }
/* Push n nils onto the stack */ /* Push n nils onto the stack */
void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n) { void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n) {
GstValue *stack, *current, *end; GstValue *stack, *current, *end;
gst_thread_ensure_extra(vm, thread, n); gst_thread_ensure_extra(vm, thread, n);
stack = thread->data + thread->count; stack = thread->data + thread->count;
current = stack + gst_frame_size(stack); current = stack + gst_frame_size(stack);
end = current + n; end = current + n;
for (; current < end; ++current) { for (; current < end; ++current) {
current->type = GST_NIL; current->type = GST_NIL;
} }
gst_frame_size(stack) += n; gst_frame_size(stack) += n;
} }
/* Package up extra args after and including n into tuple at n*/ /* Package up extra args after and including n into tuple at n*/
void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) { void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) {
GstValue *stack = thread->data + thread->count; GstValue *stack = thread->data + thread->count;
uint32_t size = gst_frame_size(stack); uint32_t size = gst_frame_size(stack);
if (n >= size) { if (n >= size) {
gst_thread_pushnil(vm, thread, n - size + 1); gst_thread_pushnil(vm, thread, n - size + 1);
stack = thread->data + thread->count; stack = thread->data + thread->count;
stack[n].type = GST_TUPLE; stack[n].type = GST_TUPLE;
stack[n].data.tuple = gst_tuple(vm, 0); stack[n].data.tuple = gst_tuple(vm, 0);
} else { } else {
uint32_t i; uint32_t i;
GstValue *tuple = gst_tuple(vm, size - n); GstValue *tuple = gst_tuple(vm, size - n);
for (i = n; i < size; ++i) for (i = n; i < size; ++i)
tuple[i - n] = stack[i]; tuple[i - n] = stack[i];
stack[n].type = GST_TUPLE; stack[n].type = GST_TUPLE;
stack[n].data.tuple = tuple; stack[n].data.tuple = tuple;
gst_frame_size(stack) = n + 1; gst_frame_size(stack) = n + 1;
} }
} }
/* Expand a callee on the stack frame to its delegate function. This means that /* Expand a callee on the stack frame to its delegate function. This means that
@ -128,70 +128,70 @@ GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uin
uint32_t frameOffset; uint32_t frameOffset;
GstValue *oldStack, *newStack; GstValue *oldStack, *newStack;
/* Push the frame */ /* Push the frame */
gst_thread_ensure_extra(vm, thread, GST_FRAME_SIZE + arity + 4); gst_thread_ensure_extra(vm, thread, GST_FRAME_SIZE + arity + 4);
oldStack = thread->data + thread->count; oldStack = thread->data + thread->count;
frameOffset = gst_frame_size(oldStack) + GST_FRAME_SIZE; frameOffset = gst_frame_size(oldStack) + GST_FRAME_SIZE;
newStack = oldStack + frameOffset; newStack = oldStack + frameOffset;
gst_frame_prevsize(newStack) = gst_frame_size(oldStack); gst_frame_prevsize(newStack) = gst_frame_size(oldStack);
gst_frame_env(newStack) = NULL; gst_frame_env(newStack) = NULL;
gst_frame_errjmp(newStack) = NULL; gst_frame_errjmp(newStack) = NULL;
gst_frame_size(newStack) = 0; gst_frame_size(newStack) = 0;
thread->count += frameOffset; thread->count += frameOffset;
/* Get real callable */ /* Get real callable */
if (gst_thread_expand_callable(vm, thread, callee) == NULL) if (gst_thread_expand_callable(vm, thread, callee) == NULL)
return NULL; return NULL;
/* Ensure the extra space and initialize to nil */ /* Ensure the extra space and initialize to nil */
gst_thread_pushnil(vm, thread, arity); gst_thread_pushnil(vm, thread, arity);
/* Return ok */ /* Return ok */
return thread->data + thread->count; return thread->data + thread->count;
} }
/* After pushing arguments to a stack frame created with gst_thread_beginframe, call this /* After pushing arguments to a stack frame created with gst_thread_beginframe, call this
* to finalize the frame before starting a function call. */ * to finalize the frame before starting a function call. */
void gst_thread_endframe(Gst *vm, GstThread *thread) { void gst_thread_endframe(Gst *vm, GstThread *thread) {
GstValue *stack = thread->data + thread->count; GstValue *stack = thread->data + thread->count;
GstValue callee = gst_frame_callee(stack); GstValue callee = gst_frame_callee(stack);
if (callee.type == GST_FUNCTION) { if (callee.type == GST_FUNCTION) {
GstFunction *fn = callee.data.function; GstFunction *fn = callee.data.function;
gst_frame_pc(stack) = fn->def->byteCode; gst_frame_pc(stack) = fn->def->byteCode;
if (fn->def->flags & GST_FUNCDEF_FLAG_VARARG) { if (fn->def->flags & GST_FUNCDEF_FLAG_VARARG) {
uint32_t arity = fn->def->arity; uint32_t arity = fn->def->arity;
gst_thread_tuplepack(vm, thread, arity); gst_thread_tuplepack(vm, thread, arity);
} else { } else {
uint32_t locals = fn->def->locals; uint32_t locals = fn->def->locals;
if (gst_frame_size(stack) < locals) { if (gst_frame_size(stack) < locals) {
gst_thread_pushnil(vm, thread, locals - gst_frame_size(stack)); gst_thread_pushnil(vm, thread, locals - gst_frame_size(stack));
} }
} }
} }
} }
/* Pop a stack frame from the thread. Returns the new stack frame, or /* Pop a stack frame from the thread. Returns the new stack frame, or
* NULL if there are no more frames */ * NULL if there are no more frames */
GstValue *gst_thread_popframe(Gst *vm, GstThread *thread) { GstValue *gst_thread_popframe(Gst *vm, GstThread *thread) {
GstValue *stack = thread->data + thread->count; GstValue *stack = thread->data + thread->count;
uint32_t prevsize = gst_frame_prevsize(stack); uint32_t prevsize = gst_frame_prevsize(stack);
GstValue *nextstack = stack - GST_FRAME_SIZE - prevsize; GstValue *nextstack = stack - GST_FRAME_SIZE - prevsize;
GstFuncEnv *env = gst_frame_env(stack); GstFuncEnv *env = gst_frame_env(stack);
/* Check for closures */ /* Check for closures */
if (env != NULL) { if (env != NULL) {
uint32_t size = gst_frame_size(stack); uint32_t size = gst_frame_size(stack);
env->thread = NULL; env->thread = NULL;
env->stackOffset = size; env->stackOffset = size;
env->values = gst_alloc(vm, sizeof(GstValue) * size); env->values = gst_alloc(vm, sizeof(GstValue) * size);
gst_memcpy(env->values, stack, sizeof(GstValue) * size); gst_memcpy(env->values, stack, sizeof(GstValue) * size);
} }
/* Shrink stack */ /* Shrink stack */
thread->count -= GST_FRAME_SIZE + prevsize; thread->count -= GST_FRAME_SIZE + prevsize;
/* Check if the stack is empty, and if so, return null */ /* Check if the stack is empty, and if so, return null */
if (thread->count) if (thread->count)
return nextstack; return nextstack;
else else
return NULL; return NULL;
@ -201,39 +201,39 @@ GstValue *gst_thread_popframe(Gst *vm, GstThread *thread) {
* for primitive tail calls. */ * for primitive tail calls. */
GstValue *gst_thread_tail(Gst *vm, GstThread *thread) { GstValue *gst_thread_tail(Gst *vm, GstThread *thread) {
GstFuncEnv *env; GstFuncEnv *env;
GstValue *stack = thread->data + thread->count; GstValue *stack = thread->data + thread->count;
GstValue *nextStack = gst_thread_popframe(vm, thread); GstValue *nextStack = gst_thread_popframe(vm, thread);
uint32_t i; uint32_t i;
if (nextStack == NULL) return NULL; if (nextStack == NULL) return NULL;
env = gst_frame_env(nextStack); env = gst_frame_env(nextStack);
/* Check for old closures */ /* Check for old closures */
if (env != NULL) { if (env != NULL) {
uint32_t size = gst_frame_size(stack); uint32_t size = gst_frame_size(stack);
env->thread = NULL; env->thread = NULL;
env->stackOffset = size; env->stackOffset = size;
env->values = gst_alloc(vm, sizeof(GstValue) * size); env->values = gst_alloc(vm, sizeof(GstValue) * size);
gst_memcpy(env->values, stack, sizeof(GstValue) * size); gst_memcpy(env->values, stack, sizeof(GstValue) * size);
} }
/* Modify new closure */ /* Modify new closure */
env = gst_frame_env(stack); env = gst_frame_env(stack);
if (env != NULL) { if (env != NULL) {
env->stackOffset = thread->count; env->stackOffset = thread->count;
} }
/* Copy over (some of) stack frame. Leave ret and prevsize untouched. */ /* Copy over (some of) stack frame. Leave ret and prevsize untouched. */
gst_frame_env(nextStack) = env; gst_frame_env(nextStack) = env;
gst_frame_size(nextStack) = gst_frame_size(stack); gst_frame_size(nextStack) = gst_frame_size(stack);
gst_frame_pc(nextStack) = gst_frame_pc(stack); gst_frame_pc(nextStack) = gst_frame_pc(stack);
gst_frame_errjmp(nextStack) = gst_frame_errjmp(stack); gst_frame_errjmp(nextStack) = gst_frame_errjmp(stack);
gst_frame_errloc(nextStack) = gst_frame_errloc(stack); gst_frame_errloc(nextStack) = gst_frame_errloc(stack);
gst_frame_callee(nextStack) = gst_frame_callee(stack); gst_frame_callee(nextStack) = gst_frame_callee(stack);
/* Copy stack arguments */ /* Copy stack arguments */
for (i = 0; i < gst_frame_size(nextStack); ++i) for (i = 0; i < gst_frame_size(nextStack); ++i)
nextStack[i] = stack[i]; nextStack[i] = stack[i];
return nextStack; return nextStack;
} }

114
vm.c
View File

@ -349,7 +349,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
continue; continue;
case GST_OP_RET: /* Return */ case GST_OP_RET: /* Return */
temp = stack[pc[1]]; temp = stack[pc[1]];
stack = gst_thread_popframe(vm, &thread); stack = gst_thread_popframe(vm, &thread);
if (thread.count < stackBase) { if (thread.count < stackBase) {
vm->ret = temp; vm->ret = temp;
@ -362,59 +362,59 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) {
case GST_OP_CAL: /* Call */ case GST_OP_CAL: /* Call */
case GST_OP_TCL: /* Tail call */ case GST_OP_TCL: /* Tail call */
{ {
GstValue *oldStack; GstValue *oldStack;
temp = stack[pc[1]]; temp = stack[pc[1]];
int isTCall = *pc == GST_OP_TCL; int isTCall = *pc == GST_OP_TCL;
uint32_t i, arity, offset, size; uint32_t i, arity, offset, size;
uint16_t ret = pc[2]; uint16_t ret = pc[2];
offset = isTCall ? 3 : 4; offset = isTCall ? 3 : 4;
arity = pc[offset - 1]; arity = pc[offset - 1];
/* Push new frame */ /* Push new frame */
stack = gst_thread_beginframe(vm, &thread, temp, arity); stack = gst_thread_beginframe(vm, &thread, temp, arity);
oldStack = stack - GST_FRAME_SIZE - gst_frame_prevsize(stack); oldStack = stack - GST_FRAME_SIZE - gst_frame_prevsize(stack);
/* Write arguments */ /* Write arguments */
size = gst_frame_size(stack); size = gst_frame_size(stack);
for (i = 0; i < arity; ++i) for (i = 0; i < arity; ++i)
stack[i + size - arity] = oldStack[pc[offset + i]]; stack[i + size - arity] = oldStack[pc[offset + i]];
/* Finish new frame */ /* Finish new frame */
gst_thread_endframe(vm, &thread); gst_thread_endframe(vm, &thread);
/* Check tail call - if so, replace frame. */ /* Check tail call - if so, replace frame. */
if (isTCall) { if (isTCall) {
stack = gst_thread_tail(vm, &thread); stack = gst_thread_tail(vm, &thread);
} else { } else {
gst_frame_ret(oldStack) = ret; gst_frame_ret(oldStack) = ret;
} }
/* Call function */ /* Call function */
temp = gst_frame_callee(stack); temp = gst_frame_callee(stack);
if (temp.type == GST_FUNCTION) { if (temp.type == GST_FUNCTION) {
/* Save pc and set new pc */ /* Save pc and set new pc */
if (!isTCall) if (!isTCall)
gst_frame_pc(oldStack) = pc + offset + arity; gst_frame_pc(oldStack) = pc + offset + arity;
pc = temp.data.function->def->byteCode; pc = temp.data.function->def->byteCode;
} else { } else {
int status; int status;
GST_STATE_WRITE(); GST_STATE_WRITE();
vm->ret.type = GST_NIL; vm->ret.type = GST_NIL;
status = temp.data.cfunction(vm); status = temp.data.cfunction(vm);
GST_STATE_SYNC(); GST_STATE_SYNC();
stack = gst_thread_popframe(vm, &thread); stack = gst_thread_popframe(vm, &thread);
if (status == GST_RETURN_OK) if (status == GST_RETURN_OK)
if (thread.count < stackBase) { if (thread.count < stackBase) {
GST_STATE_WRITE(); GST_STATE_WRITE();
return status; return status;
} else { } else {
stack[gst_frame_ret(stack)] = vm->ret; stack[gst_frame_ret(stack)] = vm->ret;
if (isTCall) if (isTCall)
pc = gst_frame_pc(stack); pc = gst_frame_pc(stack);
else else
pc += offset + arity; pc += offset + arity;
} }
else else
goto vm_error; goto vm_error;
} }
} }
break; break;
/* Handle errors from c functions and vm opcodes */ /* Handle errors from c functions and vm opcodes */
vm_error: vm_error:
@ -453,11 +453,11 @@ int gst_run(Gst *vm, GstValue callee) {
/* If callee was not actually a function, get the delegate function */ /* If callee was not actually a function, get the delegate function */
callee = gst_frame_callee(stack); callee = gst_frame_callee(stack);
if (callee.type == GST_CFUNCTION) { if (callee.type == GST_CFUNCTION) {
int status; int status;
vm->ret.type = GST_NIL; vm->ret.type = GST_NIL;
status = callee.data.cfunction(vm); status = callee.data.cfunction(vm);
gst_thread_popframe(vm, vm->thread); gst_thread_popframe(vm, vm->thread);
return status; return status;
} else { } else {
return gst_continue(vm); return gst_continue(vm);
} }
@ -484,15 +484,15 @@ int gst_call(Gst *vm, GstValue callee, uint32_t arity, GstValue *args) {
gst_thread_endframe(vm, vm->thread); gst_thread_endframe(vm, vm->thread);
/* Call function */ /* Call function */
callee = gst_frame_callee(stack); callee = gst_frame_callee(stack);
if (callee.type == GST_FUNCTION) { if (callee.type == GST_FUNCTION) {
gst_frame_pc(stack) = callee.data.function->def->byteCode; gst_frame_pc(stack) = callee.data.function->def->byteCode;
status = gst_continue(vm); status = gst_continue(vm);
} else { } else {
vm->ret.type = GST_NIL; vm->ret.type = GST_NIL;
status = callee.data.cfunction(vm); status = callee.data.cfunction(vm);
gst_thread_popframe(vm, vm->thread); gst_thread_popframe(vm, vm->thread);
} }
/* Pop the extra nil */ /* Pop the extra nil */
--gst_frame_size(gst_thread_stack(vm->thread)); --gst_frame_size(gst_thread_stack(vm->thread));