GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/lib/object.c Lines: 84 85 98.8 %
Date: 2020-08-07 19:15:19 Branches: 51 54 94.4 %

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
36
ANN void exception(const VM_Shred shred, const m_str c) {
23
108
  gw_err("%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]\n",
24
108
          c, shred->tick->xid, shred->info->name, shred->pc - 1);
25
36
  vm_shred_exit(shred);
26
36
}
27
28
8942
M_Object new_object(MemPool p, const VM_Shred shred, const Type t) {
29
8942
  const M_Object a = mp_calloc(p, M_Object);
30
8942
  a->ref = 1;
31
8942
  a->type_ref = t;
32
8942
  if(t->nspc) {
33
7306
    a->vtable = &t->nspc->info->vtable;
34
7306
    if(t->nspc->info->offset)
35
7257
      a->data = (m_bit*)_mp_calloc(p, t->nspc->info->offset);
36
  }
37
8942
  if(shred)
38
1854
    vector_add(&shred->gc, (vtype)a);
39
8942
  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
240
M_Object new_string2(const struct Gwion_ *gwion, const VM_Shred shred, const m_str str) {
49
240
  const M_Object o = new_object(gwion->mp, shred, gwion->type[et_string]);
50
240
  STRING(o) = str;
51
240
  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
7938
ANN void __release(const M_Object o, const VM_Shred shred) {
65
7938
  MemPool p = shred->info->mp;
66
7938
  Type t = o->type_ref;
67
  do {
68
22729
    if(GET_FLAG(t, nonnull))
69
9
      t = t->e->parent;
70
22729
    if(!t->nspc)
71
15862
      continue;
72
6867
    struct scope_iter iter = { t->nspc->info->value, 0, 0 };\
73
    Value v;
74
81602
    while(scope_iter(&iter, &v) > 0) {
75

134720
      if(!GET_FLAG(v, static) && !GET_FLAG(v, pure) &&
76
66852
          isa(v->type, shred->info->vm->gwion->type[et_object]) > 0)
77
23
        release(*(M_Object*)(o->data + v->from->offset), shred);
78

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

6867
    if(GET_FLAG(t, dtor) && t->nspc->dtor) {
90
6160
      if(GET_FLAG(t->nspc->dtor, builtin))
91
6153
        ((f_xtor)t->nspc->dtor->native_func)(o, NULL, shred);
92
      else {
93
7
        o->type_ref = t;
94
7
        handle_dtor(o, shred);
95
7
        return;
96
      }
97
    }
98
22722
  } while((t = t->e->parent));
99
7931
  free_object(p, o);
100
}
101
102
7939
ANN void free_object(MemPool p, const M_Object o) {
103

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

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

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

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