Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/core/ext.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
0
int MVM_ext_load(MVMThreadContext *tc, MVMString *lib, MVMString *ext) {
4
0
    MVMString *colon, *prefix, *name;
5
0
    MVMExtRegistry *entry;
6
0
    MVMDLLSym *sym;
7
0
    void (*init)(MVMThreadContext *);
8
0
9
0
    MVMROOT2(tc, lib, ext, {
10
0
        colon = MVM_string_ascii_decode_nt(
11
0
            tc, tc->instance->VMString, ":");
12
0
        prefix = MVM_string_concatenate(tc, lib, colon);
13
0
        name = MVM_string_concatenate(tc, prefix, ext);
14
0
    });
15
0
16
0
    uv_mutex_lock(&tc->instance->mutex_ext_registry);
17
0
18
0
    MVM_HASH_GET(tc, tc->instance->ext_registry, name, entry);
19
0
20
0
    /* Extension already loaded. */
21
0
    if (entry) {
22
0
        uv_mutex_unlock(&tc->instance->mutex_ext_registry);
23
0
        return 0;
24
0
    }
25
0
26
0
    MVMROOT(tc, name, {
27
0
        sym = (MVMDLLSym *)MVM_dll_find_symbol(tc, lib, ext);
28
0
    });
29
0
    if (!sym) {
30
0
        uv_mutex_unlock(&tc->instance->mutex_ext_registry);
31
0
        MVM_exception_throw_adhoc(tc, "extension symbol not found");
32
0
    }
33
0
34
0
    entry = MVM_malloc(sizeof *entry);
35
0
    entry->sym = sym;
36
0
    entry->name = name;
37
0
38
0
    MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->name,
39
0
        "Extension name");
40
0
    MVM_HASH_BIND(tc, tc->instance->ext_registry, name, entry);
41
0
    MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->hash_handle.key,
42
0
        "Extension name hash key");
43
0
44
0
    uv_mutex_unlock(&tc->instance->mutex_ext_registry);
45
0
46
0
    /* Call extension's initializer */
47
0
    init = (void (*)(MVMThreadContext *))sym->body.address;
48
0
    init(tc);
49
0
50
0
    return 1;
