Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/6model/reprs/MVMStaticFrame.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* This representation's function pointer table. */
4
static const MVMREPROps MVMStaticFrame_this_repr;
5
6
/* Creates a new type object of this representation, and associates it with
7
 * the given HOW. Also sets the invocation protocol handler in the STable. */
8
144
static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) {
9
144
    MVMSTable *st = MVM_gc_allocate_stable(tc, &MVMStaticFrame_this_repr, HOW);
10
144
11
144
    MVMROOT(tc, st, {
12
144
        MVMObject *obj = MVM_gc_allocate_type_object(tc, st);
13
144
        MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj);
14
144
        st->size = sizeof(MVMStaticFrame);
15
144
    });
16
144
17
144
    return st->WHAT;
18
144
}
19
20
/* Copies the body of one object to another. */
21
1.53k
static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) {
22
1.53k
    MVMStaticFrameBody *src_body  = (MVMStaticFrameBody *)src;
23
1.53k
    MVMStaticFrameBody *dest_body = (MVMStaticFrameBody *)dest;
24
1.53k
25
1.53k
    if (!src_body->fully_deserialized)
26
0
        MVM_exception_throw_adhoc(tc, "Can only clone a fully deserialized MVMFrame");
27
1.53k
28
1.53k
    dest_body->orig_bytecode = src_body->orig_bytecode;
29
1.53k
    dest_body->bytecode_size = src_body->bytecode_size;
30
1.53k
    if (src_body->bytecode == src_body->orig_bytecode) {
31
1.53k
        /* Easy - the source MVMStaticFrameBody doesn't own the memory. */
32
1.53k
        dest_body->bytecode = src_body->bytecode;
33
1.53k
    }
34
0
    else {
35
0
        /* We're going to need to make a copy, in case the source object gets
36
0
           GC'd before we do, and so they free memory we point to. */
37
0
        /* If this gets to be a resource hog, then implement something more
38
0
           sophisticated. The easiest thing would be to bump the allocated size
39
0
           and value stored in bytecode by sizeof(MVMuint64), and use the extra
40
0
           space to store a reference count. */
41
0
        dest_body->bytecode = MVM_malloc(src_body->bytecode_size);
42
0
        memcpy(dest_body->bytecode, src_body->bytecode, src_body->bytecode_size);
43
0
    }
44
1.53k
45
1.53k
    MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->cu, src_body->cu);
46
1.53k
    MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->cuuid, src_body->cuuid);
47
1.53k
    MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->name, src_body->name);
48
1.53k
    MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->static_code, src_body->static_code);
49
1.53k
50
1.53k
    dest_body->num_locals = src_body->num_locals;
51
1.53k
    dest_body->num_lexicals = src_body->num_lexicals;
52
1.53k
    {
53
1.53k
        MVMuint16 *local_types = MVM_malloc(sizeof(MVMuint16) * src_body->num_locals);
54
1.53k
        MVMuint16 *lexical_types = MVM_malloc(sizeof(MVMuint16) * src_body->num_lexicals);
55
1.53k
        memcpy(local_types, src_body->local_types, sizeof(MVMuint16) * src_body->num_locals);
56
1.53k
        if (src_body->num_lexicals)
57
0
            memcpy(lexical_types, src_body->lexical_types,
58
0
                sizeof(MVMuint16) * src_body->num_lexicals);
59
1.53k
        dest_body->local_types = local_types;
60
1.53k
        dest_body->lexical_types = lexical_types;
61
1.53k
    }
62
1.53k
    {
63
1.53k
        MVMLexicalRegistry *current, *tmp;
64
1.53k
        unsigned bucket_tmp;
65
1.53k
66
1.53k
        /* NOTE: if we really wanted to, we could avoid rehashing... */
67
1.53k
        HASH_ITER(hash_handle, src_body->lexical_names, current, tmp, bucket_tmp) {
68
0
            MVMLexicalRegistry *new_entry = MVM_malloc(sizeof(MVMLexicalRegistry));
69
0
            /* don't need to clone the string */
70
0
            MVM_ASSIGN_REF(tc, &(dest_root->header), new_entry->key, current->key);
71
0
            new_entry->value = current->value;
72
0
            MVM_HASH_BIND(tc, dest_body->lexical_names, current->key, new_entry);
73
0
        }
74
1.53k
    }
