From: Jérémie Astor Date: Thu, 16 Sep 2021 13:08:52 +0000 (+0200) Subject: :art: Improve Object X-Git-Tag: nightly~443 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=c251d62671968063d5ccc4ed85b14409dc99d887;p=gwion.git :art: Improve Object --- diff --git a/include/env/type.h b/include/env/type.h index 6a68f189..168d55e8 100644 --- a/include/env/type.h +++ b/include/env/type.h @@ -37,6 +37,7 @@ enum tflag { tflag_noret = 1 << 18, tflag_contract = 1 << 19, tflag_float = 1 << 20, + tflag_union = 1 << 21, } __attribute__((packed)); struct Type_ { diff --git a/include/env/value.h b/include/env/value.h index aa498b6d..92000963 100644 --- a/include/env/value.h +++ b/include/env/value.h @@ -18,7 +18,8 @@ enum vflag { vflag_builtin = 1 << 5, vflag_member = 1 << 6, vflag_closed = 1 << 7, - vflag_inner = 1 << 8 // value is in a scope + vflag_inner = 1 << 8, // value is in a scope + vflag_release = 1 << 9 // vflag_used = 1 << 3 } __attribute__((packed)); diff --git a/include/object.h b/include/object.h index af933b4a..54745c56 100644 --- a/include/object.h +++ b/include/object.h @@ -2,10 +2,11 @@ #define __OBJECT typedef struct M_Object_ *M_Object; struct M_Object_ { - m_bit * data; - Type type_ref; - struct Vector_ vtable; - volatile size_t ref; + Type type_ref; + struct Vector_ vtable; + /*volatile */uint32_t ref; + uint32_t offset; + m_bit data[]; }; ANN void instantiate_object(const VM_Shred, const Type); @@ -60,7 +61,7 @@ static inline void struct_addref(const Gwion gwion, const Type type, } } -static inline void compound_release(const VM_Shred shred, const Type t, +ANN static inline void compound_release(const VM_Shred shred, const Type t, const m_bit *ptr) { if (!tflag(t, tflag_struct)) object_release(shred, t, ptr); diff --git a/src/env/value.c b/src/env/value.c index a82e2661..e64a5cbf 100644 --- a/src/env/value.c +++ b/src/env/value.c @@ -7,12 +7,16 @@ #define MAX(a, b) (a >= b ? a : b) ANN void free_value(Value a, Gwion gwion) { const Type t = a->type; +// if(t) { + if (t->size > SZ_INT && !vflag(a, vflag_func) && a->d.ptr) _mp_free(gwion->mp, t->size, a->d.ptr); else if (is_class(gwion, t)) type_remref(t, gwion); - /* else */if (vflag(a, vflag_inner)) + else if (vflag(a, vflag_inner)) type_remref(t, gwion); +// } + mp_free(gwion->mp, ValueFrom, a->from); mp_free(gwion->mp, Value, a); } diff --git a/src/lib/array.c b/src/lib/array.c index fa41f106..aa8f32ee 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -957,7 +957,7 @@ INSTR(ArrayAlloc) { return; // TODO make exception vararg } *(void **)(ref->data + SZ_INT) = aai.data; -// vector_add(&shred->gc, (m_uint)ref); // heyo + vector_add(&shred->gc, (m_uint)ref); // heyo if (!info->is_obj) { POP_REG(shred, SZ_INT * (info->depth - 1)); *(M_Object *)REG(-SZ_INT) = ref; diff --git a/src/lib/object.c b/src/lib/object.c index 2880c96f..bd340374 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -21,14 +21,12 @@ #undef insert_symbol M_Object new_object(MemPool p, const VM_Shred shred, const Type t) { - const M_Object a = mp_calloc(p, M_Object); + const uint32_t offset = sizeof(struct M_Object_) + t->nspc->offset; + const M_Object a = _mp_calloc(p, offset); a->ref = 1; a->type_ref = t; - if (t->nspc) { - a->vtable.ptr = t->nspc->vtable.ptr; - if (t->nspc->offset) - a->data = (m_bit *)_mp_calloc(p, t->nspc->offset); - } + a->offset = t->nspc->offset; + a->vtable.ptr = t->nspc->vtable.ptr; if (shred) vector_add(&shred->gc, (vtype)a); return a; } @@ -47,7 +45,8 @@ M_Object new_string2(const struct Gwion_ *gwion, const VM_Shred shred, return o; } -ANN static void handle_dtor(const M_Object o, const VM_Shred shred) { +ANN static void user_dtor(const M_Object o, const VM_Shred shred, const Type t) { + o->type_ref = t; const VM_Shred sh = new_vm_shred(shred->info->mp, o->type_ref->nspc->dtor); vmcode_addref(o->type_ref->nspc->dtor); sh->base = shred->base; @@ -56,39 +55,47 @@ ANN static void handle_dtor(const M_Object o, const VM_Shred shred) { ++sh->info->me->ref; } -__attribute__((hot)) ANN void __release(const M_Object o, - const VM_Shred shred) { - vector_rem2(&shred->gc, (vtype)o); - MemPool p = shred->info->mp; - Type t = o->type_ref; - do { - if (!t->nspc) continue; - if (isa(t, shred->info->vm->gwion->type[et_union]) < 0) { - struct scope_iter iter = {t->nspc->info->value, 0, 0}; - Value v; - while (scope_iter(&iter, &v) > 0) { - if (!GET_FLAG(v, static) && - isa(v->type, shred->info->vm->gwion->type[et_compound]) > 0) - compound_release(shred, v->type, o->data + v->from->offset); - } - } - if (tflag(t, tflag_dtor)) { - if (t->nspc->dtor->builtin) - ((f_xtor)t->nspc->dtor->native_func)(o, NULL, shred); - else { - o->type_ref = t; - handle_dtor(o, shred); - return; - } - } - } while ((t = t->info->parent)); - free_object(p, o); +static DTOR(object_dtor) { + free_object(shred->info->mp, o); +} + +ANN static inline Type next_type(Type t) { + do if(t->nspc) return t; + while((t = t->info->parent)); + return NULL; +} + +ANN static inline void release_not_union(const m_bit *data, const VM_Shred shred, const Scope s) { + const Map m = &s->map; + for(m_uint i = map_size(m) + 1; --i;) { + const Value v = (Value) VVAL(m, i-1); + if (vflag(v, vflag_release)) + compound_release(shred, v->type, data + v->from->offset); + } +} + +ANN static void do_release(const M_Object o, + const VM_Shred shred, const Type t) { + const Type next = next_type(t); + if(!next) return; + if (!tflag(t, tflag_union)) + release_not_union(o->data, shred, t->nspc->info->value); + if (tflag(t, tflag_dtor)) { + if (t->nspc->dtor->builtin) + ((f_xtor)t->nspc->dtor->native_func)(o, NULL, shred); + else + return user_dtor(o, shred, t); + } + return do_release(o, shred, t->info->parent); +} + +ANN void __release(const M_Object o, const VM_Shred shred) { +// vector_rem2(&shred->gc, (vtype)o); + do_release(o, shred, o->type_ref); } ANN void free_object(MemPool p, const M_Object o) { - if (o->type_ref->nspc && o->type_ref->nspc->offset) - mp_free2(p, o->type_ref->nspc->offset, o->data); - mp_free(p, M_Object, o); + mp_free2(p, o->offset, o); } static ID_CHECK(opck_this) { @@ -119,6 +126,10 @@ static ID_EMIT(opem_this) { GWION_IMPORT(object) { const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, "@Compound"); gwi_set_global_type(gwi, t_object, et_object); + t_object->nspc = new_nspc(gwi->gwion->mp, "Object"); + t_object->nspc->dtor = new_vmcode(gwi->gwion->mp, NULL, NULL, "Object", SZ_INT, true, false); + t_object->nspc->dtor->native_func = (m_uint)object_dtor; + t_object->tflag |= tflag_dtor; struct SpecialId_ spid = {.ck = opck_this, .em = opem_this, .is_const = 1}; gwi_specialid(gwi, "this", &spid); return GW_OK; diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 4e2a1b30..f0d39370 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -229,7 +229,6 @@ OP_EMIT(opem_object_dot) { const Exp_Dot *member = (Exp_Dot *)data; const Type t_base = actual_type(emit->gwion, member->base->type); const Value value = find_value(t_base, member->xid); - if (is_class(emit->gwion, value->type)) { const Instr instr = emit_add_instr(emit, RegPushImm); instr->m_val = (m_uint)value->type; diff --git a/src/main.c b/src/main.c index d3a59b0f..225f6254 100644 --- a/src/main.c +++ b/src/main.c @@ -21,7 +21,8 @@ static void sig(int unused NUSED) { static void afl_run(const Gwion gwion) { __AFL_INIT(); - while (__AFL_LOOP(128)) { +// while (__AFL_LOOP(128)) { + while (__AFL_LOOP(32)) { push_global(gwion, "[afl]"); FILE *f = fdopen(0, "r"); if (compile_file(gwion, "afl", f)) gwion_run(gwion); diff --git a/src/parse/check.c b/src/parse/check.c index f6757c51..07836089 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -163,13 +163,18 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl *decl) { } if (!decl->type) ERR_O(decl->td->pos, _("can't find type")); { - CHECK_BO(inferable(env, decl->type, decl->td->pos)); CHECK_BO(ensure_check(env, decl->type)); + if(inferable(env, decl->type, decl->td->pos) < 0) { + if(!tflag(decl->type, tflag_check) && decl->type->ref > 1 && env->class_def && !env->scope->depth) + type_remref(decl->type, env->gwion); + return NULL; + } } const m_bool global = GET_FLAG(decl->td, global); const m_uint scope = !global ? env->scope->depth : env_push_global(env); const m_bool ret = check_decl(env, decl); if (global) env_pop(env, scope); + env_weight(env, 1 + isa(decl->type, env->gwion->type[et_object]) > 0); return ret > 0 ? decl->list->self->value->type : NULL; } @@ -209,6 +214,7 @@ ANN static Type check_prim_array(const Env env, const Array_Sub *data) { if (!e) ERR_O(prim_pos(data), _("must provide values/expressions for array [...]")) CHECK_OO(check_exp(env, e)); + env_weight(env, 1); return array->type = prim_array_match(env, e); } @@ -225,6 +231,7 @@ ANN static m_bool check_range(const Env env, Range *range) { ANN static Type check_prim_range(const Env env, Range **data) { Range *range = *data; CHECK_BO(check_range(env, range)); + env_weight(env, 1); const Exp e = range->start ?: range->end; assert(e); const Symbol sym = insert_symbol("@range"); @@ -288,6 +295,7 @@ ANN static Type check_dot(const Env env, const Exp_Dot *member) { .lhs = member->base->type, .data = (uintptr_t)member, .pos = exp_self(member)->pos}; + env_weight(env, 1); return op_check(env, &opi); } @@ -367,17 +375,20 @@ ANN static Type check_prim_id(const Env env, const Symbol *data) { ANN static Type check_prim_perform(const Env env, const Symbol *data) { env_add_effect(env, *data, prim_pos(data)); + env_weight(env, 1); return env->gwion->type[et_void]; } ANN static Type check_prim_interp(const Env env, const Exp *exp) { CHECK_OO(check_exp(env, *exp)); + env_weight(env, 1); return env->gwion->type[et_string]; } ANN static Type check_prim_hack(const Env env, const Exp *data) { if (env->func) unset_fflag(env->func, fflag_pure); CHECK_OO(check_prim_interp(env, data)); + env_weight(env, 1); return env->gwion->type[et_gack]; } /* @@ -452,6 +463,7 @@ static ANN Type check_exp_array(const Env env, const Exp_Array *array) { static ANN Type check_exp_slice(const Env env, const Exp_Slice *range) { CHECK_OO(check_exp(env, range->base)); CHECK_BO(check_range(env, range->range)); + env_weight(env, 1); const Symbol sym = insert_symbol("@slice"); const Exp e = range->range->start ?: range->range->end; assert(e); @@ -1801,6 +1813,78 @@ ANN static inline bool type_is_recurs(const Type t, const Type tgt) { return isa(tgt, t) > 0 || isa(t, tgt) > 0 || (tgt->info->tuple && vector_find(&tgt->info->tuple->contains, (m_uint)t) > -1); } +ANN static m_bool recursive_type_base(const Env env, const Type t); +ANN static bool recursive_type(const Env env, const Type t, const Type tgt); +ANN static bool recursive_value(const Env env, const Type t, const Value v) { +//if(!v->from->owner_class)exit(13); + const Type tgt = array_base(v->type); + if(type_is_recurs(t, tgt)) { + env_err(env, v->from->loc, _("recursive type")); + env->context->error = false; + gwerr_secondary("in class", t->name, t->info->cdef->base.pos); + + const Type first = tgt->info->value->from->loc.first.line < t->info->value->from->loc.first.line ? +// tgt : t; + v->type : t; + const Type second = tgt->info->value->from->loc.first.line > t->info->value->from->loc.first.line ? +// tgt : t; + v->type : t; + +printf("%s %s\n", first->name, second->name); + + if(first != second) { + const Map m1 = &first->info->value->from->owner->info->type->map; + map_remove(m1, (m_uint)insert_symbol(first->name)); + const Map m2 = &second->info->value->from->owner->info->type->map; + map_remove(m2, (m_uint)insert_symbol(second->name)); + if(first->ref > 2) + type_remref(first, env->gwion); + if(second->ref > 2) + type_remref(second, env->gwion); + if(tgt != t && v->type == tgt && strncmp(tgt->name, "Option:[", 8)) + recursive_type_base(env, tgt); + } + set_tflag(t, tflag_infer); + set_tflag(tgt, tflag_infer); + unset_tflag(t, tflag_check); + unset_tflag(tgt, tflag_check); + return true; + } + if(v->type->nspc && !GET_FLAG(v, late) && + isa(tgt, env->gwion->type[et_compound]) > 0) + return recursive_type(env, t, tgt); + return false; +} + +ANN static bool recursive_type(const Env env, const Type t, const Type tgt) { + Value v; + struct scope_iter inner = {tgt->nspc->info->value, 0, 0}; + bool error = false; + while (scope_iter(&inner, &v) > 0) { + if(!GET_FLAG(v, late) && recursive_value(env, t, v)) { + error = true; + } + } + return error; +} + +ANN static m_bool recursive_type_base(const Env env, const Type t) { + Value value; + bool error = false; + struct scope_iter iter = {t->nspc->info->value, 0, 0}; + while (scope_iter(&iter, &value) > 0) { + if (isa(value->type, env->gwion->type[et_compound]) < 0) continue; + if (value->type->nspc && !GET_FLAG(value, late)) { + if(recursive_type(env, t, value->type)) { + env_err(env, value->from->loc, _("recursive type")); + gw_err("use {+G}late{0} on one (or more) of the variables?\n"); + error = true; + } + } + } + return error; +} + ANN bool check_trait_requests(const Env env, const Type t, const ID_List list); ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) { const Type t = cdef->base.type; @@ -1826,48 +1910,7 @@ ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) { return GW_ERROR; } } - - Value value; - struct scope_iter iter = {t->nspc->info->value, 0, 0}; - while (scope_iter(&iter, &value) > 0) { - if (isa(value->type, env->gwion->type[et_compound]) < 0) continue; -// const Type t = array_base(value->type); - if (value->type->nspc && !GET_FLAG(value, late)) { - Value v; - struct scope_iter inner = {value->type->nspc->info->value, 0, 0}; -bool error = false; - while (scope_iter(&inner, &v) > 0) { - const Type tgt = array_base(v->type); -// if(isa(tgt, t) > 0 || isa(t, tgt) > 0 || (tgt->info->tuple && vector_find(&tgt->info->tuple->contains, (m_uint)t) > -1)) { - if(type_is_recurs(t, tgt)) { - env_err(env, v->from->loc, _("recursive type")); - env->context->error = false; - env_err(env, value->from->loc, _("recursive type")); - gw_err("use {+G}late{0} on one (or more) of the variables?\n"); -// env_set_error(env); -vector_rem2(&t->info->tuple->contains, (m_uint)tgt); -vector_rem2(&tgt->info->tuple->contains, (m_uint)t); -type_remref(t, env->gwion); -//type_remref(tgt, env->gwion); -//nspc_add_type_front(t->nspc, insert_symbol(tgt->name), tgt); -//nspc_add_type_front(tgt->nspc, insert_symbol(tgt->name), t); - set_tflag(t, tflag_infer); - set_tflag(tgt, tflag_infer); - unset_tflag(t, tflag_check); - unset_tflag(tgt, tflag_check); -//value->type = env->gwion->type[et_error]; -//v->type = env->gwion->type[et_error]; -//env->gwion->type[et_error]->ref += 2; - -error = true; -// return GW_OK; - } - } -if(error) -// return GW_OK; - return GW_ERROR; - } - } + CHECK_BB(recursive_type_base(env, t)); nspc_allocdata(env->gwion->mp, t->nspc); return GW_OK; } diff --git a/src/parse/scan0.c b/src/parse/scan0.c index c25764c9..fb9ec57d 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -235,6 +235,7 @@ ANN static Type union_type(const Env env, const Symbol s, const loc_t loc) { t->nspc = new_nspc(env->gwion->mp, name); t->nspc->parent = env->curr; t->info->tuple = new_tupleform(env->gwion->mp, NULL); // ??? + set_tflag(t, tflag_union); add_type(env, env->curr, t); mk_class(env, t, loc); SET_FLAG(t, final); @@ -380,7 +381,7 @@ ANN static Exp arglist2exp(MemPool p, Arg_List arg, const Exp default_arg) { } ANN2(1,2) static Ast scan0_func_def_default(const MemPool p, const Ast ast, - const Ast next) { + const Ast next) { const Func_Def base_fdef = ast->section->d.func_def; Arg_List base_arg = base_fdef->base->args, former = NULL; while (base_arg) { @@ -505,14 +506,14 @@ ANN m_bool scan0_class_def(const Env env, const Class_Def c) { } ANN m_bool scan0_ast(const Env env, Ast ast) { + Ast next; do { + next = ast->next; CHECK_BB(scan0_section(env, ast->section)); if (ast->section->section_type != ae_section_func || !fdef_defaults(ast->section->d.func_def)) continue; - const Ast next = ast->next; - scan0_func_def_default(env->gwion->mp, ast, next); - if(!(ast = next))break; - } while ((ast = ast->next)); + (void)scan0_func_def_default(env->gwion->mp, ast, ast->next); + } while ((ast = next)); return GW_OK; } diff --git a/src/parse/scan1.c b/src/parse/scan1.c index be0f4dfa..4637ede9 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -128,6 +128,8 @@ ANN static m_bool scan1_decl(const Env env, const Exp_Decl *decl) { if (env->class_def->info->tuple) tuple_contains(env, v); if (!GET_FLAG(decl->td, static)) { set_vflag(v, vflag_member); + if(isa(t, env->gwion->type[et_object]) > 0) + set_vflag(v, vflag_release); if (tflag(env->class_def, tflag_struct)) { v->from->offset = env->class_def->size; env->class_def->size += t->size; @@ -508,9 +510,10 @@ ANN static inline m_bool scan1_union_def_inner_loop(const Env env, if (nspc_lookup_value0(env->curr, l->xid)) ERR_B(l->pos, _("'%s' already declared in union"), s_name(l->xid)) const Value v = new_value(env->gwion->mp, t, s_name(l->xid)); - if (!tflag(t, tflag_scan1)) // ??? +// if (!tflag(t, tflag_scan1)) // ??? tuple_contains(env, v); // ??? - v->from->offset = SZ_INT; +// v->from->offset = SZ_INT; + v->from->offset = v->type->size; valuefrom(env, v->from, udef->pos); nspc_add_value_front(env->curr, l->xid, v); if (t->size > sz) sz = t->size; diff --git a/tests/plug/enum.c b/tests/plug/enum.c index 898eec8a..cac4005b 100644 --- a/tests/plug/enum.c +++ b/tests/plug/enum.c @@ -22,20 +22,6 @@ GWION_IMPORT(enum_test) { GWI_BB(gwi_enum_add(gwi, "TYPED_ENUM9", 9)) GWI_OB(gwi_enum_end(gwi)) - GWI_OB(gwi_class_ini(gwi, "Enum", NULL)) - GWI_BB(gwi_enum_ini(gwi, "MyTest")) - GWI_BB(gwi_enum_add(gwi, "ENUM0", 0)) - GWI_BB(gwi_enum_add(gwi, "ENUM1", 1)) - GWI_BB(gwi_enum_add(gwi, "ENUM2", 2)) - GWI_BB(gwi_enum_add(gwi, "ENUM3", 3)) - GWI_BB(gwi_enum_add(gwi, "ENUM4", 4)) - GWI_BB(gwi_enum_add(gwi, "ENUM5", 5)) - GWI_BB(gwi_enum_add(gwi, "ENUM6", 6)) - GWI_BB(gwi_enum_add(gwi, "ENUM7", 7)) - GWI_BB(gwi_enum_add(gwi, "ENUM8", 8)) - GWI_BB(gwi_enum_add(gwi, "ENUM9", 9)) - GWI_OB(gwi_enum_end(gwi)) - GWI_OB(gwi_class_end(gwi)) return GW_OK; diff --git a/tests/plug/enum_fail3.c b/tests/plug/enum_fail3.c index a64d7199..73453467 100644 --- a/tests/plug/enum_fail3.c +++ b/tests/plug/enum_fail3.c @@ -9,7 +9,7 @@ #include "import.h" GWION_IMPORT(enum_test) { - GWI_BB(gwi_enum_ini(gwi, NULL)) + GWI_BB(gwi_enum_ini(gwi, "test")) GWI_BB(gwi_enum_add(gwi, "adc", 0)) GWI_BB(gwi_enum_ini(gwi, NULL)) return GW_OK;