GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/lib/object.c Lines: 82 83 98.8 %
Date: 2020-09-14 00:22:58 Branches: 53 56 94.6 %

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#include "gwion_util.h"
4
#include "gwion_ast.h"
5
#include "gwion_env.h"
6
#include "vm.h"
7
#include "gwion.h"
8
#include "instr.h"
9
#include "object.h"
10
#include "operator.h"
11
#include "import.h"
12
#include "emit.h"
13
#include "traverse.h"
14
#include "template.h"
15
#include "parse.h"
16
#include "specialid.h"
17
18
#include "gwi.h"
19
#include "gack.h"
20
21
#undef insert_symbol
22
37
ANN void exception(const VM_Shred shred, const m_str c) {
23
111
  gw_err("%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]\n",
24
111
          c, shred->tick->xid, shred->info->name, shred->pc - 1);
25
37
  vm_shred_exit(shred);
26
37
}
27
28
8813
M_Object new_object(MemPool p, const VM_Shred shred, const Type t) {
29
8813
  const M_Object a = mp_calloc(p, M_Object);
30
8813
  a->ref = 1;
31
8813
  a->type_ref = t;
32
8813
  if(t->nspc) {
33
7176
    a->vtable = &t->nspc->info->vtable;
34
7176
    if(t->nspc->info->offset)
35
7125
      a->data = (m_bit*)_mp_calloc(p, t->nspc->info->offset);
36
  }
37
8813
  if(shred)
38
1877
    vector_add(&shred->gc, (vtype)a);
39
8813
  return a;
40
}
41
42
29
M_Object new_string(MemPool p, const VM_Shred shred, const m_str str) {
43
29
  const M_Object o = new_object(p, shred, shred->info->vm->gwion->type[et_string]);
44
29
  STRING(o) = s_name(insert_symbol(shred->info->vm->gwion->st, str));
45
29
  return o;
46
}
47
48
243
M_Object new_string2(const struct Gwion_ *gwion, const VM_Shred shred, const m_str str) {
49
243
  const M_Object o = new_object(gwion->mp, shred, gwion->type[et_string]);
50
243
  STRING(o) = str;
51
243
  return o;
52
}
53
54
7
ANN static void handle_dtor(const M_Object o, const VM_Shred shred) {
55
7
  const VM_Shred sh = new_vm_shred(shred->info->mp, o->type_ref->nspc->dtor);
56
7
  ADD_REF(o->type_ref->nspc->dtor);
57
7
  sh->base = shred->base;
58
7
  *(M_Object*)sh->mem = o;
59
7
  vm_add_shred(shred->info->vm, sh);
60
7
  ++sh->info->me->ref;
61
7
}
62
63
__attribute__((hot))
64
7828
ANN void __release(const M_Object o, const VM_Shred shred) {
65
7828
  MemPool p = shred->info->mp;
66
7828
  Type t = o->type_ref;
67
  do {
68

22403
    if(!t->nspc || is_special(t))
69
15651
      continue;
70
6752
    struct scope_iter iter = { t->nspc->info->value, 0, 0 };\
71
    Value v;
72
80730
    while(scope_iter(&iter, &v) > 0) {
73

133414
      if(!GET_FLAG(v, static) && !GET_FLAG(v, pure) &&
74
66188
          isa(v->type, shred->info->vm->gwion->type[et_object]) > 0)
75
24
        release(*(M_Object*)(o->data + v->from->offset), shred);
76

67205
      else if(GET_FLAG(v->type, struct) &&
77

5
            !GET_FLAG(v, static) && !GET_FLAG(v, pure) && v->type->e->tuple) {
78
1
        const TupleForm tf = v->type->e->tuple;
79
5
        for(m_uint i = 0; i < vector_size(&tf->types); ++i) {
80
4
          const m_bit *data = o->data + v->from->offset;
81
4
          const Type t = (Type)vector_at(&tf->types, i);
82
4
          if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
83
1
            release(*(M_Object*)(data + vector_at(&tf->offset, i)), shred);
84
        }
85
      }
86
    }
87

6752
    if(GET_FLAG(t, dtor) && t->nspc->dtor) {
88
6045
      if(GET_FLAG(t->nspc->dtor, builtin))
89
6038
        ((f_xtor)t->nspc->dtor->native_func)(o, NULL, shred);
90
      else {
91
7
        o->type_ref = t;
92
7
        handle_dtor(o, shred);
93
7
        return;
94
      }
95
    }
96
22396
  } while((t = t->e->parent));
97
7821
  free_object(p, o);
98
}
99
100
7828
ANN void free_object(MemPool p, const M_Object o) {
101

7828
  if(o->type_ref->nspc && o->type_ref->nspc->info->offset)
102
6144
    mp_free2(p, o->type_ref->nspc->info->offset, o->data);
103
7828
  mp_free(p, M_Object, o);
104
7828
}
105
106
60
static ID_CHECK(opck_this) {
107
60
  if(!env->class_def)
108
1
    ERR_O(exp_self(prim)->pos, _("keyword 'this' can be used only inside class definition..."))
109

59
  if(env->func && !GET_FLAG(env->func, member))
110
1
      ERR_O(exp_self(prim)->pos, _("keyword 'this' cannot be used inside static functions..."))
111

58
  if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack"))
112
    return force_type(env, get_gack(env->class_def->e->parent)); // get_gack ?
113
58
  return env->class_def;
114
}
115
116
160
static ID_EMIT(opem_this) {
117

160
  if(!exp_getvar(exp_self(prim)) && GET_FLAG(exp_self(prim)->info->type, struct)) {
118
1
    const Instr instr = emit_add_instr(emit, RegPushMemDeref);
119
1
    instr->m_val2 = emit->env->class_def->size;
120
1
    return (Instr)GW_OK;
121
  }
122
159
  return emit_add_instr(emit, RegPushMem);
123
}
124
125
711
GWION_IMPORT(object) {
126
711
  const Type t_object  = gwi_mk_type(gwi, "Object", SZ_INT, "@Compound");
127
711
  gwi_set_global_type(gwi, t_object, et_object);
128
711
  struct SpecialId_ spid = { .ck=opck_this, .em=opem_this, .is_const=1 };
129
711
  gwi_specialid(gwi, "this", &spid);
130
711
  return GW_OK;
131
}