75
1.53k
76
1.53k
    /* Static environment needs to be copied, and any objects WB'd. */
77
1.53k
    if (src_body->env_size) {
78
0
        MVMuint16 *type_map = src_body->lexical_types;
79
0
        MVMuint16  count    = src_body->num_lexicals;
80
0
        MVMuint16  i;
81
0
82
0
        dest_body->static_env = MVM_malloc(src_body->env_size);
83
0
        memcpy(dest_body->static_env, src_body->static_env, src_body->env_size);
84
0
        dest_body->static_env_flags = MVM_malloc(src_body->num_lexicals);
85
0
        memcpy(dest_body->static_env_flags, src_body->static_env_flags, src_body->num_lexicals);
86
0
87
0
        for (i = 0; i < count; i++) {
88
0
            if (type_map[i] == MVM_reg_str) {
89
0
                MVM_gc_write_barrier(tc, (MVMCollectable *)dest_root, (MVMCollectable *)dest_body->static_env[i].s);
90
0
            }
91
0
            else if (type_map[i] == MVM_reg_obj) {
92
0
                MVM_gc_write_barrier(tc, (MVMCollectable *)dest_root, (MVMCollectable *)dest_body->static_env[i].o);
93
0
            }
94
0
        }
95
0
    }
96
1.53k
    dest_body->env_size = src_body->env_size;
97
1.53k
    dest_body->work_size = src_body->work_size;
98
1.53k
99
1.53k
    if (src_body->outer)
100
1.53k
        MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->outer, src_body->outer);
101
1.53k
102
1.53k
    dest_body->num_handlers = src_body->num_handlers;
103
1.53k
    dest_body->handlers     = MVM_malloc(src_body->num_handlers * sizeof(MVMFrameHandler));
104
1.53k
    if (src_body->num_handlers)
105
425
        memcpy(dest_body->handlers, src_body->handlers,
106
425
            src_body->num_handlers * sizeof(MVMFrameHandler));
107
1.53k
    dest_body->instrumentation_level = 0;
108
1.53k
    dest_body->num_annotations       = src_body->num_annotations;
109
1.53k
    dest_body->annotations_data      = src_body->annotations_data;
110
1.53k
    dest_body->fully_deserialized    = 1;
