/home/travis/build/MoarVM/MoarVM/src/6model/reprs/NativeRef.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | |
3 | | /* This representation's function pointer table. */ |
4 | | static const MVMREPROps NativeRef_this_repr; |
5 | | |
6 | | /* Creates a new type object of this representation, and associates it with |
7 | | * the given HOW. */ |
8 | 16 | static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) { |
9 | 16 | MVMSTable *st = MVM_gc_allocate_stable(tc, &NativeRef_this_repr, HOW); |
10 | 16 | |
11 | 16 | MVMROOT(tc, st, { |
12 | 16 | MVMObject *obj = MVM_gc_allocate_type_object(tc, st); |
13 | 16 | MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj); |
14 | 16 | st->size = sizeof(MVMNativeRef); |
15 | 16 | }); |
16 | 16 | |
17 | 16 | return st->WHAT; |
18 | 16 | } |
19 | | |
20 | | /* Copies the body of one object to another. */ |
21 | 0 | static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) { |
22 | 0 | MVM_exception_throw_adhoc(tc, "Cannot copy object with repr MVMNativeRef"); |
23 | 0 | } |
24 | | |
25 | | /* Set the size of objects on the STable. */ |
26 | 0 | static void deserialize_stable_size(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) { |
27 | 0 | st->size = sizeof(MVMNativeRef); |
28 | 0 | } |
29 | | |
30 | | /* Serializes the REPR data. */ |
31 | 0 | static void serialize_repr_data(MVMThreadContext *tc, MVMSTable *st, MVMSerializationWriter *writer) { |
32 | 0 | MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)st->REPR_data; |
33 | 0 | if (repr_data) { |
34 | 0 | MVM_serialization_write_int(tc, writer, repr_data->primitive_type); |
35 | 0 | MVM_serialization_write_int(tc, writer, repr_data->ref_kind); |
36 | 0 | } |
37 | 0 | else { |
38 | 0 | MVM_serialization_write_int(tc, writer, 0); |
39 | 0 | MVM_serialization_write_int(tc, writer, 0); |
40 | 0 | } |
41 | 0 | } |
42 | | |
43 | | /* Deserializes REPR data. */ |
44 | 0 | static void deserialize_repr_data(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) { |
45 | 0 | MVMNativeRefREPRData *repr_data = MVM_malloc(sizeof(MVMNativeRefREPRData)); |
46 | 0 | repr_data->primitive_type = MVM_serialization_read_int(tc, reader); |
47 | 0 | repr_data->ref_kind = MVM_serialization_read_int(tc, reader); |
48 | 0 | st->REPR_data = repr_data; |
49 | 0 | } |
50 | | |
51 | | /* Called by the VM to mark any GCable items. */ |
52 | 0 | static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) { |
53 | 0 | MVMNativeRefBody *ref = (MVMNativeRefBody *)data; |
54 | 0 | MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)st->REPR_data; |
55 | 0 | switch (repr_data->ref_kind) { |
56 | 0 | case MVM_NATIVEREF_LEX: |
57 | 0 | MVM_gc_worklist_add(tc, worklist, &ref->u.lex.frame); |
58 | 0 | break; |
59 | 0 | case MVM_NATIVEREF_ATTRIBUTE: |
60 | 0 | MVM_gc_worklist_add(tc, worklist, &ref->u.attribute.obj); |
61 | 0 | MVM_gc_worklist_add(tc, worklist, &ref->u.attribute.class_handle); |
62 | 0 | MVM_gc_worklist_add(tc, worklist, &ref->u.attribute.name); |
63 | 0 | break; |
64 | 0 | case MVM_NATIVEREF_POSITIONAL: |
65 | 0 | MVM_gc_worklist_add(tc, worklist, &ref->u.positional.obj); |
66 | 0 | break; |
67 | 0 | case MVM_NATIVEREF_MULTIDIM: |
68 | 0 | MVM_gc_worklist_add(tc, worklist, &ref->u.multidim.obj); |
69 | 0 | MVM_gc_worklist_add(tc, worklist, &ref->u.multidim.indices); |
70 | 0 | break; |
71 | 0 | } |
72 | 0 | } |
73 | | |
74 | | /* Frees the representation data, if any. */ |
75 | 0 | static void gc_free_repr_data(MVMThreadContext *tc, MVMSTable *st) { |
76 | 0 | MVM_free(st->REPR_data); |
77 | 0 | } |
78 | | |
79 | | /* Gets the storage specification for this representation. */ |
80 | | static const MVMStorageSpec storage_spec = { |
81 | | MVM_STORAGE_SPEC_REFERENCE, /* inlineable */ |
82 | | 0, /* bits */ |
83 | | 0, /* align */ |
84 | | MVM_STORAGE_SPEC_BP_NONE, /* boxed_primitive */ |
85 | | 0, /* can_box */ |
86 | | 0, /* is_unsigned */ |
87 | | }; |
88 | 0 | static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) { |
89 | 0 | return &storage_spec; |
90 | 0 | } |
91 | | |
92 | | /* Compose the representation. */ |
93 | 16 | static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info_hash) { |
94 | 16 | MVMStringConsts *str_consts = &(tc->instance->str_consts); |
95 | 16 | MVMObject *info = MVM_repr_at_key_o(tc, info_hash, str_consts->nativeref); |
96 | 16 | if (IS_CONCRETE(info)) { |
97 | 16 | MVMObject *type = MVM_repr_at_key_o(tc, info, str_consts->type); |
98 | 16 | MVMuint16 prim = REPR(type)->get_storage_spec(tc, STABLE(type))->boxed_primitive; |
99 | 16 | if (prim != MVM_STORAGE_SPEC_BP_NONE) { |
100 | 16 | MVMObject *refkind = MVM_repr_at_key_o(tc, info, str_consts->refkind); |
101 | 16 | if (IS_CONCRETE(refkind)) { |
102 | 16 | MVMNativeRefREPRData *repr_data; |
103 | 16 | MVMuint16 kind; |
104 | 16 | MVMString *refkind_s = MVM_repr_get_str(tc, refkind); |
105 | 16 | if (MVM_string_equal(tc, refkind_s, str_consts->lexical)) { |
106 | 7 | kind = MVM_NATIVEREF_LEX; |
107 | 7 | } |
108 | 9 | else if (MVM_string_equal(tc, refkind_s, str_consts->attribute)) { |
109 | 6 | kind = MVM_NATIVEREF_ATTRIBUTE; |
110 | 6 | } |
111 | 3 | else if (MVM_string_equal(tc, refkind_s, str_consts->positional)) { |
112 | 3 | kind = MVM_NATIVEREF_POSITIONAL; |
113 | 3 | } |
114 | 0 | else if (MVM_string_equal(tc, refkind_s, str_consts->multidim)) { |
115 | 0 | kind = MVM_NATIVEREF_MULTIDIM; |
116 | 0 | } |
117 | 0 | else { |
118 | 0 | MVM_exception_throw_adhoc(tc, "NativeRef: invalid refkind in compose"); |
119 | 0 | } |
120 | 16 | |
121 | 16 | repr_data = MVM_malloc(sizeof(MVMNativeRefREPRData)); |
122 | 16 | repr_data->primitive_type = prim; |
123 | 16 | repr_data->ref_kind = kind; |
124 | 16 | st->REPR_data = repr_data; |
125 | 16 | } |
126 | 0 | else { |
127 | 0 | MVM_exception_throw_adhoc(tc, "NativeRef: missing refkind in compose"); |
128 | 0 | } |
129 | 16 | } |
130 | 0 | else { |
131 | 0 | MVM_exception_throw_adhoc(tc, "NativeRef: non-native type supplied in compose"); |
132 | 0 | } |
133 | 16 | } |
134 | 0 | else { |
135 | 0 | MVM_exception_throw_adhoc(tc, "NativeRef: missing nativeref protocol in compose"); |
136 | 0 | } |
137 | 16 | } |
138 | | |
139 | | /* Initializes the representation. */ |
140 | 130 | const MVMREPROps * MVMNativeRef_initialize(MVMThreadContext *tc) { |
141 | 130 | return &NativeRef_this_repr; |
142 | 130 | } |
143 | | |
144 | 0 | static void spesh(MVMThreadContext *tc, MVMSTable *st, MVMSpeshGraph *g, MVMSpeshBB *bb, MVMSpeshIns *ins) { |
145 | 0 | MVMNativeRefREPRData * repr_data = (MVMNativeRefREPRData *)st->REPR_data; |
146 | 0 | MVMuint16 opcode = ins->info->opcode; |
147 | 0 |
|
148 | 0 | if (!repr_data) |
149 | 0 | return; |
150 | 0 |
|
151 | 0 | if (repr_data->ref_kind != MVM_NATIVEREF_LEX) |
152 | 0 | return; /* TODO implement spesh for attribute and positional references */ |
153 | 0 |
|
154 | 0 | switch (opcode) { |
155 | 0 | case MVM_OP_assign_i: { |
156 | 0 | MVMSpeshOperand target = ins->operands[0]; |
157 | 0 | MVMSpeshOperand value = ins->operands[1]; |
158 | 0 | if (repr_data->primitive_type != MVM_STORAGE_SPEC_BP_INT) |
159 | 0 | return; /* Shouldn't happen. so maybe throw an error? */ |
160 | 0 | ins->info = MVM_op_get_op(MVM_OP_sp_deref_bind_i64); |
161 | 0 | ins->operands = MVM_spesh_alloc(tc, g, 3 * sizeof(MVMSpeshOperand)); |
162 | 0 | ins->operands[0] = target; |
163 | 0 | ins->operands[1] = value; |
164 | 0 | ins->operands[2].lit_i64 = offsetof(MVMNativeRef, body.u.lex.var); |
165 | 0 | break; |
166 | 0 | } |
167 | 0 | case MVM_OP_decont_i: { |
168 | 0 | MVMSpeshOperand target = ins->operands[0]; |
169 | 0 | MVMSpeshOperand source = ins->operands[1]; |
170 | 0 | if (repr_data->primitive_type != MVM_STORAGE_SPEC_BP_INT) |
171 | 0 | return; /* Shouldn't happen. so maybe throw an error? */ |
172 | 0 | ins->info = MVM_op_get_op(MVM_OP_sp_deref_get_i64); |
173 | 0 | ins->operands = MVM_spesh_alloc(tc, g, 3 * sizeof(MVMSpeshOperand)); |
174 | 0 | ins->operands[0] = target; |
175 | 0 | ins->operands[1] = source; |
176 | 0 | ins->operands[2].lit_i64 = offsetof(MVMNativeRef, body.u.lex.var); |
177 | 0 | break; |
178 | 0 | } |
179 | 0 | } |
180 | 0 | } |
181 | | |
182 | | static const MVMREPROps NativeRef_this_repr = { |
183 | | type_object_for, |
184 | | MVM_gc_allocate_object, |
185 | | NULL, /* initialize */ |
186 | | copy_to, |
187 | | MVM_REPR_DEFAULT_ATTR_FUNCS, |
188 | | MVM_REPR_DEFAULT_BOX_FUNCS, |
189 | | MVM_REPR_DEFAULT_POS_FUNCS, |
190 | | MVM_REPR_DEFAULT_ASS_FUNCS, |
191 | | MVM_REPR_DEFAULT_ELEMS, |
192 | | get_storage_spec, |
193 | | NULL, /* change_type */ |
194 | | NULL, /* serialize */ |
195 | | NULL, /* deserialize */ |
196 | | serialize_repr_data, |
197 | | deserialize_repr_data, |
198 | | deserialize_stable_size, |
199 | | gc_mark, |
200 | | NULL, /* gc_free */ |
201 | | NULL, /* gc_cleanup */ |
202 | | NULL, /* gc_mark_repr_data */ |
203 | | gc_free_repr_data, |
204 | | compose, |
205 | | spesh, /* spesh */ |
206 | | "NativeRef", /* name */ |
207 | | MVM_REPR_ID_NativeRef, |
208 | | NULL, /* unmanaged_size */ |
209 | | NULL, /* describe_refs */ |
210 | | }; |
211 | | |
212 | | /* Validates the given type is a native reference of the required primitive |
213 | | * type and reference kind. */ |
214 | 16 | void MVM_nativeref_ensure(MVMThreadContext *tc, MVMObject *type, MVMuint16 wantprim, MVMuint16 wantkind, char *guilty) { |
215 | 16 | if (REPR(type)->ID == MVM_REPR_ID_NativeRef) { |
216 | 16 | MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(type)->REPR_data; |
217 | 16 | if (!repr_data) |
218 | 0 | MVM_exception_throw_adhoc(tc, "%s set to NativeRef that is not yet composed", guilty); |
219 | 16 | if (repr_data->primitive_type != wantprim) |
220 | 0 | MVM_exception_throw_adhoc(tc, "%s set to NativeRef of wrong primitive type", guilty); |
221 | 16 | if (repr_data->ref_kind != wantkind) |
222 | 0 | MVM_exception_throw_adhoc(tc, "%s set to NativeRef of wrong reference kind", guilty); |
223 | 16 | } |
224 | 0 | else { |
225 | 0 | MVM_exception_throw_adhoc(tc, "%s requires a type with REPR NativeRef", guilty); |
226 | 0 | } |
227 | 16 | } |
228 | | |
229 | | /* Creation of native references for lexicals. */ |
230 | 15 | static MVMObject * lex_ref(MVMThreadContext *tc, MVMObject *type, MVMFrame *f, MVMRegister *r, MVMuint16 reg_type) { |
231 | 15 | MVMNativeRef *ref; |
232 | 15 | MVMROOT(tc, f, { |
233 | 15 | ref = (MVMNativeRef *)MVM_gc_allocate_object(tc, STABLE(type)); |
234 | 15 | }); |
235 | 15 | MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.lex.frame, f); |
236 | 15 | ref->body.u.lex.var = r; |
237 | 15 | ref->body.u.lex.type = reg_type; |
238 | 15 | return (MVMObject *)ref; |
239 | 15 | } |
240 | | |
241 | | /* Creation of native references for lexicals. */ |
242 | 15 | static MVMFrame * get_lexical_outer(MVMThreadContext *tc, MVMuint16 outers) { |
243 | 15 | MVMFrame *f = tc->cur_frame; |
244 | 15 | while (outers) { |
245 | 0 | if (!f) |
246 | 0 | MVM_exception_throw_adhoc(tc, "getlexref_*: outer index out of range"); |
247 | 0 | f = f->outer; |
248 | 0 | outers--; |
249 | 0 | } |
250 | 15 | return f; |
251 | 15 | } |
252 | 5 | MVMObject * MVM_nativeref_lex_i(MVMThreadContext *tc, MVMuint16 outers, MVMuint16 idx) { |
253 | 5 | MVMObject *ref_type; |
254 | 5 | MVM_frame_force_to_heap(tc, tc->cur_frame); |
255 | 5 | ref_type = MVM_hll_current(tc)->int_lex_ref; |
256 | 5 | if (ref_type) { |
257 | 5 | MVMFrame *f = get_lexical_outer(tc, outers); |
258 | 0 | MVMuint16 *lexical_types = f->spesh_cand && f->spesh_cand->lexical_types |
259 | 0 | ? f->spesh_cand->lexical_types |
260 | 5 | : f->static_info->body.lexical_types; |
261 | 5 | MVMuint16 type = lexical_types[idx]; |
262 | 5 | if (type != MVM_reg_int64 && type != MVM_reg_int32 && |
263 | 0 | type != MVM_reg_int16 && type != MVM_reg_int8 && |
264 | 0 | type != MVM_reg_uint64 && type != MVM_reg_uint32 && |
265 | 0 | type != MVM_reg_uint16 && type != MVM_reg_uint8) |
266 | 0 | MVM_exception_throw_adhoc(tc, "getlexref_i: lexical is not an int"); |
267 | 5 | return lex_ref(tc, ref_type, f, &(f->env[idx]), type); |
268 | 5 | } |
269 | 0 | MVM_exception_throw_adhoc(tc, "No int lexical reference type registered for current HLL"); |
270 | 0 | } |
271 | 5 | MVMObject * MVM_nativeref_lex_n(MVMThreadContext *tc, MVMuint16 outers, MVMuint16 idx) { |
272 | 5 | MVMObject *ref_type; |
273 | 5 | MVM_frame_force_to_heap(tc, tc->cur_frame); |
274 | 5 | ref_type = MVM_hll_current(tc)->num_lex_ref; |
275 | 5 | if (ref_type) { |
276 | 5 | MVMFrame *f = get_lexical_outer(tc, outers); |
277 | 0 | MVMuint16 *lexical_types = f->spesh_cand && f->spesh_cand->lexical_types |
278 | 0 | ? f->spesh_cand->lexical_types |
279 | 5 | : f->static_info->body.lexical_types; |
280 | 5 | MVMuint16 type = lexical_types[idx]; |
281 | 5 | if (type != MVM_reg_num64 && type != MVM_reg_num32) |
282 | 0 | MVM_exception_throw_adhoc(tc, "getlexref_n: lexical is not a num"); |
283 | 5 | return lex_ref(tc, ref_type, f, &(f->env[idx]), type); |
284 | 5 | } |
285 | 0 | MVM_exception_throw_adhoc(tc, "No num lexical reference type registered for current HLL"); |
286 | 0 | } |
287 | 5 | MVMObject * MVM_nativeref_lex_s(MVMThreadContext *tc, MVMuint16 outers, MVMuint16 idx) { |
288 | 5 | MVMObject *ref_type; |
289 | 5 | MVM_frame_force_to_heap(tc, tc->cur_frame); |
290 | 5 | ref_type = MVM_hll_current(tc)->str_lex_ref; |
291 | 5 | if (ref_type) { |
292 | 5 | MVMFrame *f = get_lexical_outer(tc, outers); |
293 | 0 | MVMuint16 *lexical_types = f->spesh_cand && f->spesh_cand->lexical_types |
294 | 0 | ? f->spesh_cand->lexical_types |
295 | 5 | : f->static_info->body.lexical_types; |
296 | 5 | if (lexical_types[idx] != MVM_reg_str) |
297 | 0 | MVM_exception_throw_adhoc(tc, "getlexref_s: lexical is not a str (%d, %d)", outers, idx); |
298 | 5 | return lex_ref(tc, ref_type, f, &(f->env[idx]), MVM_reg_str); |
299 | 5 | } |
300 | 0 | MVM_exception_throw_adhoc(tc, "No str lexical reference type registered for current HLL"); |
301 | 0 | } |
302 | 0 | static MVMObject * lexref_by_name(MVMThreadContext *tc, MVMObject *type, MVMString *name, MVMuint16 kind) { |
303 | 0 | MVMFrame *cur_frame = tc->cur_frame; |
304 | 0 | while (cur_frame != NULL) { |
305 | 0 | MVMLexicalRegistry *lexical_names = cur_frame->static_info->body.lexical_names; |
306 | 0 | if (lexical_names) { |
307 | 0 | MVMLexicalRegistry *entry; |
308 | 0 | MVM_HASH_GET(tc, lexical_names, name, entry) |
309 | 0 | if (entry) { |
310 | 0 | if (cur_frame->static_info->body.lexical_types[entry->value] == kind) { |
311 | 0 | return lex_ref(tc, type, cur_frame, &cur_frame->env[entry->value], kind); |
312 | 0 | } |
313 | 0 | else { |
314 | 0 | char *c_name = MVM_string_utf8_encode_C_string(tc, name); |
315 | 0 | char *waste[] = { c_name, NULL }; |
316 | 0 | MVM_exception_throw_adhoc_free(tc, waste, |
317 | 0 | "Lexical with name '%s' has wrong type", |
318 | 0 | c_name); |
319 | 0 | } |
320 | 0 | } |
321 | 0 | } |
322 | 0 | cur_frame = cur_frame->outer; |
323 | 0 | } |
324 | 0 | { |
325 | 0 | char *c_name = MVM_string_utf8_encode_C_string(tc, name); |
326 | 0 | char *waste[] = { c_name, NULL }; |
327 | 0 | MVM_exception_throw_adhoc_free(tc, waste, "No lexical found with name '%s'", |
328 | 0 | c_name); |
329 | 0 | } |
330 | 0 | } |
331 | 0 | MVMObject * MVM_nativeref_lex_name_i(MVMThreadContext *tc, MVMString *name) { |
332 | 0 | MVMObject *ref_type; |
333 | 0 | MVMROOT(tc, name, { |
334 | 0 | MVM_frame_force_to_heap(tc, tc->cur_frame); |
335 | 0 | }); |
336 | 0 | ref_type = MVM_hll_current(tc)->int_lex_ref; |
337 | 0 | if (ref_type) |
338 | 0 | return lexref_by_name(tc, ref_type, name, MVM_reg_int64); |
339 | 0 | MVM_exception_throw_adhoc(tc, "No int lexical reference type registered for current HLL"); |
340 | 0 | } |
341 | 0 | MVMObject * MVM_nativeref_lex_name_n(MVMThreadContext *tc, MVMString *name) { |
342 | 0 | MVMObject *ref_type; |
343 | 0 | MVMROOT(tc, name, { |
344 | 0 | MVM_frame_force_to_heap(tc, tc->cur_frame); |
345 | 0 | }); |
346 | 0 | ref_type = MVM_hll_current(tc)->num_lex_ref; |
347 | 0 | if (ref_type) |
348 | 0 | return lexref_by_name(tc, ref_type, name, MVM_reg_num64); |
349 | 0 | MVM_exception_throw_adhoc(tc, "No num lexical reference type registered for current HLL"); |
350 | 0 | } |
351 | 0 | MVMObject * MVM_nativeref_lex_name_s(MVMThreadContext *tc, MVMString *name) { |
352 | 0 | MVMObject *ref_type; |
353 | 0 | MVMROOT(tc, name, { |
354 | 0 | MVM_frame_force_to_heap(tc, tc->cur_frame); |
355 | 0 | }); |
356 | 0 | ref_type = MVM_hll_current(tc)->str_lex_ref; |
357 | 0 | if (ref_type) |
358 | 0 | return lexref_by_name(tc, ref_type, name, MVM_reg_str); |
359 | 0 | MVM_exception_throw_adhoc(tc, "No str lexical reference type registered for current HLL"); |
360 | 0 | } |
361 | | |
362 | | /* Creation of native references for attributes. */ |
363 | 6 | static MVMObject * attrref(MVMThreadContext *tc, MVMObject *type, MVMObject *obj, MVMObject *class_handle, MVMString *name) { |
364 | 6 | MVMNativeRef *ref; |
365 | 6 | MVMROOT(tc, obj, { |
366 | 6 | MVMROOT(tc, class_handle, { |
367 | 6 | MVMROOT(tc, name, { |
368 | 6 | ref = (MVMNativeRef *)MVM_gc_allocate_object(tc, STABLE(type)); |
369 | 6 | MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.attribute.obj, obj); |
370 | 6 | MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.attribute.class_handle, class_handle); |
371 | 6 | MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.attribute.name, name); |
372 | 6 | }); |
373 | 6 | }); |
374 | 6 | }); |
375 | 6 | return (MVMObject *)ref; |
376 | 6 | } |
377 | 2 | MVMObject * MVM_nativeref_attr_i(MVMThreadContext *tc, MVMObject *obj, MVMObject *class_handle, MVMString *name) { |
378 | 2 | MVMObject *ref_type = MVM_hll_current(tc)->int_attr_ref; |
379 | 2 | if (ref_type) |
380 | 2 | return attrref(tc, ref_type, obj, class_handle, name); |
381 | 0 | MVM_exception_throw_adhoc(tc, "No int attribute reference type registered for current HLL"); |
382 | 0 | } |
383 | 2 | MVMObject * MVM_nativeref_attr_n(MVMThreadContext *tc, MVMObject *obj, MVMObject *class_handle, MVMString *name) { |
384 | 2 | MVMObject *ref_type = MVM_hll_current(tc)->num_attr_ref; |
385 | 2 | if (ref_type) |
386 | 2 | return attrref(tc, ref_type, obj, class_handle, name); |
387 | 0 | MVM_exception_throw_adhoc(tc, "No num attribute reference type registered for current HLL"); |
388 | 0 | } |
389 | 2 | MVMObject * MVM_nativeref_attr_s(MVMThreadContext *tc, MVMObject *obj, MVMObject *class_handle, MVMString *name) { |
390 | 2 | MVMObject *ref_type = MVM_hll_current(tc)->str_attr_ref; |
391 | 2 | if (ref_type) |
392 | 2 | return attrref(tc, ref_type, obj, class_handle, name); |
393 | 0 | MVM_exception_throw_adhoc(tc, "No str attribute reference type registered for current HLL"); |
394 | 0 | } |
395 | | |
396 | | /* Creation of native references for positionals. */ |
397 | 3 | static MVMObject * posref(MVMThreadContext *tc, MVMObject *type, MVMObject *obj, MVMint64 idx) { |
398 | 3 | MVMNativeRef *ref; |
399 | 3 | MVMROOT(tc, obj, { |
400 | 3 | ref = (MVMNativeRef *)MVM_gc_allocate_object(tc, STABLE(type)); |
401 | 3 | MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.positional.obj, obj); |
402 | 3 | ref->body.u.positional.idx = idx; |
403 | 3 | }); |
404 | 3 | return (MVMObject *)ref; |
405 | 3 | } |
406 | 1 | MVMObject * MVM_nativeref_pos_i(MVMThreadContext *tc, MVMObject *obj, MVMint64 idx) { |
407 | 1 | MVMObject *ref_type = MVM_hll_current(tc)->int_pos_ref; |
408 | 1 | if (ref_type) |
409 | 1 | return posref(tc, ref_type, obj, idx); |
410 | 0 | MVM_exception_throw_adhoc(tc, "No int positional reference type registered for current HLL"); |
411 | 0 | } |
412 | 1 | MVMObject * MVM_nativeref_pos_n(MVMThreadContext *tc, MVMObject *obj, MVMint64 idx) { |
413 | 1 | MVMObject *ref_type = MVM_hll_current(tc)->num_pos_ref; |
414 | 1 | if (ref_type) |
415 | 1 | return posref(tc, ref_type, obj, idx); |
416 | 0 | MVM_exception_throw_adhoc(tc, "No num positional reference type registered for current HLL"); |
417 | 0 | } |
418 | 1 | MVMObject * MVM_nativeref_pos_s(MVMThreadContext *tc, MVMObject *obj, MVMint64 idx) { |
419 | 1 | MVMObject *ref_type = MVM_hll_current(tc)->str_pos_ref; |
420 | 1 | if (ref_type) |
421 | 1 | return posref(tc, ref_type, obj, idx); |
422 | 0 | MVM_exception_throw_adhoc(tc, "No str positional reference type registered for current HLL"); |
423 | 0 | } |
424 | | |
425 | | /* Creation of native references for multi-dimensional positionals. */ |
426 | 0 | static MVMObject * md_posref(MVMThreadContext *tc, MVMObject *type, MVMObject *obj, MVMObject *indices) { |
427 | 0 | MVMNativeRef *ref; |
428 | 0 | MVMROOT(tc, obj, { |
429 | 0 | MVMROOT(tc, indices, { |
430 | 0 | ref = (MVMNativeRef *)MVM_gc_allocate_object(tc, STABLE(type)); |
431 | 0 | MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.multidim.obj, obj); |
432 | 0 | MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.multidim.indices, indices); |
433 | 0 | }); |
434 | 0 | }); |
435 | 0 | return (MVMObject *)ref; |
436 | 0 | } |
437 | 0 | MVMObject * MVM_nativeref_multidim_i(MVMThreadContext *tc, MVMObject *obj, MVMObject *indices) { |
438 | 0 | MVMObject *ref_type = MVM_hll_current(tc)->int_multidim_ref; |
439 | 0 | if (ref_type) |
440 | 0 | return md_posref(tc, ref_type, obj, indices); |
441 | 0 | MVM_exception_throw_adhoc(tc, "No int multidim positional reference type registered for current HLL"); |
442 | 0 | } |
443 | 0 | MVMObject * MVM_nativeref_multidim_n(MVMThreadContext *tc, MVMObject *obj, MVMObject *indices) { |
444 | 0 | MVMObject *ref_type = MVM_hll_current(tc)->num_multidim_ref; |
445 | 0 | if (ref_type) |
446 | 0 | return md_posref(tc, ref_type, obj, indices); |
447 | 0 | MVM_exception_throw_adhoc(tc, "No num multidim positional reference type registered for current HLL"); |
448 | 0 | } |
449 | 0 | MVMObject * MVM_nativeref_multidim_s(MVMThreadContext *tc, MVMObject *obj, MVMObject *indices) { |
450 | 0 | MVMObject *ref_type = MVM_hll_current(tc)->str_multidim_ref; |
451 | 0 | if (ref_type) |
452 | 0 | return md_posref(tc, ref_type, obj, indices); |
453 | 0 | MVM_exception_throw_adhoc(tc, "No str multidim positional reference type registered for current HLL"); |
454 | 0 | } |
455 | | |
456 | | /* Reference read functions. These do no checks that the reference is of the |
457 | | * right kind and primitive type, they just go ahead and do the read. Thus |
458 | | * they are more suited to calling from optimized code. The checking path is |
459 | | * in the native ref container implementation, in containers.c; after checks, |
460 | | * they delegate here. */ |
461 | 5 | MVMint64 MVM_nativeref_read_lex_i(MVMThreadContext *tc, MVMObject *ref_obj) { |
462 | 5 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
463 | 5 | switch (ref->body.u.lex.type) { |
464 | 0 | case MVM_reg_int8: |
465 | 0 | return ref->body.u.lex.var->i8; |
466 | 0 | case MVM_reg_int16: |
467 | 0 | return ref->body.u.lex.var->i16; |
468 | 0 | case MVM_reg_int32: |
469 | 0 | return ref->body.u.lex.var->i32; |
470 | 5 | default: |
471 | 5 | return ref->body.u.lex.var->i64; |
472 | 5 | } |
473 | 5 | } |
474 | 5 | MVMnum64 MVM_nativeref_read_lex_n(MVMThreadContext *tc, MVMObject *ref_obj) { |
475 | 5 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
476 | 5 | switch (ref->body.u.lex.type) { |
477 | 0 | case MVM_reg_num32: |
478 | 0 | return ref->body.u.lex.var->n32; |
479 | 5 | default: |
480 | 5 | return ref->body.u.lex.var->n64; |
481 | 5 | } |
482 | 5 | } |
483 | 5 | MVMString * MVM_nativeref_read_lex_s(MVMThreadContext *tc, MVMObject *ref_obj) { |
484 | 5 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
485 | 5 | return ref->body.u.lex.var->s; |
486 | 5 | } |
487 | 1 | MVMint64 MVM_nativeref_read_attribute_i(MVMThreadContext *tc, MVMObject *ref_obj) { |
488 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
489 | 1 | return MVM_repr_get_attr_i(tc, ref->body.u.attribute.obj, |
490 | 1 | ref->body.u.attribute.class_handle, ref->body.u.attribute.name, MVM_NO_HINT); |
491 | 1 | } |
492 | 1 | MVMnum64 MVM_nativeref_read_attribute_n(MVMThreadContext *tc, MVMObject *ref_obj) { |
493 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
494 | 1 | return MVM_repr_get_attr_n(tc, ref->body.u.attribute.obj, |
495 | 1 | ref->body.u.attribute.class_handle, ref->body.u.attribute.name, MVM_NO_HINT); |
496 | 1 | } |
497 | 1 | MVMString * MVM_nativeref_read_attribute_s(MVMThreadContext *tc, MVMObject *ref_obj) { |
498 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
499 | 1 | return MVM_repr_get_attr_s(tc, ref->body.u.attribute.obj, |
500 | 1 | ref->body.u.attribute.class_handle, ref->body.u.attribute.name, MVM_NO_HINT); |
501 | 1 | } |
502 | 1 | MVMint64 MVM_nativeref_read_positional_i(MVMThreadContext *tc, MVMObject *ref_obj) { |
503 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
504 | 1 | return MVM_repr_at_pos_i(tc, ref->body.u.positional.obj, ref->body.u.positional.idx); |
505 | 1 | } |
506 | 1 | MVMnum64 MVM_nativeref_read_positional_n(MVMThreadContext *tc, MVMObject *ref_obj) { |
507 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
508 | 1 | return MVM_repr_at_pos_n(tc, ref->body.u.positional.obj, ref->body.u.positional.idx); |
509 | 1 | } |
510 | 1 | MVMString * MVM_nativeref_read_positional_s(MVMThreadContext *tc, MVMObject *ref_obj) { |
511 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
512 | 1 | return MVM_repr_at_pos_s(tc, ref->body.u.positional.obj, ref->body.u.positional.idx); |
513 | 1 | } |
514 | 0 | MVMint64 MVM_nativeref_read_multidim_i(MVMThreadContext *tc, MVMObject *ref_obj) { |
515 | 0 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
516 | 0 | return MVM_repr_at_pos_multidim_i(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices); |
517 | 0 | } |
518 | 0 | MVMnum64 MVM_nativeref_read_multidim_n(MVMThreadContext *tc, MVMObject *ref_obj) { |
519 | 0 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
520 | 0 | return MVM_repr_at_pos_multidim_n(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices); |
521 | 0 | } |
522 | 0 | MVMString * MVM_nativeref_read_multidim_s(MVMThreadContext *tc, MVMObject *ref_obj) { |
523 | 0 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
524 | 0 | return MVM_repr_at_pos_multidim_s(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices); |
525 | 0 | } |
526 | | |
527 | | /* Reference write functions. Same (non-checking) rules as the reads above. */ |
528 | 2 | void MVM_nativeref_write_lex_i(MVMThreadContext *tc, MVMObject *ref_obj, MVMint64 value) { |
529 | 2 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
530 | 2 | switch (ref->body.u.lex.type) { |
531 | 0 | case MVM_reg_int8: |
532 | 0 | ref->body.u.lex.var->i8 = (MVMint8)value; |
533 | 0 | break; |
534 | 0 | case MVM_reg_int16: |
535 | 0 | ref->body.u.lex.var->i16 = (MVMint16)value; |
536 | 0 | break; |
537 | 0 | case MVM_reg_int32: |
538 | 0 | ref->body.u.lex.var->i32 = (MVMint32)value; |
539 | 0 | break; |
540 | 2 | default: |
541 | 2 | ref->body.u.lex.var->i64 = value; |
542 | 2 | break; |
543 | 2 | } |
544 | 2 | } |
545 | 2 | void MVM_nativeref_write_lex_n(MVMThreadContext *tc, MVMObject *ref_obj, MVMnum64 value) { |
546 | 2 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
547 | 2 | switch (ref->body.u.lex.type) { |
548 | 0 | case MVM_reg_num32: |
549 | 0 | ref->body.u.lex.var->n32 = (MVMnum32)value; |
550 | 0 | break; |
551 | 2 | default: |
552 | 2 | ref->body.u.lex.var->n64 = value; |
553 | 2 | break; |
554 | 2 | } |
555 | 2 | } |
556 | 2 | void MVM_nativeref_write_lex_s(MVMThreadContext *tc, MVMObject *ref_obj, MVMString *value) { |
557 | 2 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
558 | 2 | MVM_ASSIGN_REF(tc, &(ref->body.u.lex.frame->header), |
559 | 2 | ref->body.u.lex.var->s, value); |
560 | 2 | } |
561 | 2 | void MVM_nativeref_write_attribute_i(MVMThreadContext *tc, MVMObject *ref_obj, MVMint64 value) { |
562 | 2 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
563 | 2 | MVMRegister r; |
564 | 2 | r.i64 = value; |
565 | 2 | MVM_repr_bind_attr_inso(tc, ref->body.u.attribute.obj, ref->body.u.attribute.class_handle, |
566 | 2 | ref->body.u.attribute.name, MVM_NO_HINT, r, MVM_reg_int64); |
567 | 2 | } |
568 | 2 | void MVM_nativeref_write_attribute_n(MVMThreadContext *tc, MVMObject *ref_obj, MVMnum64 value) { |
569 | 2 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
570 | 2 | MVMRegister r; |
571 | 2 | r.n64 = value; |
572 | 2 | MVM_repr_bind_attr_inso(tc, ref->body.u.attribute.obj, ref->body.u.attribute.class_handle, |
573 | 2 | ref->body.u.attribute.name, MVM_NO_HINT, r, MVM_reg_num64); |
574 | 2 | } |
575 | 2 | void MVM_nativeref_write_attribute_s(MVMThreadContext *tc, MVMObject *ref_obj, MVMString *value) { |
576 | 2 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
577 | 2 | MVMRegister r; |
578 | 2 | r.s = value; |
579 | 2 | MVM_repr_bind_attr_inso(tc, ref->body.u.attribute.obj, ref->body.u.attribute.class_handle, |
580 | 2 | ref->body.u.attribute.name, MVM_NO_HINT, r, MVM_reg_str); |
581 | 2 | } |
582 | 1 | void MVM_nativeref_write_positional_i(MVMThreadContext *tc, MVMObject *ref_obj, MVMint64 value) { |
583 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
584 | 1 | MVM_repr_bind_pos_i(tc, ref->body.u.positional.obj, ref->body.u.positional.idx, value); |
585 | 1 | } |
586 | 1 | void MVM_nativeref_write_positional_n(MVMThreadContext *tc, MVMObject *ref_obj, MVMnum64 value) { |
587 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
588 | 1 | MVM_repr_bind_pos_n(tc, ref->body.u.positional.obj, ref->body.u.positional.idx, value); |
589 | 1 | } |
590 | 1 | void MVM_nativeref_write_positional_s(MVMThreadContext *tc, MVMObject *ref_obj, MVMString *value) { |
591 | 1 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
592 | 1 | MVM_repr_bind_pos_s(tc, ref->body.u.positional.obj, ref->body.u.positional.idx, value); |
593 | 1 | } |
594 | | |
595 | 0 | void MVM_nativeref_write_multidim_i(MVMThreadContext *tc, MVMObject *ref_obj, MVMint64 value) { |
596 | 0 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
597 | 0 | MVM_repr_bind_pos_multidim_i(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices, value); |
598 | 0 | } |
599 | 0 | void MVM_nativeref_write_multidim_n(MVMThreadContext *tc, MVMObject *ref_obj, MVMnum64 value) { |
600 | 0 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
601 | 0 | MVM_repr_bind_pos_multidim_n(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices, value); |
602 | 0 | } |
603 | 0 | void MVM_nativeref_write_multidim_s(MVMThreadContext *tc, MVMObject *ref_obj, MVMString *value) { |
604 | 0 | MVMNativeRef *ref = (MVMNativeRef *)ref_obj; |
605 | 0 | MVM_repr_bind_pos_multidim_s(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices, value); |
606 | 0 | } |