Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/6model/reprs/MVMCode.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 MVMCode_this_repr;
5
6
/* Invocation protocol handler. */
7
15.0M
static void invoke_handler(MVMThreadContext *tc, MVMObject *invokee, MVMCallsite *callsite, MVMRegister *args) {
8
15.0M
    if (IS_CONCRETE(invokee)) {
9
15.0M
        MVMCode *code = (MVMCode *)invokee;
10
15.0M
        MVM_frame_invoke(tc, code->body.sf, callsite, args,
11
15.0M
            code->body.outer, invokee, -1);
12
15.0M
    }
13
0
    else {
14
0
        MVM_exception_throw_adhoc(tc, "Cannot invoke code type object");
15
0
    }
16
15.0M
}
17
18
/* Creates a new type object of this representation, and associates it with
19
 * the given HOW. Also sets the invocation protocol handler in the STable. */
20
144
static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) {
21
144
    MVMSTable *st = MVM_gc_allocate_stable(tc, &MVMCode_this_repr, HOW);
22
144
23
144
    MVMROOT(tc, st, {
24
144
        MVMObject *obj = MVM_gc_allocate_type_object(tc, st);
25
144
        MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj);
26
144
        st->invoke = invoke_handler;
27
144
        st->size = sizeof(MVMCode);
28
144
    });
29
144
30
144
    return st->WHAT;
31
144
}
32
33
/* Copies the body of one object to another. */
34
27.3k
static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) {
35
27.3k
    MVMCodeBody *src_body  = (MVMCodeBody *)src;
36
27.3k
    MVMCodeBody *dest_body = (MVMCodeBody *)dest;
37
27.3k
    MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->sf, src_body->sf);
38
27.3k
    if (src_body->outer) {
39
2.96k
        MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->outer, src_body->outer);
40
2.96k
    }
41
27.3k
    MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->name, src_body->name);
42
27.3k
    /* Explicitly do *not* copy state vars in a (presumably closure) clone. */
43
27.3k
}
44
45
/* Adds held objects to the GC worklist. */
46
215k
static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) {
47
215k
    MVMCodeBody *body = (MVMCodeBody *)data;
48
215k
    MVM_gc_worklist_add(tc, worklist, &body->outer);
49
215k
    MVM_gc_worklist_add(tc, worklist, &body->code_object);
50
215k
    MVM_gc_worklist_add(tc, worklist, &body->sf);
51
215k
    MVM_gc_worklist_add(tc, worklist, &body->name);
52
215k
    if (body->state_vars) {
53
0
        MVMuint8 *flags  = body->sf->body.static_env_flags;
54
0
        MVMuint16 *types = body->sf->body.lexical_types;
55
0
        MVMint64 numlex  = body->sf->body.num_lexicals;
56
0
        MVMint64 i;
57
0
        for (i = 0; i < numlex; i++) {
58
0
            if (flags[i] == 2) {
59
0
                if (types[i] == MVM_reg_obj)
60
0
                    MVM_gc_worklist_add(tc, worklist, &body->state_vars[i].o);
61
0
                else if (types[i] == MVM_reg_str)
62
0
                    MVM_gc_worklist_add(tc, worklist, &body->state_vars[i].s);
63
0
            }
64
0
        }
65
0
    }
66
215k
}
67
68
/* Called by the VM in order to free memory associated with this object. */
69
204k
static void gc_free(MVMThreadContext *tc, MVMObject *obj) {
70
204k
    MVMCode *code_obj = (MVMCode *)obj;
71
204k
    MVM_free(code_obj->body.state_vars);
72
204k
}
73
74
static const MVMStorageSpec storage_spec = {
75
    MVM_STORAGE_SPEC_REFERENCE, /* inlineable */
76
    0,                          /* bits */
77
    0,                          /* align */
78
    MVM_STORAGE_SPEC_BP_NONE,   /* boxed_primitive */
79
    0,                          /* can_box */
80
    0,                          /* is_unsigned */
81
};
82
83
84
/* Gets the storage specification for this representation. */
85
0
static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) {
86
0
    return &storage_spec;
87
0
}
88
89
/* Compose the representation. */
90
0
static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info) {
91
0
    /* Nothing to do for this REPR. */
92
0
}
93
94
/* Initializes the representation. */
95
144
const MVMREPROps * MVMCode_initialize(MVMThreadContext *tc) {
96
144
    return &MVMCode_this_repr;
97
144
}
98
99
static const MVMREPROps MVMCode_this_repr = {
100
    type_object_for,
101
    MVM_gc_allocate_object,
102
    NULL, /* initialize */
103
    copy_to,
104
    MVM_REPR_DEFAULT_ATTR_FUNCS,
105
    MVM_REPR_DEFAULT_BOX_FUNCS,
106
    MVM_REPR_DEFAULT_POS_FUNCS,
107
    MVM_REPR_DEFAULT_ASS_FUNCS,
108
    MVM_REPR_DEFAULT_ELEMS,
109
    get_storage_spec,
110
    NULL, /* change_type */
111
    NULL, /* serialize */
112
    NULL, /* deserialize */
113
    NULL, /* serialize_repr_data */
114
    NULL, /* deserialize_repr_data */
115
    NULL, /* deserialize_stable_size */
116
    gc_mark,
117
    gc_free,
118
    NULL, /* gc_cleanup */
119
    NULL, /* gc_mark_repr_data */
120
    NULL, /* gc_free_repr_data */
121
    compose,
122
    NULL, /* spesh */
123
    "MVMCode", /* name */
124
    MVM_REPR_ID_MVMCode,
125
    NULL, /* unmanaged_size */
126
    NULL, /* describe_refs */
127
};
128
129
0
MVM_PUBLIC MVMObject * MVM_code_location(MVMThreadContext *tc, MVMObject *code) {
130
0
    MVMObject *BOOTHash = tc->instance->boot_types.BOOTHash;
131
0
    MVMObject *result = REPR(BOOTHash)->allocate(tc, STABLE(BOOTHash));
132
0
    MVMString *file;
133
0
    MVMint32   line;
134
0
    MVMObject *filename_boxed;
135
0
    MVMObject *linenumber_boxed;
136
0
    MVMString *filename_key, *linenumber_key;
137
0
138
0
    MVM_code_location_out(tc, code, &file, &line);
139
0
140
0
    MVM_gc_root_temp_push(tc, (MVMCollectable **)&file);
141
0
    MVM_gc_root_temp_push(tc, (MVMCollectable **)&result);
142
0
143
0
    filename_key = MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "file");
