Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/core/hll.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
2.78k
MVMHLLConfig *MVM_hll_get_config_for(MVMThreadContext *tc, MVMString *name) {
4
2.78k
    MVMHLLConfig *entry;
5
2.78k
6
2.78k
    uv_mutex_lock(&tc->instance->mutex_hllconfigs);
7
2.78k
8
2.78k
    if (tc->instance->hll_compilee_depth) {
9
0
        MVM_HASH_GET(tc, tc->instance->compilee_hll_configs, name, entry);
10
0
    }
11
2.78k
    else {
12
2.78k
        MVM_HASH_GET(tc, tc->instance->compiler_hll_configs, name, entry);
13
2.78k
    }
14
2.78k
15
2.78k
    if (!entry) {
16
148
        entry = MVM_calloc(1, sizeof(MVMHLLConfig));
17
148
        entry->name = name;
18
148
        entry->int_box_type = tc->instance->boot_types.BOOTInt;
19
148
        entry->num_box_type = tc->instance->boot_types.BOOTNum;
20
148
        entry->str_box_type = tc->instance->boot_types.BOOTStr;
21
148
        entry->slurpy_array_type = tc->instance->boot_types.BOOTArray;
22
148
        entry->slurpy_hash_type = tc->instance->boot_types.BOOTHash;
23
148
        entry->array_iterator_type = tc->instance->boot_types.BOOTIter;
24
148
        entry->hash_iterator_type = tc->instance->boot_types.BOOTIter;
25
148
        entry->foreign_type_int = tc->instance->boot_types.BOOTInt;
26
148
        entry->foreign_type_num = tc->instance->boot_types.BOOTNum;
27
148
        entry->foreign_type_str = tc->instance->boot_types.BOOTStr;
28
148
        if (tc->instance->hll_compilee_depth) {
29
0
            MVM_HASH_BIND(tc, tc->instance->compilee_hll_configs, name, entry);
30
0
        }
31
148
        else {
32
148
            MVM_HASH_BIND(tc, tc->instance->compiler_hll_configs, name, entry);
33
148
        }
34
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->int_box_type, "HLL int_box_type");
35
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->num_box_type, "HLL num_box_type");
36
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->str_box_type, "HLL str_box_type");
37
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->slurpy_array_type, "HLL slurpy_array_type");
38
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->slurpy_hash_type, "HLL slurpy_hash_type");
39
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->array_iterator_type, "HLL array_iterator_type");
40
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->hash_iterator_type, "HLL hash_iterator_type");
41
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->foreign_type_int, "HLL foreign_type_int");
42
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->foreign_type_num, "HLL foreign_type_num");
43
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->foreign_type_str, "HLL foreign_type_str");
44
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->foreign_transform_array, "HLL foreign_transform_array");
45
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->foreign_transform_hash, "HLL foreign_transform_hash");
46
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->foreign_transform_code, "HLL foreign_transform_code");
47
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->null_value, "HLL null_value");
48
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->exit_handler, "HLL exit_handler");
49
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->finalize_handler, "HLL finalize_handler");
50
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->bind_error, "HLL bind_error");
51
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->method_not_found_error, "HLL method_not_found_error");
52
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->lexical_handler_not_found_error, "HLL lexical_handler_not_found_error");
53
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->int_lex_ref, "HLL int_lex_ref");
54
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->num_lex_ref, "HLL num_lex_ref");
55
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->str_lex_ref, "HLL str_lex_ref");
56
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->int_attr_ref, "HLL int_attr_ref");
57
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->num_attr_ref, "HLL num_attr_ref");
58
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->str_attr_ref, "HLL str_attr_ref");
59
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->int_pos_ref, "HLL int_pos_ref");
60
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->num_pos_ref, "HLL num_pos_ref");
61
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->str_pos_ref, "HLL str_pos_ref");
62
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->int_multidim_ref, "HLL int_multidim_ref");
63
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->num_multidim_ref, "HLL num_multidim_ref");
64
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->str_multidim_ref, "HLL str_multidim_ref");
65
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->name, "HLL name");
66
148
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->hash_handle.key, "HLL hash key");
67
148
    }
68
2.78k
69
2.78k
    uv_mutex_unlock(&tc->instance->mutex_hllconfigs);