51
0
}
52
53
int MVM_ext_register_extop(MVMThreadContext *tc, const char *cname,
54
        MVMExtOpFunc func, MVMuint8 num_operands, MVMuint8 operands[],
55
0
        MVMExtOpSpesh *spesh, MVMExtOpFactDiscover *discover, MVMuint32 flags) {
56
0
    MVMExtOpRegistry *entry;
57
0
    MVMString *name = MVM_string_ascii_decode_nt(
58
0
            tc, tc->instance->VMString, cname);
59
0
60
0
    uv_mutex_lock(&tc->instance->mutex_extop_registry);
61
0
62
0
    MVM_HASH_GET(tc, tc->instance->extop_registry, name, entry);
63
0
64
0
    /* Op already registered, so just verify its signature. */
65
0
    if (entry) {
66
0
        uv_mutex_unlock(&tc->instance->mutex_extop_registry);
67
0
        if (num_operands != entry->info.num_operands
68
0
                || memcmp(operands, entry->info.operands, num_operands) != 0)
69
0
            MVM_exception_throw_adhoc(tc,
70
0
                    "signature mismatch when re-registering extension op %s",
71
0
                    cname);
72
0
        return 0;
73
0
    }
74
0
75
0
    /* Sanity-check signature. */
76
0
    if (num_operands > MVM_MAX_OPERANDS) {
77
0
        uv_mutex_unlock(&tc->instance->mutex_extop_registry);
78
0
        MVM_exception_throw_adhoc(tc,
79
0
                "cannot register extension op with more than %u operands",
80
0
                MVM_MAX_OPERANDS);
81
0
    }
82
0
    {
83
0
        MVMuint8 i = 0;
84
0
85
0
        for(; i < num_operands; i++) {
86
0
            MVMuint8 flags = operands[i];
87
0
88
0
            switch (flags & MVM_operand_rw_mask) {
89
0
                case MVM_operand_literal:
90
0
                    goto check_literal;
91
0
92
0
                case MVM_operand_read_reg:
93
0
                case MVM_operand_write_reg:
94
0
                case MVM_operand_read_lex:
95
0
                case MVM_operand_write_lex:
96
0
                    goto check_reg;
97
0
98
0
                default:
99
0
                    goto fail;
100
0
            }
101
0
102
0
        check_literal:
103
0
            switch (flags & MVM_operand_type_mask) {
104
0
                case MVM_operand_int8:
105
0
                case MVM_operand_int16:
106
0
                case MVM_operand_int32:
107
0
                case MVM_operand_int64:
108
0
                case MVM_operand_num32:
109
0
                case MVM_operand_num64:
110
0
                case MVM_operand_str:
111
0
                case MVM_operand_coderef:
112
0
                    continue;
113
0
114
0
                case MVM_operand_ins:
115
0
                case MVM_operand_callsite:
116
0
                default:
117
0
                    goto fail;
118
0
            }
119
0
120
0
        check_reg:
121
0
            switch (flags & MVM_operand_type_mask) {
122
0
                case MVM_operand_int8:
123
0
                case MVM_operand_int16:
124
0
                case MVM_operand_int32:
125
0
                case MVM_operand_int64:
126
0
                case MVM_operand_num32:
127
0
                case MVM_operand_num64:
128
0
                case MVM_operand_str:
129
0
                case MVM_operand_obj:
130
0
                case MVM_operand_type_var:
131
0
                case MVM_operand_uint8:
132
0
                case MVM_operand_uint16:
133
0
                case MVM_operand_uint32:
134
0
                case MVM_operand_uint64:
135
0
                    continue;
136
0
137
0
                default:
138
0
                    goto fail;
139
0
            }
140
0
141
0
        fail:
142
0
            uv_mutex_unlock(&tc->instance->mutex_extop_registry);
143
0
            MVM_exception_throw_adhoc(tc,
144
0
                    "extension op %s has illegal signature", cname);
145
0
        }
146
0
    }
147
0
148
0
    entry                    = MVM_malloc(sizeof *entry);
149
0
    entry->name              = name;
150
0
    entry->func              = func;
151
0
    entry->info.name         = cname;
152
0
    entry->info.opcode       = (MVMuint16)-1;
153
0
    entry->info.mark[0]      = '.';
154
0
    entry->info.mark[1]      = 'x';
155
0
    entry->info.num_operands = num_operands;
156
0
    entry->info.pure         = flags & MVM_EXTOP_PURE;
157
0
    entry->info.deopt_point  = 0;
158
0
    entry->info.logged       = 0;
159
0
    entry->info.no_inline    = flags & MVM_EXTOP_NOINLINE;
160
0
    entry->info.jittivity    = (flags & MVM_EXTOP_INVOKISH) ? MVM_JIT_INFO_INVOKISH : 0;
161
0
    entry->info.uses_hll     = 0;
162
0
    memcpy(entry->info.operands, operands, num_operands);
163
0
    memset(entry->info.operands + num_operands, 0,
164
0
            MVM_MAX_OPERANDS - num_operands);
165
0
    entry->spesh      = spesh;
166
0
    entry->discover   = discover;
167
0
    entry->no_jit     = flags & MVM_EXTOP_NO_JIT;
168
0
    entry->allocating = flags & MVM_EXTOP_ALLOCATING;
169
0
170
0
    MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->name,
171
0
        "Extension op name");
172
0
    MVM_HASH_BIND(tc, tc->instance->extop_registry, name, entry);
173
0
    MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->hash_handle.key,
174
0
        "Extension op name hash key");
175
0
176
0
    uv_mutex_unlock(&tc->instance->mutex_extop_registry);
177
0
178
0
    return 1;
179
0
}
180
181
const MVMOpInfo * MVM_ext_resolve_extop_record(MVMThreadContext *tc,
182
0
        MVMExtOpRecord *record) {
183
0
    MVMExtOpRegistry *entry;
184
0
185
0
    /* Already resolved. */
186
0
    if (record->info)
187
0
        return record->info;
188
0
189
0
    uv_mutex_lock(&tc->instance->mutex_extop_registry);
190
0
191
0
    MVM_HASH_GET(tc, tc->instance->extop_registry, record->name, entry);
192
0
193
0
    if (!entry) {
194
0
        uv_mutex_unlock(&tc->instance->mutex_extop_registry);
195
0
        return NULL;
196
0
    }
197
0
198
0
    /* Resolve record. */
199
0
    record->info       = &entry->info;
200
0
    record->func       = entry->func;
201
0
    record->spesh      = entry->spesh;
202
0
    record->discover   = entry->discover;
203
0
    record->no_jit     = entry->no_jit;
204
0
    record->allocating = entry->allocating;
205
0
206
0
    uv_mutex_unlock(&tc->instance->mutex_extop_registry);
207
0
208
0
    return record->info;
209
0
}