111
1.53k
}
112
113
/* Adds held objects to the GC worklist. */
114
3.62k
static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) {
115
3.62k
    MVMStaticFrameBody *body = (MVMStaticFrameBody *)data;
116
3.62k
    MVMLexicalRegistry *current, *tmp;
117
3.62k
    unsigned bucket_tmp;
118
3.62k
119
3.62k
    /* mvmobjects */
120
3.62k
    MVM_gc_worklist_add(tc, worklist, &body->cu);
121
3.62k
    MVM_gc_worklist_add(tc, worklist, &body->cuuid);
122
3.62k
    MVM_gc_worklist_add(tc, worklist, &body->name);
123
3.62k
    MVM_gc_worklist_add(tc, worklist, &body->outer);
124
3.62k
    MVM_gc_worklist_add(tc, worklist, &body->static_code);
125
3.62k
126
3.62k
    /* If it's not fully deserialized, none of the following can apply. */
127
3.62k
    if (!body->fully_deserialized)
128
0
        return;
129
3.62k
130
3.62k
    /* lexical names hash keys */
131
3.62k
    HASH_ITER(hash_handle, body->lexical_names, current, tmp, bucket_tmp) {
132
0
        MVM_gc_worklist_add(tc, worklist, &current->hash_handle.key);
133
0
        MVM_gc_worklist_add(tc, worklist, &current->key);
134
0
    }
135
3.62k
136
3.62k
    /* static env */
137
3.62k
    if (body->static_env) {
138
0
        MVMuint16 *type_map = body->lexical_types;
139
0
        MVMuint16  count    = body->num_lexicals;
140
0
        MVMuint16  i;
141
0
        for (i = 0; i < count; i++)
142
0
            if (type_map[i] == MVM_reg_str || type_map[i] == MVM_reg_obj)
143
0
                MVM_gc_worklist_add(tc, worklist, &body->static_env[i].o);
144
0
    }
145
3.62k
146
3.62k
    /* Spesh. */
147
3.62k
    MVM_gc_worklist_add(tc, worklist, &body->spesh);
148
3.62k
}
149
150
/* Called by the VM in order to free memory associated with this object. */
151
0
static void gc_free(MVMThreadContext *tc, MVMObject *obj) {
152
0
    MVMStaticFrame *sf = (MVMStaticFrame *)obj;
153
0
    MVMStaticFrameBody *body = &sf->body;
154
0
    if (body->orig_bytecode != body->bytecode) {
155
0
        MVM_free(body->bytecode);
156
0
        body->bytecode = body->orig_bytecode;
157
0
    }
158
0
159
0
160
0
    /* If it's not fully deserialized, none of the following can apply. */
161
0
    if (!body->fully_deserialized)
162
0
        return;
163
0
    MVM_free(body->handlers);
164
0
    MVM_free(body->work_initial);
165
0
    MVM_free(body->static_env);
166
0
    MVM_free(body->static_env_flags);
167
0
    MVM_free(body->local_types);
168
0
    MVM_free(body->lexical_types);
169
0
    MVM_free(body->lexical_names_list);
170
0
    MVM_HASH_DESTROY(tc, hash_handle, MVMLexicalRegistry, body->lexical_names);
171
0
}
172
173
static const MVMStorageSpec storage_spec = {
174
    MVM_STORAGE_SPEC_REFERENCE, /* inlineable */
175
    0,                          /* bits */
176
    0,                          /* align */
177
    MVM_STORAGE_SPEC_BP_NONE,   /* boxed_primitive */
178
    0,                          /* can_box */
179
    0,                          /* is_unsigned */
180
};
181
182
183
/* Gets the storage specification for this representation. */
184
0
static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) {
185
0
    /* XXX in the end we'll support inlining of this... */
186
0
    return &storage_spec;
187
0
}
188
189
/* Compose the representation. */
190
0
static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info) {
191
0
    /* Nothing to do for this REPR. */
192
0
}
193
194
/* Calculates the non-GC-managed memory we hold on to. */
195
1.17k
static MVMuint64 unmanaged_size(MVMThreadContext *tc, MVMSTable *st, void *data) {
196
1.17k
    MVMStaticFrameBody *body = (MVMStaticFrameBody *)data;
197
1.17k
    MVMuint64 size = 0;
198
1.17k
199
1.17k
    if (body->fully_deserialized) {
200
1.17k
        size += sizeof(MVMuint16) * body->num_locals;
201
1.17k
        size += sizeof(MVMuint16) * body->num_lexicals;
202
1.17k
203
1.17k
        if (body->bytecode != body->orig_bytecode)
204
0
            size += body->bytecode_size;
205
1.17k
206
1.17k
        size += sizeof(MVMLexicalRegistry *) * body->num_lexicals;
207
1.17k
208
1.17k
        size += sizeof(MVMLexicalRegistry) * HASH_CNT(hash_handle, body->lexical_names);
209
1.17k
210
1.17k
        size += sizeof(MVMFrameHandler) * body->num_handlers;
211
1.17k
212
1.17k
        /* XXX i *think* the annotations are just a pointer into the serialized
213
1.17k
         * blob, so don't actually count it towards the unmanaged size. */
214
1.17k
        /*
215
1.17k
        size += sizeof(MVMuint8) * body->num_annotations
216
1.17k
        */
217
1.17k
        size += body->env_size; /* static_env */
218
1.17k
        size += body->num_lexicals; /* static_env_flags */
219
1.17k
220
1.17k
        if (body->instrumentation) {
221
0
            size += body->instrumentation->uninstrumented_bytecode_size;
222
0
            size += body->instrumentation->instrumented_bytecode_size;
223
0
224
0
            /* XXX not 100% sure if num_handlers from the body is also the
225
0
             * number of handlers in instrumented version. should be, though. */
226
0
            size += sizeof(MVMFrameHandler) * body->num_handlers * 2;
227
0
        }
228
1.17k
    }
229
1.17k
230
1.17k
    return size;
231
1.17k
}
232
233
0
static void describe_refs(MVMThreadContext *tc, MVMHeapSnapshotState *ss, MVMSTable *st, void *data) {
234
0
    MVMStaticFrameBody *body = (MVMStaticFrameBody *)data;
235
0
    MVMLexicalRegistry *current, *tmp;
236
0
    unsigned bucket_tmp;
237
0
238
0
    MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss,
239
0
        (MVMCollectable *)body->cu, "Compilation Unit");