144
0
    MVM_gc_root_temp_push(tc, (MVMCollectable **)&filename_key);
145
0
146
0
    linenumber_key = MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "line");
147
0
    MVM_gc_root_temp_push(tc, (MVMCollectable **)&linenumber_key);
148
0
149
0
    filename_boxed = MVM_repr_box_str(tc, tc->instance->boot_types.BOOTStr, file);
150
0
    MVM_repr_bind_key_o(tc, result, filename_key, filename_boxed);
151
0
152
0
    linenumber_boxed = MVM_repr_box_int(tc, tc->instance->boot_types.BOOTInt, line);
153
0
    MVM_repr_bind_key_o(tc, result, linenumber_key, linenumber_boxed);
154
0
155
0
    MVM_gc_root_temp_pop_n(tc, 4);
156
0
157
0
    return result;
158
0
}
159
160
void MVM_code_location_out(MVMThreadContext *tc, MVMObject *code,
161
0
                           MVMString **file_out, MVMint32 *line_out) {
162
0
    if (REPR(code)->ID != MVM_REPR_ID_MVMCode) {
163
0
        MVM_exception_throw_adhoc(tc, "getcodelocation needs an object of MVMCode REPR, got %s instead", REPR(code)->name);
164
0
    } else {
165
0
        MVMCodeBody          *body = &((MVMCode*)code)->body;
166
0
        MVMBytecodeAnnotation *ann = MVM_bytecode_resolve_annotation(tc, &body->sf->body, 0);
167
0
        MVMCompUnit            *cu = body->sf->body.cu;
168
0
        MVMint32           str_idx = ann ? ann->filename_string_heap_index : 0;
169
0
170
0
        *line_out = ann ? ann->line_number : 1;
171
0
        if (ann && str_idx < cu->body.num_strings) {
172
0
            *file_out = MVM_cu_string(tc, cu, str_idx);
173
0
        } else {
174
0
            *file_out = cu->body.filename;
175
0
        }
176
0
        MVM_free(ann);
177
0
    }
178
0
}