70
2.78k
71
2.78k
    return entry;
72
2.78k
}
73
74
#define check_config_key(tc, hash, name, member, config) do { \
75
    MVMString *key = MVM_string_utf8_decode((tc), (tc)->instance->VMString, (name), strlen((name))); \
76
    MVMObject *val = MVM_repr_at_key_o((tc), (hash), key); \
77
    if (!MVM_is_null(tc, val)) (config)->member = val; \
78
} while (0)
79
#define check_config_key_reftype(tc, hash, name, member, config, wantprim, wantkind) do { \
80
    MVMString *key = MVM_string_utf8_decode((tc), (tc)->instance->VMString, (name), strlen((name))); \
81
    MVMObject *val = MVM_repr_at_key_o((tc), (hash), key); \
82
    if (!MVM_is_null(tc, val)) { \
83
        MVM_nativeref_ensure(tc, val, wantprim, wantkind, name); \
84
        (config)->member = val; \
85
    }\
86
} while (0)
87
88
145
MVMObject * MVM_hll_set_config(MVMThreadContext *tc, MVMString *name, MVMObject *config_hash) {
89
145
    MVMHLLConfig *config;
90
145
91
145
    config = MVM_hll_get_config_for(tc, name);
92
145
93
145
    if (!config_hash || REPR(config_hash)->ID != MVM_REPR_ID_MVMHash
94
145
            || !IS_CONCRETE(config_hash)) {
95
0
        MVM_exception_throw_adhoc(tc, "set hll config needs concrete hash");
96
0
    }
97
145
98
145
    /* MVM_string_utf8_decode() can potentially allocate, and hence gc. */
99
145
    MVMROOT(tc, config_hash, {
100
145
            check_config_key(tc, config_hash, "int_box", int_box_type, config);
101
145
            check_config_key(tc, config_hash, "num_box", num_box_type, config);
102
145
            check_config_key(tc, config_hash, "str_box", str_box_type, config);
103
145
            check_config_key(tc, config_hash, "slurpy_array", slurpy_array_type, config);
104
145
            check_config_key(tc, config_hash, "slurpy_hash", slurpy_hash_type, config);
105
145
            check_config_key(tc, config_hash, "array_iter", array_iterator_type, config);
106
145
            check_config_key(tc, config_hash, "hash_iter", hash_iterator_type, config);
107
145
            check_config_key(tc, config_hash, "foreign_type_int", foreign_type_int, config);
108
145
            check_config_key(tc, config_hash, "foreign_type_num", foreign_type_num, config);
109
145
            check_config_key(tc, config_hash, "foreign_type_str", foreign_type_str, config);
110
145
            check_config_key(tc, config_hash, "foreign_transform_array", foreign_transform_array, config);
111
145
            check_config_key(tc, config_hash, "foreign_transform_hash", foreign_transform_hash, config);
112
145
            check_config_key(tc, config_hash, "foreign_transform_code", foreign_transform_code, config);
113
145
            check_config_key(tc, config_hash, "null_value", null_value, config);
114
145
            check_config_key(tc, config_hash, "exit_handler", exit_handler, config);
115
145
            check_config_key(tc, config_hash, "finalize_handler", finalize_handler, config);
116
145
            check_config_key(tc, config_hash, "bind_error", bind_error, config);
117
145
            check_config_key(tc, config_hash, "method_not_found_error", method_not_found_error, config);
118
145
            check_config_key(tc, config_hash, "lexical_handler_not_found_error", lexical_handler_not_found_error, config);
119
145
            check_config_key_reftype(tc, config_hash, "int_lex_ref", int_lex_ref,
120
145
                config, MVM_STORAGE_SPEC_BP_INT, MVM_NATIVEREF_LEX);
121
145
            check_config_key_reftype(tc, config_hash, "num_lex_ref", num_lex_ref,
122
145
                config, MVM_STORAGE_SPEC_BP_NUM, MVM_NATIVEREF_LEX);
123
145
            check_config_key_reftype(tc, config_hash, "str_lex_ref", str_lex_ref,
124
145
                config, MVM_STORAGE_SPEC_BP_STR, MVM_NATIVEREF_LEX);
125
145
            check_config_key_reftype(tc, config_hash, "int_attr_ref", int_attr_ref,
126
145
                config, MVM_STORAGE_SPEC_BP_INT, MVM_NATIVEREF_ATTRIBUTE);
127
145
            check_config_key_reftype(tc, config_hash, "num_attr_ref", num_attr_ref,
128
145
                config, MVM_STORAGE_SPEC_BP_NUM, MVM_NATIVEREF_ATTRIBUTE);
129
145
            check_config_key_reftype(tc, config_hash, "str_attr_ref", str_attr_ref,
130
145
                config, MVM_STORAGE_SPEC_BP_STR, MVM_NATIVEREF_ATTRIBUTE);
131
145
            check_config_key_reftype(tc, config_hash, "int_pos_ref", int_pos_ref,
132
145
                config, MVM_STORAGE_SPEC_BP_INT, MVM_NATIVEREF_POSITIONAL);
133
145
            check_config_key_reftype(tc, config_hash, "num_pos_ref", num_pos_ref,
134
145
                config, MVM_STORAGE_SPEC_BP_NUM, MVM_NATIVEREF_POSITIONAL);
135
145
            check_config_key_reftype(tc, config_hash, "str_pos_ref", str_pos_ref,
136
145
                config, MVM_STORAGE_SPEC_BP_STR, MVM_NATIVEREF_POSITIONAL);
137
145
            check_config_key_reftype(tc, config_hash, "int_multidim_ref", int_multidim_ref,
138
145
                config, MVM_STORAGE_SPEC_BP_INT, MVM_NATIVEREF_MULTIDIM);
139
145
            check_config_key_reftype(tc, config_hash, "num_multidim_ref", num_multidim_ref,
140
145
                config, MVM_STORAGE_SPEC_BP_NUM, MVM_NATIVEREF_MULTIDIM);
141
145
            check_config_key_reftype(tc, config_hash, "str_multidim_ref", str_multidim_ref,
142
145
                config, MVM_STORAGE_SPEC_BP_STR, MVM_NATIVEREF_MULTIDIM);
143
145
        });
144
145
145
145
    MVM_intcache_for(tc, config->int_box_type);
146
145
147
145
    return config_hash;
148
145
}
149
150
/* Gets the current HLL configuration. */
151
626k
MVMHLLConfig *MVM_hll_current(MVMThreadContext *tc) {
152
626k
    return (*tc->interp_cu)->body.hll_config;
153
626k
}
154
155
/* Enter a level of compilee HLL configuration mode. */
156
0
void MVM_hll_enter_compilee_mode(MVMThreadContext *tc) {
157
0
    uv_mutex_lock(&tc->instance->mutex_hllconfigs);
158
0
    tc->instance->hll_compilee_depth++;
159
0
    uv_mutex_unlock(&tc->instance->mutex_hllconfigs);
160
0
}
161
162
/* Leave a level of compilee HLL configuration mode. */
163
0
void MVM_hll_leave_compilee_mode(MVMThreadContext *tc) {
164
0
    uv_mutex_lock(&tc->instance->mutex_hllconfigs);
165
0
    tc->instance->hll_compilee_depth--;
166
0
    uv_mutex_unlock(&tc->instance->mutex_hllconfigs);
167
0
}
168
169
/* Checks if an object belongs to the correct HLL, and does a type mapping
170
 * of it if not. */