240
0
    MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss,
241
0
        (MVMCollectable *)body->cuuid, "Compilation Unit Unique ID");
242
0
    MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss,
243
0
        (MVMCollectable *)body->name, "Name");
244
0
    MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss,
245
0
        (MVMCollectable *)body->outer, "Outer static frame");
246
0
    MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss,
247
0
        (MVMCollectable *)body->static_code, "Static code object");
248
0
249
0
    /* If it's not fully deserialized, none of the following can apply. */
250
0
    if (!body->fully_deserialized)
251
0
        return;
252
0
253
0
    /* lexical names hash keys */
254
0
    HASH_ITER(hash_handle, body->lexical_names, current, tmp, bucket_tmp) {
255
0
        MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss,
256
0
            (MVMCollectable *)current->key, "Lexical name");
257
0
    }
258
0
259
0
    /* static env */
260
0
    if (body->static_env) {
261
0
        MVMuint16 *type_map = body->lexical_types;
262
0
        MVMuint16  count    = body->num_lexicals;
263
0
        MVMuint16  i;
264
0
        for (i = 0; i < count; i++)
265
0
            if (type_map[i] == MVM_reg_str || type_map[i] == MVM_reg_obj)
266
0
                MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss,
267
0
                    (MVMCollectable *)body->static_env[i].o, "Static Environment Entry");
268
0
    }
269
0
270
0
    /* Spesh data */
271
0
    MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss,
272
0
        (MVMCollectable *)body->spesh, "Specializer Data");
273
0
}
274
275
/* Initializes the representation. */
276
144
const MVMREPROps * MVMStaticFrame_initialize(MVMThreadContext *tc) {
277
144
    return &MVMStaticFrame_this_repr;
278
144
}
279
280
static const MVMREPROps MVMStaticFrame_this_repr = {
281
    type_object_for,
282
    MVM_gc_allocate_object,
283
    NULL, /* initialize */
284
    copy_to,
285
    MVM_REPR_DEFAULT_ATTR_FUNCS,
286
    MVM_REPR_DEFAULT_BOX_FUNCS,
287
    MVM_REPR_DEFAULT_POS_FUNCS,
288
    MVM_REPR_DEFAULT_ASS_FUNCS,
289
    MVM_REPR_DEFAULT_ELEMS,
290
    get_storage_spec,
291
    NULL, /* change_type */
292
    NULL, /* serialize */
293
    NULL, /* deserialize */
294
    NULL, /* serialize_repr_data */
295
    NULL, /* deserialize_repr_data */
296
    NULL, /* deserialize_stable_size */
297
    gc_mark,
298
    gc_free,
299
    NULL, /* gc_cleanup */
300
    NULL, /* gc_mark_repr_data */
301
    NULL, /* gc_free_repr_data */
302
    compose,
303
    NULL, /* spesh */
304
    "MVMStaticFrame", /* name */
305
    MVM_REPR_ID_MVMStaticFrame,
306
    unmanaged_size, /* unmanaged_size */
307
    describe_refs,
308
};