diff --git a/lang/boolean.c b/lang/boolean.c index b031635..8d6a2ab 100644 --- a/lang/boolean.c +++ b/lang/boolean.c @@ -15,7 +15,6 @@ Object boolean_create(VmState state, bool value) { Object obj = object_create(state, &boolean_class, sizeof(struct boolean)); - vm_abort_if(state, !obj, "unable to allocate boolean"); struct boolean *boolean = (struct boolean *)object_priv(state, obj, &boolean_class); boolean->value = value; diff --git a/lang/bytecode.c b/lang/bytecode.c index 1df1c22..748c53c 100644 --- a/lang/bytecode.c +++ b/lang/bytecode.c @@ -31,8 +31,8 @@ OP_GET_ARG = 0x0F, }; -void bytecode_run(VmState state, Object obj, const unsigned char *bytecode, - struct object_list *args) { +void bytecode_run( + VmState state, Object obj, const unsigned char *bytecode, Object args) { const unsigned char *pos_code = &bytecode[0]; unsigned char op = OP_END; while ((op = *pos_code++) != OP_END) { diff --git a/lang/bytecode.h b/lang/bytecode.h index 4ea1b60..bba4371 100644 --- a/lang/bytecode.h +++ b/lang/bytecode.h @@ -10,7 +10,7 @@ // Runs bytecode // obj is used for OP_SELF // args is used for OP_GET_ARG -void bytecode_run(VmState state, Object obj, const unsigned char *bytecode, - struct object_list *args); +void bytecode_run( + VmState state, Object obj, const unsigned char *bytecode, Object args); #endif diff --git a/lang/compile.py b/lang/compile.py index e96e472..d00a82d 100755 --- a/lang/compile.py +++ b/lang/compile.py @@ -953,16 +953,16 @@ def generate_class_boilerplate(): return """static struct object_class CLASSNAME_class; -static Object CLASSNAME_create(VmState state, ObjectList use_modules) { - Object obj = object_create(state, &CLASSNAME_class, sizeof(ObjectList)); - ObjectList *args = (ObjectList *)object_priv(state, obj, &CLASSNAME_class); +static Object CLASSNAME_create(VmState state, Object use_modules) { + Object obj = object_create(state, &CLASSNAME_class, sizeof(Object)); + Object *args = (Object *)object_priv(state, obj, &CLASSNAME_class); *args = use_modules; return obj; } static void CLASSNAME_cleanup(VmState state, Object obj) { - ObjectList *args = (ObjectList *)object_priv(state, obj, &CLASSNAME_class); - object_list_drop(state, args); + Object *args = (Object *)object_priv(state, obj, &CLASSNAME_class); + object_drop(state, args); }""" def generate_class_call(class_name, func_name, index): @@ -982,7 +982,7 @@ }; static void CLASSNAME_call_bytecode(VmState state, Object obj, int priv) { - struct object_list **args = (struct object_list **)object_priv(state, obj, &CLASSNAME_class); + Object *args = (Object*)object_priv(state, obj, &CLASSNAME_class); const unsigned char *bytecode = CLASSNAME_bytecodes[priv]; bytecode_run(state, obj, bytecode, *args); } diff --git a/lang/module.c b/lang/module.c index c293597..c1c5db7 100644 --- a/lang/module.c +++ b/lang/module.c @@ -130,7 +130,7 @@ int use_count = 0; for (const char **use = info->uses; *use != NULL; ++use) ++use_count; - ObjectList use_modules = object_list_create(state, use_count); + Object use_modules = object_list_create(state, use_count); int use_modules_next = 0; for (const char **use = info->uses; *use != NULL; ++use) { const ModuleInfo *use_info = info_by_name(*use); diff --git a/lang/module.h b/lang/module.h index 46cff97..59841e5 100644 --- a/lang/module.h +++ b/lang/module.h @@ -24,7 +24,7 @@ struct module_info { const char *name; const char **uses; - Object (*create)(VmState state, struct object_list *use_modules); + Object (*create)(VmState state, Object use_modules); }; typedef struct module_info ModuleInfo; diff --git a/lang/object.c b/lang/object.c index 948903a..9508bbf 100644 --- a/lang/object.c +++ b/lang/object.c @@ -74,62 +74,62 @@ vm_abort_msg(state, "dispatch_call: no call found to dispatch"); } +static struct object_class object_list_class; + struct object_list { int length; - atomic_int ref_count; Object elems[]; }; -ObjectList object_list_create(VmState state, int length) { +Object object_list_create(VmState state, int length) { size_t elem_size = sizeof(Object) * length; size_t size = sizeof(struct object_list) + elem_size; - ObjectList list = calloc(size, 1); - vm_abort_if( - state, list == NULL, "object_list_create: not enough memory"); + Object obj = object_create(state, &object_list_class, size); + struct object_list *list = (struct object_list *)object_priv( + state, obj, &object_list_class); list->length = length; - list->ref_count = 1; for (int i = 0; i < length; ++i) list->elems[i] = object_none(); - return list; + return obj; } -int object_list_length(VmState state, ObjectList list) { - (void)state; +int object_list_length(VmState state, Object obj) { + struct object_list *list = (struct object_list *)object_priv( + state, obj, &object_list_class); return list->length; } -void object_list_set(VmState state, ObjectList list, int index, Object obj) { +void object_list_set(VmState state, Object obj, int index, Object new) { + struct object_list *list = (struct object_list *)object_priv( + state, obj, &object_list_class); vm_abort_if(state, index < 0, "object_list_get: index too small"); vm_abort_if(state, index >= list->length, "object_list_get: index too large"); object_drop(state, &(list->elems[index])); - list->elems[index] = obj; + list->elems[index] = new; } -Object object_list_get(VmState state, ObjectList list, int index) { +Object object_list_get(VmState state, Object obj, int index) { + struct object_list *list = (struct object_list *)object_priv( + state, obj, &object_list_class); vm_abort_if(state, index < 0, "object_list_get: index too small"); vm_abort_if(state, index >= list->length, "object_list_get: index too large"); - Object obj = list->elems[index]; - object_hold(state, obj); - return obj; + Object new = list->elems[index]; + object_hold(state, new); + return new; } -void object_list_hold(VmState state, ObjectList list) { - (void)state; - atomic_fetch_add_explicit(&list->ref_count, 1, memory_order_relaxed); +static void object_list_cleanup(VmState state, Object obj) { + struct object_list *list = (struct object_list *)object_priv( + state, obj, &object_list_class); + for (int i = 0; i < list->length; ++i) + object_drop(state, &(list->elems[i])); } -void object_list_drop(VmState state, ObjectList *listptr) { - (void)state; - ObjectList list = (ObjectList)*listptr; - atomic_int count = atomic_fetch_sub_explicit( - &list->ref_count, 1, memory_order_relaxed); - if (count == 1) { - // We were the last user of the list, clean it up - for (int i = 0; i < list->length; ++i) - object_drop(state, &(list->elems[i])); - free(list); - } - *listptr = NULL; -} +static struct object_call object_list_calls[] = {{.name = NULL, /* end */}}; + +static struct object_class object_list_class = { + .cleanup = object_list_cleanup, + .calls = &object_list_calls[0], +}; diff --git a/lang/object.h b/lang/object.h index 6b5c4e0..0aee1a4 100644 --- a/lang/object.h +++ b/lang/object.h @@ -41,24 +41,17 @@ // Creates a list of objects with a specific length // All objects are initialized to object_none -ObjectList object_list_create(VmState state, int length); +Object object_list_create(VmState state, int length); // Gets the length of an object list -int object_list_length(VmState state, ObjectList list); +int object_list_length(VmState state, Object list); // Sets an element in the object list // The object's reference is taken from the caller -void object_list_set(VmState state, ObjectList list, int index, Object obj); +void object_list_set(VmState state, Object list, int index, Object obj); // Gets an element from the object list // A new reference is created for the caller -Object object_list_get(VmState state, ObjectList list, int index); - -// Adds a reference to an object list -void object_list_hold(VmState state, ObjectList list); - -// Drops a reference to an object list, possibly cleaning its contents -// Sets listptr to NULL -void object_list_drop(VmState state, ObjectList *listptr); +Object object_list_get(VmState state, Object list, int index); #endif diff --git a/lang/types.h b/lang/types.h index 2835e7d..3e316a0 100644 --- a/lang/types.h +++ b/lang/types.h @@ -8,10 +8,6 @@ struct object; typedef struct object *Object; -// Opaque type for an object list -struct object_list; -typedef struct object_list *ObjectList; - // Opaque type for the VM state struct vm_state; typedef struct vm_state *VmState; diff --git a/lang/vm.c b/lang/vm.c index a9e9c07..45156ce 100644 --- a/lang/vm.c +++ b/lang/vm.c @@ -12,7 +12,7 @@ #include struct vm_state { - ObjectList stack; + Object stack; int stack_base; int stack_next; Object tail_obj; @@ -34,7 +34,7 @@ } void vm_destroy(VmState *state) { - object_list_drop(*state, &(*state)->stack); + object_drop(*state, &(*state)->stack); free((*state)->stack_trace); free(*state); }