mirror of
https://github.com/janet-lang/janet
synced 2024-11-24 17:27:18 +00:00
Retabbed things
This commit is contained in:
parent
9f09a19feb
commit
ba82ba414a
306
dict.c
306
dict.c
@ -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, ¬used);
|
bucket = hash_findkv(obj->data, obj->capacity, key, ¬used);
|
||||||
}
|
}
|
||||||
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
2
ds.c
@ -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
90
gc.c
@ -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
216
thread.c
@ -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
114
vm.c
@ -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));
|
||||||
|
Loading…
Reference in New Issue
Block a user