171
23
void MVM_hll_map(MVMThreadContext *tc, MVMObject *obj, MVMHLLConfig *hll, MVMRegister *res_reg) {
172
23
    /* Null objects get mapped to null_value. */
173
23
    if (MVM_is_null(tc, obj)) {
174
3
        res_reg->o = hll->null_value;
175
3
    }
176
23
177
23
    /* If the object belongs to the current HLL, we're done. */
178
20
    else if (STABLE(obj)->hll_owner == hll) {
179
4
        res_reg->o = obj;
180
4
    }
181
20
182
20
    /* Otherwise, need to try a mapping. */
183
16
    else {
184
16
        switch (STABLE(obj)->hll_role) {
185
1
            case MVM_HLL_ROLE_INT:
186
1
                if (hll->foreign_type_int)
187
1
                    res_reg->o = IS_CONCRETE(obj)
188
1
                        ? MVM_repr_box_int(tc, hll->foreign_type_int, MVM_repr_get_int(tc, obj))
189
0
                        : hll->foreign_type_int;
190
1
                else
191
0
                    res_reg->o = obj;
192
1
                break;
193
1
            case MVM_HLL_ROLE_NUM:
194
1
                if (hll->foreign_type_num)
195
1
                    res_reg->o = IS_CONCRETE(obj)
196
1
                        ? MVM_repr_box_num(tc, hll->foreign_type_num, MVM_repr_get_num(tc, obj))
197
0
                        : hll->foreign_type_num;
198
1
                else
199
0
                    res_reg->o = obj;
200
1
                break;
201
1
            case MVM_HLL_ROLE_STR:
202
1
                if (hll->foreign_type_str)
203
1
                    res_reg->o = IS_CONCRETE(obj)
204
1
                        ? MVM_repr_box_str(tc, hll->foreign_type_str, MVM_repr_get_str(tc, obj))
205
0
                        : hll->foreign_type_str;
206
1
                else
207
0
                    res_reg->o = obj;
208
1
                break;
209
6
            case MVM_HLL_ROLE_ARRAY:
210
6
                if (hll->foreign_transform_array) {
211
5
                    /* Invoke and set result register as return location. */
212
5
                    MVMObject *code = MVM_frame_find_invokee(tc, hll->foreign_transform_array, NULL);
213
5
                    MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
214
5
215
5
                    MVM_args_setup_thunk(tc, res_reg, MVM_RETURN_OBJ, inv_arg_callsite);
216
5
                    tc->cur_frame->args[0].o = obj;
217
5
                    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
218
5
                }
219
1
                else {
220
1
                    res_reg->o = obj;
221
1
                }
222
6
                break;
223
2
            case MVM_HLL_ROLE_HASH:
224
2
                if (hll->foreign_transform_hash) {
225
2
                    /* Invoke and set result register as return location. */
226
2
                    MVMObject *code = MVM_frame_find_invokee(tc, hll->foreign_transform_hash, NULL);
227
2
                    MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
228
2
229
2
                    MVM_args_setup_thunk(tc, res_reg, MVM_RETURN_OBJ, inv_arg_callsite);
230
2
                    tc->cur_frame->args[0].o = obj;
231
2
                    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
232
2
                }
233
0
                else {
234
0
                    res_reg->o = obj;
235
0
                }
236
2
                break;
237
3
            case MVM_HLL_ROLE_CODE:
238
3
                if (hll->foreign_transform_code) {
239
2
                    /* Invoke and set result register as return location. */
240
2
                    MVMObject *code = MVM_frame_find_invokee(tc, hll->foreign_transform_code, NULL);
241
2
                    MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
242
2
243
2
                    MVM_args_setup_thunk(tc, res_reg, MVM_RETURN_OBJ, inv_arg_callsite);
244
2
                    tc->cur_frame->args[0].o = obj;
245
2
                    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
246
2
                }
247
1
                else {
248
1
                    res_reg->o = obj;
249
1
                }
250
3
                break;
251
2
            default:
252
2
                res_reg->o = obj;
253
16
        }
254
16
    }
255
23
}
256
257
/* Looks up an object in the HLL symbols stash. */
258
4.84k
MVMObject * MVM_hll_sym_get(MVMThreadContext *tc, MVMString *hll, MVMString *sym) {
259
4.84k
    MVMObject *syms = tc->instance->hll_syms, *hash, *result;
260
4.84k
    uv_mutex_lock(&tc->instance->mutex_hll_syms);
261
4.84k
    hash = MVM_repr_at_key_o(tc, syms, hll);
262
4.84k
    if (MVM_is_null(tc, hash)) {
263
1
        MVMROOT(tc, hll, {
264
1
        MVMROOT(tc, syms, {
265
1
            hash = MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTHash);
266
1
        });
267
1
        });
268
1
        MVM_repr_bind_key_o(tc, syms, hll, hash);
269
1
        result = tc->instance->VMNull;
270
1
    }
271
4.84k
    else {
272
4.84k
        result = MVM_repr_at_key_o(tc, hash, sym);
273
4.84k
    }
274
4.84k
    uv_mutex_unlock(&tc->instance->mutex_hll_syms);
275
4.84k
    return result;
276
4.84k
}