Coverage Report

Created: 2017-04-15 07:07

/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
    MVMROOT(tc, lib, {
10
0
    MVMROOT(tc, ext, {
11
0
        colon = MVM_string_ascii_decode_nt(
12
0
            tc, tc->instance->VMString, ":");
13
0
        prefix = MVM_string_concatenate(tc, lib, colon);
14
0
        name = MVM_string_concatenate(tc, prefix, ext);
15
0
    });
16
0
    });
17
0
18
0
    uv_mutex_lock(&tc->instance->mutex_ext_registry);
19
0
20
0
    MVM_HASH_GET(tc, tc->instance->ext_registry, name, entry);
21
0
22
0
    /* Extension already loaded. */
23
0
    if (entry) {
24
0
        uv_mutex_unlock(&tc->instance->mutex_ext_registry);
25
0
        return 0;
26
0
    }
27
0
28
0
    MVMROOT(tc, name, {
29
0
        sym = (MVMDLLSym *)MVM_dll_find_symbol(tc, lib, ext);
30
0
    });
31
0
    if (!sym) {
32
0
        uv_mutex_unlock(&tc->instance->mutex_ext_registry);
33
0
        MVM_exception_throw_adhoc(tc, "extension symbol not found");
34
0
    }
35
0
36
0
    entry = MVM_malloc(sizeof *entry);
37
0
    entry->sym = sym;
38
0
    entry->name = name;
39
0
40
0
    MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->name,
41
0
        "Extension name");
42
0
    MVM_HASH_BIND(tc, tc->instance->ext_registry, name, entry);
43
0
    MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->hash_handle.key,
44
0
        "Extension name hash key");
45
0
46
0
    uv_mutex_unlock(&tc->instance->mutex_ext_registry);
47
0
48
0
    /* Call extension's initializer */
49
0
    init = (void (*)(MVMThreadContext *))sym->body.address;
50
0
    init(tc);
51
0
52
0
    return 1;
53
0
}
54
55
int MVM_ext_register_extop(MVMThreadContext *tc, const char *cname,
56
        MVMExtOpFunc func, MVMuint8 num_operands, MVMuint8 operands[],
57
0
        MVMExtOpSpesh *spesh, MVMExtOpFactDiscover *discover, MVMuint32 flags) {
58
0
    MVMExtOpRegistry *entry;
59
0
    MVMString *name = MVM_string_ascii_decode_nt(
60
0
            tc, tc->instance->VMString, cname);
61
0
62
0
    uv_mutex_lock(&tc->instance->mutex_extop_registry);
63
0
64
0
    MVM_HASH_GET(tc, tc->instance->extop_registry, name, entry);
65
0
66
0
    /* Op already registered, so just verify its signature. */
67
0
    if (entry) {
68
0
        uv_mutex_unlock(&tc->instance->mutex_extop_registry);
69
0
        if (num_operands != entry->info.num_operands
70
0
                || memcmp(operands, entry->info.operands, num_operands) != 0)
71
0
            MVM_exception_throw_adhoc(tc,
72
0
                    "signature mismatch when re-registering extension op %s",
73
0
                    cname);
74
0
        return 0;
75
0
    }
76
0
77
0
    /* Sanity-check signature. */
78
0
    if (num_operands > MVM_MAX_OPERANDS) {
79
0
        uv_mutex_unlock(&tc->instance->mutex_extop_registry);
80
0
        MVM_exception_throw_adhoc(tc,
81
0
                "cannot register extension op with more than %u operands",
82
0
                MVM_MAX_OPERANDS);
83
0
    }
84
0
    {
85
0
        MVMuint8 i = 0;
86
0
87
0
        for(; i < num_operands; i++) {
88
0
            MVMuint8 flags = operands[i];
89
0
90
0
            switch (flags & MVM_operand_rw_mask) {
91
0
                case MVM_operand_literal:
92
0
                    goto check_literal;
93
0
94
0
                case MVM_operand_read_reg:
95
0
                case MVM_operand_write_reg:
96
0
                case MVM_operand_read_lex:
97
0
                case MVM_operand_write_lex:
98
0
                    goto check_reg;
99
0
100
0
                default:
101
0
                    goto fail;
102
0
            }
103
0
104
0
        check_literal:
105
0
            switch (flags & MVM_operand_type_mask) {
106
0
                case MVM_operand_int8:
107
0
                case MVM_operand_int16:
108
0
                case MVM_operand_int32:
109
0
                case MVM_operand_int64:
110
0
                case MVM_operand_num32:
111
0
                case MVM_operand_num64:
112
0
                case MVM_operand_str:
113
0
                case MVM_operand_coderef:
114
0
                    continue;
115
0
116
0
                case MVM_operand_ins:
117
0
                case MVM_operand_callsite:
118
0
                default:
119
0
                    goto fail;
120
0
            }
121
0
122
0
        check_reg:
123
0
            switch (flags & MVM_operand_type_mask) {
124
0
                case MVM_operand_int8:
125
0
                case MVM_operand_int16:
126
0
                case MVM_operand_int32:
127
0
                case MVM_operand_int64:
128
0
                case MVM_operand_num32:
129
0
                case MVM_operand_num64:
130
0
                case MVM_operand_str:
131
0
                case MVM_operand_obj:
132
0
                case MVM_operand_type_var:
133
0
                case MVM_operand_uint8:
134
0
                case MVM_operand_uint16:
135
0
                case MVM_operand_uint32:
136
0
                case MVM_operand_uint64:
137
0
                    continue;
138
0
139
0
                default:
140
0
                    goto fail;
141
0
            }
142
0
143
0
        fail:
144
0
            uv_mutex_unlock(&tc->instance->mutex_extop_registry);
145
0
            MVM_exception_throw_adhoc(tc,
146
0
                    "extension op %s has illegal signature", cname);
147
0
        }
148
0
    }
149
0
150
0
    entry                    = MVM_malloc(sizeof *entry);
151
0
    entry->name              = name;
152
0
    entry->func              = func;
153
0
    entry->info.name         = cname;
154
0
    entry->info.opcode       = (MVMuint16)-1;
155
0
    entry->info.mark[0]      = '.';
156
0
    entry->info.mark[1]      = 'x';
157
0
    entry->info.num_operands = num_operands;
158
0
    entry->info.pure         = flags & MVM_EXTOP_PURE;
159
0
    entry->info.deopt_point  = 0;
160
0
    entry->info.no_inline    = flags & MVM_EXTOP_NOINLINE;
161
0
    entry->info.jittivity    = (flags & MVM_EXTOP_INVOKISH) ? MVM_JIT_INFO_INVOKISH : 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
}