/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 | } |