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