diff --git a/dict.c b/dict.c index f9087502..d4346503 100644 --- a/dict.c +++ b/dict.c @@ -11,25 +11,25 @@ static GstValue *gst_object_bag_find(GstDict *obj, GstValue key) { GstValue *start = obj->data; GstValue *end = obj->data + obj->count * 2; - while (start < end) { - if (gst_equals(*start, key)) - return start; - start += 2; - } - return NULL; + while (start < end) { + if (gst_equals(*start, key)) + return start; + start += 2; + } + return NULL; } /* Check for string equality */ 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 (gst_string_length(str) != len) return 0; - if (!gst_string_hash(str)) - gst_string_hash(str) = gst_string_calchash((uint8_t *)str); - if (gst_string_hash(str) != hash) return 0; - for (i = 0; i < len; ++i) - if (str[1] != v.data.string[i]) return 0; - return 1; + if (gst_string_length(str) != len) return 0; + if (!gst_string_hash(str)) + gst_string_hash(str) = gst_string_calchash((uint8_t *)str); + if (gst_string_hash(str) != hash) return 0; + for (i = 0; i < len; ++i) + if (str[1] != v.data.string[i]) return 0; + return 1; } /* 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); GstValue *start = obj->data; GstValue *end = obj->data + obj->count * 2; - while (start < end) { - if (start->type == GST_STRING) { - uint8_t *str = start->data.string; - if (gst_string_length(str) == len) { - if (!gst_string_hash(str)) - gst_string_hash(str) = gst_string_calchash(str); - if (gst_string_hash(str) == hash) { - return start - } - } - } - start += 2; - } - return NULL; + while (start < end) { + if (start->type == GST_STRING) { + uint8_t *str = start->data.string; + if (gst_string_length(str) == len) { + if (!gst_string_hash(str)) + gst_string_hash(str) = gst_string_calchash(str); + if (gst_string_hash(str) == hash) { + return start + } + } + } + start += 2; + } + return NULL; } /* Remove a key from a bag */ static void gst_object_bag_remove(GstDict *obj, GstValue key) { - GstValue *kv = gst_object_bag_find(obj, key); - if (kv != NULL) { - GstValue *lastKv = obj->data + --obj->count * 2; - kv[0] = lastKv[0]; - kv[1] = lastKv[1]; - } + GstValue *kv = gst_object_bag_find(obj, key); + if (kv != NULL) { + GstValue *lastKv = obj->data + --obj->count * 2; + kv[0] = lastKv[0]; + kv[1] = lastKv[1]; + } } /* Add a key to a bag */ static void gst_object_bag_put(Gst *vm, GstDict *obj, GstValue key, GstValue value) { - GstValue *kv = gst_object_bag_find(obj, key); - if (kv != NULL) { - /* Replace value */ - kv[1] = value; - } else { - /* Check for need to resize */ - if (obj->count + 1 > obj->capacity) { - uint32_t newCap = 2 * obj->count + 2; - GstValue *newData = gst_alloc(vm, sizeof(GstValue) * 2 * newCap); - gst_memcpy(newData, obj->data, obj->count * 2 * sizeof(GstValue)); - obj->data = newData; - obj->capacity = newCap; - } - /* Push to end */ - kv = obj->data + obj->count * 2; - kv[0] = key; - kv[1] = value; - ++obj->count; - } + GstValue *kv = gst_object_bag_find(obj, key); + if (kv != NULL) { + /* Replace value */ + kv[1] = value; + } else { + /* Check for need to resize */ + if (obj->count + 1 > obj->capacity) { + uint32_t newCap = 2 * obj->count + 2; + GstValue *newData = gst_alloc(vm, sizeof(GstValue) * 2 * newCap); + gst_memcpy(newData, obj->data, obj->count * 2 * sizeof(GstValue)); + obj->data = newData; + obj->capacity = newCap; + } + /* Push to end */ + kv = obj->data + obj->count * 2; + kv[0] = key; + kv[1] = value; + ++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. */ static void hash_putkv(GstValue *data, uint32_t cap, GstValue key, GstValue value) { - GstValue *end = data + 2 * cap; - GstValue *start = data + (gst_hash(key) % cap) * 2; - GstValue *bucket; - /* Check second half of array */ - for (bucket = start; bucket < end; bucket += 2) { - if (bucket[0].type == GST_NIL) { - bucket[0] = key; - bucket[1] = value; - return; - } - } - /* Check first half of array */ - for (bucket = data; bucket < start; bucket += 2) { - if (bucket[0].type == GST_NIL) { - bucket[0] = key; - bucket[1] = value; - return; - } - } - /* Should never reach here - data would be full */ + GstValue *end = data + 2 * cap; + GstValue *start = data + (gst_hash(key) % cap) * 2; + GstValue *bucket; + /* Check second half of array */ + for (bucket = start; bucket < end; bucket += 2) { + if (bucket[0].type == GST_NIL) { + bucket[0] = key; + bucket[1] = value; + return; + } + } + /* Check first half of array */ + for (bucket = data; bucket < start; bucket += 2) { + if (bucket[0].type == GST_NIL) { + bucket[0] = key; + bucket[1] = value; + return; + } + } + /* Should never reach here - data would be full */ } /* Find a bucket in the hastable */ static GstValue *hash_findkv(GstValue *data, uint32_t cap, GstValue key, GstValue **out) { - GstValue *end = data + 2 * cap; - GstValue *start = data + (gst_hash(key) % cap) * 2; - GstValue *bucket; - /* Check second half of array */ - for (bucket = start; bucket < end; bucket += 2) - if (bucket[0].type == GST_NIL) - if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ - continue; - else { - *out = bucket; - return NULL; - } - else if (gst_equals(bucket[0], key)) - return bucket; - /* Check first half of array */ - for (bucket = data; bucket < start; bucket += 2) - if (bucket[0].type == GST_NIL) - if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ - continue; - else { - *out = bucket; - return NULL; - } - else if (gst_equals(bucket[0], key)) - return bucket; - /* Should never reach here - data would be full */ - *out = bucket; - return NULL; + GstValue *end = data + 2 * cap; + GstValue *start = data + (gst_hash(key) % cap) * 2; + GstValue *bucket; + /* Check second half of array */ + for (bucket = start; bucket < end; bucket += 2) + if (bucket[0].type == GST_NIL) + if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ + continue; + else { + *out = bucket; + return NULL; + } + else if (gst_equals(bucket[0], key)) + return bucket; + /* Check first half of array */ + for (bucket = data; bucket < start; bucket += 2) + if (bucket[0].type == GST_NIL) + if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ + continue; + else { + *out = bucket; + return NULL; + } + else if (gst_equals(bucket[0], key)) + return bucket; + /* Should never reach here - data would be full */ + *out = bucket; + return NULL; } /* 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; fromBucket = obj->data; fromEnd = fromBucket + obj->count * 2; - for (; fromBucket < fromEnd; fromBucket += 2) { - if (fromBucket[0].type == GST_NIL) continue; - toStart = toData + (gst_hash(fromBucket[0]) % capacity) * 2; - /* Check second half of array */ - for (toBucket = toStart; toBucket < toEnd; toBucket += 2) { - if (toBucket[0].type == GST_NIL) { - toBucket[0] = fromBucket[0]; - toBucket[1] = fromBucket[1]; - goto finish_put; - } - } - /* Check first half of array */ - for (toBucket = toData; toBucket < toStart; toBucket += 2) { - if (toBucket[0].type == GST_NIL) { - toBucket[0] = fromBucket[0]; - toBucket[1] = fromBucket[1]; - goto finish_put; - } - } - /* Error if we got here - backing array to small. */ - ; - /* Continue. */ - finish_put: continue; - } - obj->capacity = capacity; - obj->data = toData; + for (; fromBucket < fromEnd; fromBucket += 2) { + if (fromBucket[0].type == GST_NIL) continue; + toStart = toData + (gst_hash(fromBucket[0]) % capacity) * 2; + /* Check second half of array */ + for (toBucket = toStart; toBucket < toEnd; toBucket += 2) { + if (toBucket[0].type == GST_NIL) { + toBucket[0] = fromBucket[0]; + toBucket[1] = fromBucket[1]; + goto finish_put; + } + } + /* Check first half of array */ + for (toBucket = toData; toBucket < toStart; toBucket += 2) { + if (toBucket[0].type == GST_NIL) { + toBucket[0] = fromBucket[0]; + toBucket[1] = fromBucket[1]; + goto finish_put; + } + } + /* Error if we got here - backing array to small. */ + ; + /* Continue. */ + finish_put: continue; + } + obj->capacity = capacity; + obj->data = toData; } /****/ @@ -202,16 +202,16 @@ GstDict *gst_dict(Gst *vm, uint32_t capacity) { GstValue gst_dict_get(GstDict *dict, GstValue key) { GstValue *bucket *notused; if (dict->flags & GST_OBJECT_FLAG_ISBAG) { - bucket = gst_object_bag_find(dict, key); + bucket = gst_object_bag_find(dict, key); } else { bucket = hash_findkv(obj->data, obj->capacity, key, ¬used); } if (bucket != NULL) { - return bucket[1]; + return bucket[1]; } else { GstValue ret; - ret.type = GST_NIL; - return ret; + ret.type = GST_NIL; + 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->count > GST_OBJECT_BAG_THRESHOLD) { /* Change to hashtable */ - obj->flags |= GST_OBJECT_FLAG_ISBAG; - gst_object_rehash(vm, obj, 4 * obj->count); - goto put_hash; + obj->flags |= GST_OBJECT_FLAG_ISBAG; + gst_object_rehash(vm, obj, 4 * obj->count); + goto put_hash; } - gst_object_bag_put(vm, obj, key, value); + gst_object_bag_put(vm, obj, key, value); } else { GstValue *bucket, *out; - put_hash: + put_hash: bucket = hash_findkv(obj->data, obj->capacity, key, &out); - if (bucket != NULL) { - bucket[1] = value; - } else { - /* Check for resize */ - if (obj->count + 1 > obj->capacity) { - gst_object_rehash(vm, obj, 2 * (obj->count + 1)); + if (bucket != NULL) { + bucket[1] = value; + } else { + /* Check for resize */ + if (obj->count + 1 > obj->capacity) { + gst_object_rehash(vm, obj, 2 * (obj->count + 1)); bucket = hash_findkv(obj->data, obj->capacity, key, &out); - } - out[0] = key; - out[1] = value; - ++obj->count; - } + } + out[0] = key; + out[1] = value; + ++obj->count; + } } } /* Remove item from dictionary */ void gst_dict_remove(GstDict *obj, GstValue key) { if (obj->flags & GST_OBJECT_FLAG_ISBAG) { - gst_object_bag_remove(obj, key); + gst_object_bag_remove(obj, key); } else { GstValue *bucket, *out; bucket = hash_findkv(obj->data, obj->capacity, key, &out); - if (bucket != NULL) { - --obj->count; - bucket[0].type = GST_NIL; - bucket[1].type = GST_BOOLEAN; - } + if (bucket != NULL) { + --obj->count; + bucket[0].type = GST_NIL; + bucket[1].type = GST_BOOLEAN; + } } } diff --git a/ds.c b/ds.c index ccdae058..37ae68a4 100644 --- a/ds.c +++ b/ds.c @@ -229,7 +229,7 @@ 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); + 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]; diff --git a/gc.c b/gc.c index 769ec831..3c6eeba5 100644 --- a/gc.c +++ b/gc.c @@ -45,11 +45,11 @@ static void gst_mark_funcdef(Gst *vm, GstFuncDef *def) { for (i = 0; i < count; ++i) { /* If the literal is a NIL type, it actually * contains a FuncDef */ - if (def->literals[i].type == GST_NIL) { - gst_mark_funcdef(vm, (GstFuncDef *) def->literals[i].data.pointer); - } else { + if (def->literals[i].type == GST_NIL) { + gst_mark_funcdef(vm, (GstFuncDef *) def->literals[i].data.pointer); + } else { 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->buckets)->color = vm->black; for (i = 0; i < x->data.object->capacity; ++i) { - bucket = x->data.object->buckets[i]; - while (bucket) { - gc_header(bucket)->color = vm->black; - gst_mark(vm, &bucket->key); - gst_mark(vm, &bucket->value); - bucket = bucket->next; - } + bucket = x->data.object->buckets[i]; + while (bucket) { + gc_header(bucket)->color = vm->black; + gst_mark(vm, &bucket->key); + gst_mark(vm, &bucket->value); + bucket = bucket->next; + } } if (x->data.object->meta != NULL) { GstValue temp; temp.type = GST_OBJECT; temp.data.object = x->data.object->meta; - gst_mark(vm, &temp); + gst_mark(vm, &temp); } } break; case GST_USERDATA: if (gc_header(x->data.string - sizeof(GstUserdataHeader))->color != vm->black) { - GstUserdataHeader *userHeader = (GstUserdataHeader *)x->data.string - 1; - gc_header(userHeader)->color = vm->black; - GstValue temp; - temp.type = GST_OBJECT; - temp.data.object = userHeader->meta; - gst_mark(vm, &temp); + GstUserdataHeader *userHeader = (GstUserdataHeader *)x->data.string - 1; + gc_header(userHeader)->color = vm->black; + GstValue temp; + temp.type = GST_OBJECT; + temp.data.object = userHeader->meta; + gst_mark(vm, &temp); } } } @@ -254,20 +254,20 @@ void gst_clear_memory(Gst *vm) { /* Header for managed memory blocks */ struct MMHeader { - struct MMHeader *next; - struct MMHeader *previous; + struct MMHeader *next; + struct MMHeader *previous; }; /* Initialize managed memory */ void gst_mm_init(GstManagedMemory *mm) { - *mm = NULL; + *mm = NULL; } /* Allocate some managed memory */ void *gst_mm_alloc(GstManagedMemory *mm, uint32_t size) { - struct MMHeader *mem = gst_raw_alloc(size + sizeof(struct MMHeader)); - if (mem == NULL) - return NULL; + struct MMHeader *mem = gst_raw_alloc(size + sizeof(struct MMHeader)); + if (mem == NULL) + return NULL; mem->next = *mm; mem->previous = NULL; *mm = mem; @@ -276,9 +276,9 @@ void *gst_mm_alloc(GstManagedMemory *mm, uint32_t size) { /* Intialize zeroed managed memory */ void *gst_mm_zalloc(GstManagedMemory *mm, uint32_t size) { - struct MMHeader *mem = gst_raw_calloc(1, size + sizeof(struct MMHeader)); - if (mem == NULL) - return NULL; + struct MMHeader *mem = gst_raw_calloc(1, size + sizeof(struct MMHeader)); + if (mem == NULL) + return NULL; mem->next = *mm; mem->previous = NULL; *mm = mem; @@ -287,32 +287,32 @@ void *gst_mm_zalloc(GstManagedMemory *mm, uint32_t size) { /* Free a memory block used in managed memory */ void gst_mm_free(GstManagedMemory *mm, void *block) { - struct MMHeader *mem = (struct MMHeader *)(((char *)block) - sizeof(struct MMHeader)); - if (mem->previous != NULL) { - mem->previous->next = mem->next; - } else { - *mm = mem->next; - } - gst_raw_free(mem); + struct MMHeader *mem = (struct MMHeader *)(((char *)block) - sizeof(struct MMHeader)); + if (mem->previous != NULL) { + mem->previous->next = mem->next; + } else { + *mm = mem->next; + } + gst_raw_free(mem); } /* Free all memory in managed memory */ void gst_mm_clear(GstManagedMemory *mm) { - struct MMHeader *block = (struct MMHeader *)(*mm); - struct MMHeader *next; - while (block != NULL) { - next = block->next; - free(block); - block = next; - }; - *mm = NULL; + struct MMHeader *block = (struct MMHeader *)(*mm); + struct MMHeader *next; + while (block != NULL) { + next = block->next; + free(block); + block = next; + }; + *mm = NULL; } /* Analog to realloc */ void *gst_mm_realloc(GstManagedMemory *mm, void *block, uint32_t nsize) { - struct MMHeader *mem = gst_raw_realloc(block, nsize + sizeof(struct MMHeader)); - if (mem == NULL) - return NULL; + struct MMHeader *mem = gst_raw_realloc(block, nsize + sizeof(struct MMHeader)); + if (mem == NULL) + return NULL; mem->next = *mm; mem->previous = NULL; *mm = mem; diff --git a/thread.c b/thread.c index d7261a94..c9f81586 100644 --- a/thread.c +++ b/thread.c @@ -7,80 +7,80 @@ /* Create a new thread */ GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) { GstThread *thread = gst_alloc(vm, sizeof(GstThread)); - GstValue *data, *stack; - if (capacity < GST_FRAME_SIZE) capacity = GST_FRAME_SIZE; - data = gst_alloc(vm, sizeof(GstValue) * capacity); - thread->capacity = capacity; - thread->count = GST_FRAME_SIZE; - thread->data = data; - thread->status = GST_THREAD_PENDING; - stack = data + GST_FRAME_SIZE; - gst_frame_size(stack) = 0; - gst_frame_prevsize(stack) = 0; - gst_frame_ret(stack) = 0; - gst_frame_errloc(stack) = 0; - gst_frame_pc(stack) = NULL; - gst_frame_env(stack) = NULL; - gst_frame_errjmp(stack) = NULL; + GstValue *data, *stack; + if (capacity < GST_FRAME_SIZE) capacity = GST_FRAME_SIZE; + data = gst_alloc(vm, sizeof(GstValue) * capacity); + thread->capacity = capacity; + thread->count = GST_FRAME_SIZE; + thread->data = data; + thread->status = GST_THREAD_PENDING; + stack = data + GST_FRAME_SIZE; + gst_frame_size(stack) = 0; + gst_frame_prevsize(stack) = 0; + gst_frame_ret(stack) = 0; + gst_frame_errloc(stack) = 0; + gst_frame_pc(stack) = NULL; + gst_frame_env(stack) = NULL; + gst_frame_errjmp(stack) = NULL; gst_thread_expand_callable(vm, thread, callee); - gst_thread_endframe(vm, thread); + gst_thread_endframe(vm, thread); return thread; } /* Ensure that the thread has enough EXTRA capacity */ void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra) { - GstValue *newData, *stack; - uint32_t usedCapacity, neededCapacity, newCapacity; - stack = thread->data + thread->count; - usedCapacity = thread->count + gst_frame_size(stack) + GST_FRAME_SIZE; - neededCapacity = usedCapacity + extra; - if (thread->capacity >= neededCapacity) return; - newCapacity = 2 * neededCapacity; - newData = gst_alloc(vm, sizeof(GstValue) * newCapacity); - gst_memcpy(newData, thread->data, sizeof(GstValue) * usedCapacity); - thread->data = newData; - thread->capacity = newCapacity; + GstValue *newData, *stack; + uint32_t usedCapacity, neededCapacity, newCapacity; + stack = thread->data + thread->count; + usedCapacity = thread->count + gst_frame_size(stack) + GST_FRAME_SIZE; + neededCapacity = usedCapacity + extra; + if (thread->capacity >= neededCapacity) return; + newCapacity = 2 * neededCapacity; + newData = gst_alloc(vm, sizeof(GstValue) * newCapacity); + gst_memcpy(newData, thread->data, sizeof(GstValue) * usedCapacity); + thread->data = newData; + thread->capacity = newCapacity; } /* Push a value on the current stack frame*/ void gst_thread_push(Gst *vm, GstThread *thread, GstValue x) { GstValue *stack; - gst_thread_ensure_extra(vm, thread, 1); - stack = thread->data + thread->count; - stack[gst_frame_size(stack)++] = x; + gst_thread_ensure_extra(vm, thread, 1); + stack = thread->data + thread->count; + stack[gst_frame_size(stack)++] = x; } /* Push n nils onto the stack */ void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n) { GstValue *stack, *current, *end; - gst_thread_ensure_extra(vm, thread, n); - stack = thread->data + thread->count; - current = stack + gst_frame_size(stack); - end = current + n; - for (; current < end; ++current) { - current->type = GST_NIL; - } - gst_frame_size(stack) += n; + gst_thread_ensure_extra(vm, thread, n); + stack = thread->data + thread->count; + current = stack + gst_frame_size(stack); + end = current + n; + for (; current < end; ++current) { + current->type = GST_NIL; + } + gst_frame_size(stack) += n; } /* Package up extra args after and including n into tuple at n*/ void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) { - GstValue *stack = thread->data + thread->count; - uint32_t size = gst_frame_size(stack); - if (n >= size) { - gst_thread_pushnil(vm, thread, n - size + 1); - stack = thread->data + thread->count; - stack[n].type = GST_TUPLE; - stack[n].data.tuple = gst_tuple(vm, 0); - } else { - uint32_t i; - GstValue *tuple = gst_tuple(vm, size - n); - for (i = n; i < size; ++i) - tuple[i - n] = stack[i]; - stack[n].type = GST_TUPLE; - stack[n].data.tuple = tuple; - gst_frame_size(stack) = n + 1; - } + GstValue *stack = thread->data + thread->count; + uint32_t size = gst_frame_size(stack); + if (n >= size) { + gst_thread_pushnil(vm, thread, n - size + 1); + stack = thread->data + thread->count; + stack[n].type = GST_TUPLE; + stack[n].data.tuple = gst_tuple(vm, 0); + } else { + uint32_t i; + GstValue *tuple = gst_tuple(vm, size - n); + for (i = n; i < size; ++i) + tuple[i - n] = stack[i]; + stack[n].type = GST_TUPLE; + stack[n].data.tuple = tuple; + gst_frame_size(stack) = n + 1; + } } /* 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; GstValue *oldStack, *newStack; - /* Push the frame */ - gst_thread_ensure_extra(vm, thread, GST_FRAME_SIZE + arity + 4); - oldStack = thread->data + thread->count; - frameOffset = gst_frame_size(oldStack) + GST_FRAME_SIZE; - newStack = oldStack + frameOffset; - gst_frame_prevsize(newStack) = gst_frame_size(oldStack); - gst_frame_env(newStack) = NULL; - gst_frame_errjmp(newStack) = NULL; - gst_frame_size(newStack) = 0; - thread->count += frameOffset; + /* Push the frame */ + gst_thread_ensure_extra(vm, thread, GST_FRAME_SIZE + arity + 4); + oldStack = thread->data + thread->count; + frameOffset = gst_frame_size(oldStack) + GST_FRAME_SIZE; + newStack = oldStack + frameOffset; + gst_frame_prevsize(newStack) = gst_frame_size(oldStack); + gst_frame_env(newStack) = NULL; + gst_frame_errjmp(newStack) = NULL; + gst_frame_size(newStack) = 0; + thread->count += frameOffset; /* Get real callable */ if (gst_thread_expand_callable(vm, thread, callee) == 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); - /* Return ok */ + /* Return ok */ return thread->data + thread->count; } /* After pushing arguments to a stack frame created with gst_thread_beginframe, call this * to finalize the frame before starting a function call. */ void gst_thread_endframe(Gst *vm, GstThread *thread) { - GstValue *stack = thread->data + thread->count; - GstValue callee = gst_frame_callee(stack); - if (callee.type == GST_FUNCTION) { - GstFunction *fn = callee.data.function; - gst_frame_pc(stack) = fn->def->byteCode; - if (fn->def->flags & GST_FUNCDEF_FLAG_VARARG) { - uint32_t arity = fn->def->arity; - gst_thread_tuplepack(vm, thread, arity); - } else { - uint32_t locals = fn->def->locals; - if (gst_frame_size(stack) < locals) { - gst_thread_pushnil(vm, thread, locals - gst_frame_size(stack)); - } - } - } + GstValue *stack = thread->data + thread->count; + GstValue callee = gst_frame_callee(stack); + if (callee.type == GST_FUNCTION) { + GstFunction *fn = callee.data.function; + gst_frame_pc(stack) = fn->def->byteCode; + if (fn->def->flags & GST_FUNCDEF_FLAG_VARARG) { + uint32_t arity = fn->def->arity; + gst_thread_tuplepack(vm, thread, arity); + } else { + uint32_t locals = fn->def->locals; + if (gst_frame_size(stack) < locals) { + gst_thread_pushnil(vm, thread, locals - gst_frame_size(stack)); + } + } + } } /* Pop a stack frame from the thread. Returns the new stack frame, or * NULL if there are no more frames */ GstValue *gst_thread_popframe(Gst *vm, GstThread *thread) { - GstValue *stack = thread->data + thread->count; - uint32_t prevsize = gst_frame_prevsize(stack); - GstValue *nextstack = stack - GST_FRAME_SIZE - prevsize; - GstFuncEnv *env = gst_frame_env(stack); + GstValue *stack = thread->data + thread->count; + uint32_t prevsize = gst_frame_prevsize(stack); + GstValue *nextstack = stack - GST_FRAME_SIZE - prevsize; + GstFuncEnv *env = gst_frame_env(stack); - /* Check for closures */ + /* Check for closures */ if (env != NULL) { uint32_t size = gst_frame_size(stack); env->thread = NULL; 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); } /* Shrink stack */ thread->count -= GST_FRAME_SIZE + prevsize; - /* Check if the stack is empty, and if so, return null */ - if (thread->count) + /* Check if the stack is empty, and if so, return null */ + if (thread->count) return nextstack; else return NULL; @@ -201,39 +201,39 @@ GstValue *gst_thread_popframe(Gst *vm, GstThread *thread) { * for primitive tail calls. */ GstValue *gst_thread_tail(Gst *vm, GstThread *thread) { GstFuncEnv *env; - GstValue *stack = thread->data + thread->count; - GstValue *nextStack = gst_thread_popframe(vm, thread); - uint32_t i; + GstValue *stack = thread->data + thread->count; + GstValue *nextStack = gst_thread_popframe(vm, thread); + uint32_t i; - if (nextStack == NULL) return NULL; - env = gst_frame_env(nextStack); + if (nextStack == NULL) return NULL; + env = gst_frame_env(nextStack); - /* Check for old closures */ + /* Check for old closures */ if (env != NULL) { uint32_t size = gst_frame_size(stack); env->thread = NULL; 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); } /* Modify new closure */ env = gst_frame_env(stack); if (env != NULL) { - env->stackOffset = thread->count; + env->stackOffset = thread->count; } - /* Copy over (some of) stack frame. Leave ret and prevsize untouched. */ - gst_frame_env(nextStack) = env; - gst_frame_size(nextStack) = gst_frame_size(stack); - gst_frame_pc(nextStack) = gst_frame_pc(stack); - gst_frame_errjmp(nextStack) = gst_frame_errjmp(stack); - gst_frame_errloc(nextStack) = gst_frame_errloc(stack); - gst_frame_callee(nextStack) = gst_frame_callee(stack); + /* Copy over (some of) stack frame. Leave ret and prevsize untouched. */ + gst_frame_env(nextStack) = env; + gst_frame_size(nextStack) = gst_frame_size(stack); + gst_frame_pc(nextStack) = gst_frame_pc(stack); + gst_frame_errjmp(nextStack) = gst_frame_errjmp(stack); + gst_frame_errloc(nextStack) = gst_frame_errloc(stack); + gst_frame_callee(nextStack) = gst_frame_callee(stack); - /* Copy stack arguments */ - for (i = 0; i < gst_frame_size(nextStack); ++i) - nextStack[i] = stack[i]; + /* Copy stack arguments */ + for (i = 0; i < gst_frame_size(nextStack); ++i) + nextStack[i] = stack[i]; - return nextStack; + return nextStack; } diff --git a/vm.c b/vm.c index 25775844..7412108f 100644 --- a/vm.c +++ b/vm.c @@ -349,7 +349,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { continue; case GST_OP_RET: /* Return */ - temp = stack[pc[1]]; + temp = stack[pc[1]]; stack = gst_thread_popframe(vm, &thread); if (thread.count < stackBase) { 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_TCL: /* Tail call */ - { - GstValue *oldStack; - temp = stack[pc[1]]; + { + GstValue *oldStack; + temp = stack[pc[1]]; int isTCall = *pc == GST_OP_TCL; - uint32_t i, arity, offset, size; - uint16_t ret = pc[2]; - offset = isTCall ? 3 : 4; - arity = pc[offset - 1]; - /* Push new frame */ - stack = gst_thread_beginframe(vm, &thread, temp, arity); - oldStack = stack - GST_FRAME_SIZE - gst_frame_prevsize(stack); - /* Write arguments */ - size = gst_frame_size(stack); - for (i = 0; i < arity; ++i) - stack[i + size - arity] = oldStack[pc[offset + i]]; - /* Finish new frame */ - gst_thread_endframe(vm, &thread); - /* Check tail call - if so, replace frame. */ - if (isTCall) { - stack = gst_thread_tail(vm, &thread); - } else { - gst_frame_ret(oldStack) = ret; - } - /* Call function */ - temp = gst_frame_callee(stack); - if (temp.type == GST_FUNCTION) { - /* Save pc and set new pc */ + uint32_t i, arity, offset, size; + uint16_t ret = pc[2]; + offset = isTCall ? 3 : 4; + arity = pc[offset - 1]; + /* Push new frame */ + stack = gst_thread_beginframe(vm, &thread, temp, arity); + oldStack = stack - GST_FRAME_SIZE - gst_frame_prevsize(stack); + /* Write arguments */ + size = gst_frame_size(stack); + for (i = 0; i < arity; ++i) + stack[i + size - arity] = oldStack[pc[offset + i]]; + /* Finish new frame */ + gst_thread_endframe(vm, &thread); + /* Check tail call - if so, replace frame. */ + if (isTCall) { + stack = gst_thread_tail(vm, &thread); + } else { + gst_frame_ret(oldStack) = ret; + } + /* Call function */ + temp = gst_frame_callee(stack); + if (temp.type == GST_FUNCTION) { + /* Save pc and set new pc */ if (!isTCall) gst_frame_pc(oldStack) = pc + offset + arity; - pc = temp.data.function->def->byteCode; - } else { - int status; - GST_STATE_WRITE(); - vm->ret.type = GST_NIL; - status = temp.data.cfunction(vm); - GST_STATE_SYNC(); - stack = gst_thread_popframe(vm, &thread); - if (status == GST_RETURN_OK) - if (thread.count < stackBase) { + pc = temp.data.function->def->byteCode; + } else { + int status; + GST_STATE_WRITE(); + vm->ret.type = GST_NIL; + status = temp.data.cfunction(vm); + GST_STATE_SYNC(); + stack = gst_thread_popframe(vm, &thread); + if (status == GST_RETURN_OK) + if (thread.count < stackBase) { GST_STATE_WRITE(); - return status; + return status; } else { - stack[gst_frame_ret(stack)] = vm->ret; + stack[gst_frame_ret(stack)] = vm->ret; if (isTCall) pc = gst_frame_pc(stack); else pc += offset + arity; } - else - goto vm_error; - } - } - break; + else + goto vm_error; + } + } + break; /* Handle errors from c functions and vm opcodes */ vm_error: @@ -453,11 +453,11 @@ int gst_run(Gst *vm, GstValue callee) { /* If callee was not actually a function, get the delegate function */ callee = gst_frame_callee(stack); if (callee.type == GST_CFUNCTION) { - int status; - vm->ret.type = GST_NIL; - status = callee.data.cfunction(vm); - gst_thread_popframe(vm, vm->thread); - return status; + int status; + vm->ret.type = GST_NIL; + status = callee.data.cfunction(vm); + gst_thread_popframe(vm, vm->thread); + return status; } else { 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); /* Call function */ - callee = gst_frame_callee(stack); - if (callee.type == GST_FUNCTION) { + callee = gst_frame_callee(stack); + if (callee.type == GST_FUNCTION) { gst_frame_pc(stack) = callee.data.function->def->byteCode; - status = gst_continue(vm); - } else { - vm->ret.type = GST_NIL; - status = callee.data.cfunction(vm); - gst_thread_popframe(vm, vm->thread); - } + status = gst_continue(vm); + } else { + vm->ret.type = GST_NIL; + status = callee.data.cfunction(vm); + gst_thread_popframe(vm, vm->thread); + } /* Pop the extra nil */ --gst_frame_size(gst_thread_stack(vm->thread));