Coverage Report

Created: 2018-07-03 15:31

/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
19
static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) {
9
19
    MVMSTable *st  = MVM_gc_allocate_stable(tc, &NativeRef_this_repr, HOW);
10
19
11
19
    MVMROOT(tc, st, {
12
19
        MVMObject *obj = MVM_gc_allocate_type_object(tc, st);
13
19
        MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj);
14
19
        st->size = sizeof(MVMNativeRef);
15
19
    });
16
19
17
19
    return st->WHAT;
18
19
}
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
19
static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info_hash) {
94
19
    MVMStringConsts *str_consts = &(tc->instance->str_consts);
95
19
    MVMObject *info = MVM_repr_at_key_o(tc, info_hash, str_consts->nativeref);
96
19
    if (IS_CONCRETE(info)) {
97
19
        MVMObject *type    = MVM_repr_at_key_o(tc, info, str_consts->type);
98
19
        MVMuint16  prim    = REPR(type)->get_storage_spec(tc, STABLE(type))->boxed_primitive;
99
19
        if (prim != MVM_STORAGE_SPEC_BP_NONE) {
100
19
            MVMObject *refkind = MVM_repr_at_key_o(tc, info, str_consts->refkind);
101
19
            if (IS_CONCRETE(refkind)) {
102
19
                MVMNativeRefREPRData *repr_data;
103
19
                MVMuint16 kind;
104
19
                MVMString *refkind_s = MVM_repr_get_str(tc, refkind);
105
19
                if (MVM_string_equal(tc, refkind_s, str_consts->lexical)) {
106
7
                    kind = MVM_NATIVEREF_LEX;
107
7
                }
108
12
                else if (MVM_string_equal(tc, refkind_s, str_consts->attribute)) {
109
6
                    kind = MVM_NATIVEREF_ATTRIBUTE;
110
6
                }
111
6
                else if (MVM_string_equal(tc, refkind_s, str_consts->positional)) {
112
3
                    kind = MVM_NATIVEREF_POSITIONAL;
113
3
                }
114
3
                else if (MVM_string_equal(tc, refkind_s, str_consts->multidim)) {
115
3
                    kind = MVM_NATIVEREF_MULTIDIM;
116
3
                }
117
0
                else {
118
0
                    MVM_exception_throw_adhoc(tc, "NativeRef: invalid refkind in compose");
119
0
                }
120
19
121
19
                repr_data = MVM_malloc(sizeof(MVMNativeRefREPRData));
122
19
                repr_data->primitive_type = prim;
123
19
                repr_data->ref_kind       = kind;
124
19
                st->REPR_data             = repr_data;
125
19
            }
126
0
            else {
127
0
                MVM_exception_throw_adhoc(tc, "NativeRef: missing refkind in compose");
128
0
            }
129
19
        }
130
0
        else {
131
0
            MVM_exception_throw_adhoc(tc, "NativeRef: non-native type supplied in compose");
132
0
        }
133
19
    }
134
0
    else {
135
0
        MVM_exception_throw_adhoc(tc, "NativeRef: missing nativeref protocol in compose");
136
0
    }
137
19
}
138
139
/* Initializes the representation. */
140
144
const MVMREPROps * MVMNativeRef_initialize(MVMThreadContext *tc) {
141
144
    return &NativeRef_this_repr;
142
144
}
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
    /* TODO re-implement spesh for this; lost due to native ref refactors */
151
0
}
152
153
static const MVMREPROps NativeRef_this_repr = {
154
    type_object_for,
155
    MVM_gc_allocate_object,
156
    NULL, /* initialize */
157
    copy_to,
158
    MVM_REPR_DEFAULT_ATTR_FUNCS,
159
    MVM_REPR_DEFAULT_BOX_FUNCS,
160
    MVM_REPR_DEFAULT_POS_FUNCS,
161
    MVM_REPR_DEFAULT_ASS_FUNCS,
162
    MVM_REPR_DEFAULT_ELEMS,
163
    get_storage_spec,
164
    NULL, /* change_type */
165
    NULL, /* serialize */
166
    NULL, /* deserialize */
167
    serialize_repr_data,
168
    deserialize_repr_data,
169
    deserialize_stable_size,
170
    gc_mark,
171
    NULL, /* gc_free */
172
    NULL, /* gc_cleanup */
173
    NULL, /* gc_mark_repr_data */
174
    gc_free_repr_data,
175
    compose,
176
    spesh, /* spesh */
177
    "NativeRef", /* name */
178
    MVM_REPR_ID_NativeRef,
179
    NULL, /* unmanaged_size */
180
    NULL, /* describe_refs */
181
};
182
183
/* Validates the given type is a native reference of the required primitive
184
 * type and reference kind. */
185
19
void MVM_nativeref_ensure(MVMThreadContext *tc, MVMObject *type, MVMuint16 wantprim, MVMuint16 wantkind, char *guilty) {
186
19
    if (REPR(type)->ID == MVM_REPR_ID_NativeRef) {
187
19
        MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(type)->REPR_data;
188
19
        if (!repr_data)
189
0
            MVM_exception_throw_adhoc(tc, "%s set to NativeRef that is not yet composed", guilty);
190
19
        if (repr_data->primitive_type != wantprim)
191
0
            MVM_exception_throw_adhoc(tc, "%s set to NativeRef of wrong primitive type", guilty);
192
19
        if (repr_data->ref_kind != wantkind)
193
0
            MVM_exception_throw_adhoc(tc, "%s set to NativeRef of wrong reference kind", guilty);
194
19
    }
195
0
    else {
196
0
        MVM_exception_throw_adhoc(tc, "%s requires a type with REPR NativeRef", guilty);
197
0
    }
198
19
}
199
200
/* Creation of native references for lexicals. */
201
static MVMObject * lex_ref(MVMThreadContext *tc, MVMObject *type, MVMFrame *f,
202
15
                           MVMuint16 env_idx, MVMuint16 reg_type) {
203
15
    MVMNativeRef *ref;
204
15
    MVMROOT(tc, f, {
205
15
        ref = (MVMNativeRef *)MVM_gc_allocate_object(tc, STABLE(type));
206
15
    });
207
15
    MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.lex.frame, f);
208
15
    ref->body.u.lex.env_idx = env_idx;
209
15
    ref->body.u.lex.type = reg_type;
210
15
    return (MVMObject *)ref;
211
15
}
212
213
/* Creation of native references for lexicals. */
214
15
static MVMFrame * get_lexical_outer(MVMThreadContext *tc, MVMuint16 outers) {
215
15
    MVMFrame *f = tc->cur_frame;
216
15
    while (outers) {
217
0
        if (!f)
218
0
            MVM_exception_throw_adhoc(tc, "getlexref_*: outer index out of range");
219
0
        f = f->outer;
220
0
        outers--;
221
0
    }
222
15
    return f;
223
15
}
224
5
MVMObject * MVM_nativeref_lex_i(MVMThreadContext *tc, MVMuint16 outers, MVMuint16 idx) {
225
5
    MVMObject *ref_type;
226
5
    MVM_frame_force_to_heap(tc, tc->cur_frame);
227
5
    ref_type = MVM_hll_current(tc)->int_lex_ref;
228
5
    if (ref_type) {
229
5
        MVMFrame  *f = get_lexical_outer(tc, outers);
230
0
        MVMuint16 *lexical_types = f->spesh_cand && f->spesh_cand->lexical_types
231
0
            ? f->spesh_cand->lexical_types
232
5
            : f->static_info->body.lexical_types;
233
5
        MVMuint16 type = lexical_types[idx];
234
5
        if (type != MVM_reg_int64 && type != MVM_reg_int32 &&
235
0
                type != MVM_reg_int16 && type != MVM_reg_int8 &&
236
0
                type != MVM_reg_uint64 && type != MVM_reg_uint32 &&
237
0
                type != MVM_reg_uint16 && type != MVM_reg_uint8)
238
0
            MVM_exception_throw_adhoc(tc, "getlexref_i: lexical is not an int");
239
5
        return lex_ref(tc, ref_type, f, idx, type);
240
5
    }
241
0
    MVM_exception_throw_adhoc(tc, "No int lexical reference type registered for current HLL");
242
0
}
243
5
MVMObject * MVM_nativeref_lex_n(MVMThreadContext *tc, MVMuint16 outers, MVMuint16 idx) {
244
5
    MVMObject *ref_type;
245
5
    MVM_frame_force_to_heap(tc, tc->cur_frame);
246
5
    ref_type = MVM_hll_current(tc)->num_lex_ref;
247
5
    if (ref_type) {
248
5
        MVMFrame  *f = get_lexical_outer(tc, outers);
249
0
        MVMuint16 *lexical_types = f->spesh_cand && f->spesh_cand->lexical_types
250
0
            ? f->spesh_cand->lexical_types
251
5
            : f->static_info->body.lexical_types;
252
5
        MVMuint16 type = lexical_types[idx];
253
5
        if (type != MVM_reg_num64 && type != MVM_reg_num32)
254
0
            MVM_exception_throw_adhoc(tc, "getlexref_n: lexical is not a num");
255
5
        return lex_ref(tc, ref_type, f, idx, type);
256
5
    }
257
0
    MVM_exception_throw_adhoc(tc, "No num lexical reference type registered for current HLL");
258
0
}
259
5
MVMObject * MVM_nativeref_lex_s(MVMThreadContext *tc, MVMuint16 outers, MVMuint16 idx) {
260
5
    MVMObject *ref_type;
261
5
    MVM_frame_force_to_heap(tc, tc->cur_frame);
262
5
    ref_type = MVM_hll_current(tc)->str_lex_ref;
263
5
    if (ref_type) {
264
5
        MVMFrame  *f = get_lexical_outer(tc, outers);
265
0
        MVMuint16 *lexical_types = f->spesh_cand && f->spesh_cand->lexical_types
266
0
            ? f->spesh_cand->lexical_types
267
5
            : f->static_info->body.lexical_types;
268
5
        if (lexical_types[idx] != MVM_reg_str)
269
0
            MVM_exception_throw_adhoc(tc, "getlexref_s: lexical is not a str (%d, %d)", outers, idx);
270
5
        return lex_ref(tc, ref_type, f, idx, MVM_reg_str);
271
5
    }
272
0
    MVM_exception_throw_adhoc(tc, "No str lexical reference type registered for current HLL");
273
0
}
274
0
#define LEXREF_ANY_INT -1
275
0
static MVMObject * lexref_by_name(MVMThreadContext *tc, MVMObject *type, MVMString *name, MVMint16 kind) {
276
0
    MVMFrame *cur_frame = tc->cur_frame;
277
0
    while (cur_frame != NULL) {
278
0
        MVMLexicalRegistry *lexical_names = cur_frame->static_info->body.lexical_names;
279
0
        if (lexical_names) {
280
0
            MVMLexicalRegistry *entry;
281
0
            MVM_HASH_GET(tc, lexical_names, name, entry)
282
0
            if (entry) {
283
0
                MVMint16 lex_kind = cur_frame->static_info->body.lexical_types[entry->value];
284
0
                if (lex_kind == kind) {
285
0
                    return lex_ref(tc, type, cur_frame, entry->value, kind);
286
0
                }
287
0
                /* If kind == LEXREF_ANY_INT we will allow any of the native int
288
0
                 * types so we don't need functions for every single type. */
289
0
                else if (kind == LEXREF_ANY_INT) {
290
0
                    switch (lex_kind) {
291
0
                        case MVM_reg_int8:
292
0
                        case MVM_reg_int16:
293
0
                        case MVM_reg_int32:
294
0
                        case MVM_reg_int64:
295
0
                        case MVM_reg_uint8:
296
0
                        case MVM_reg_uint16:
297
0
                        case MVM_reg_uint32:
298
0
                        case MVM_reg_uint64:
299
0
                            return lex_ref(tc, type, cur_frame, entry->value, lex_kind);
300
0
                    }
301
0
                }
302
0
                {
303
0
                    char *c_name = MVM_string_utf8_encode_C_string(tc, name);
304
0
                    char *waste[] = { c_name, NULL };
305
0
                    MVM_exception_throw_adhoc_free(tc, waste,
306
0
                        "Lexical with name '%s' has wrong type. real type %i wanted type %i",
307
0
                            c_name, cur_frame->static_info->body.lexical_types[entry->value], kind);
308
0
                }
309
0
            }
310
0
        }
311
0
        cur_frame = cur_frame->outer;
312
0
    }
313
0
    {
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, "No lexical found with name '%s'",
317
0
            c_name);
318
0
    }
319
0
}
320
0
MVMObject * MVM_nativeref_lex_name_i(MVMThreadContext *tc, MVMString *name) {
321
0
    MVMObject *ref_type;
322
0
    MVMROOT(tc, name, {
323
0
        MVM_frame_force_to_heap(tc, tc->cur_frame);
324
0
    });
325
0
    ref_type = MVM_hll_current(tc)->int_lex_ref;
326
0
    if (ref_type)
327
0
        /* LEXREF_ANY_INT will allow int8..int64 as well as uint8..uint64 */
328
0
        return lexref_by_name(tc, ref_type, name, LEXREF_ANY_INT);
329
0
    MVM_exception_throw_adhoc(tc, "No int lexical reference type registered for current HLL");
330
0
}
331
0
MVMObject * MVM_nativeref_lex_name_n(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)->num_lex_ref;
337
0
    if (ref_type)
338
0
        return lexref_by_name(tc, ref_type, name, MVM_reg_num64);
339
0
    MVM_exception_throw_adhoc(tc, "No num lexical reference type registered for current HLL");
340
0
}
341
0
MVMObject * MVM_nativeref_lex_name_s(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)->str_lex_ref;
347
0
    if (ref_type)
348
0
        return lexref_by_name(tc, ref_type, name, MVM_reg_str);
349
0
    MVM_exception_throw_adhoc(tc, "No str lexical reference type registered for current HLL");
350
0
}
351
352
/* Creation of native references for attributes. */
353
7
static MVMObject * attrref(MVMThreadContext *tc, MVMObject *type, MVMObject *obj, MVMObject *class_handle, MVMString *name) {
354
7
    MVMNativeRef *ref;
355
7
    MVMROOT3(tc, obj, class_handle, name, {
356
7
        ref = (MVMNativeRef *)MVM_gc_allocate_object(tc, STABLE(type));
357
7
        MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.attribute.obj, obj);
358
7
        MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.attribute.class_handle, class_handle);
359
7
        MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.attribute.name, name);
360
7
    });
361
7
    return (MVMObject *)ref;
362
7
}
363
3
MVMObject * MVM_nativeref_attr_i(MVMThreadContext *tc, MVMObject *obj, MVMObject *class_handle, MVMString *name) {
364
3
    MVMObject *ref_type = MVM_hll_current(tc)->int_attr_ref;
365
3
    if (ref_type)
366
3
        return attrref(tc, ref_type, obj, class_handle, name);
367
0
    MVM_exception_throw_adhoc(tc, "No int attribute reference type registered for current HLL");
368
0
}
369
2
MVMObject * MVM_nativeref_attr_n(MVMThreadContext *tc, MVMObject *obj, MVMObject *class_handle, MVMString *name) {
370
2
    MVMObject *ref_type = MVM_hll_current(tc)->num_attr_ref;
371
2
    if (ref_type)
372
2
        return attrref(tc, ref_type, obj, class_handle, name);
373
0
    MVM_exception_throw_adhoc(tc, "No num attribute reference type registered for current HLL");
374
0
}
375
2
MVMObject * MVM_nativeref_attr_s(MVMThreadContext *tc, MVMObject *obj, MVMObject *class_handle, MVMString *name) {
376
2
    MVMObject *ref_type = MVM_hll_current(tc)->str_attr_ref;
377
2
    if (ref_type)
378
2
        return attrref(tc, ref_type, obj, class_handle, name);
379
0
    MVM_exception_throw_adhoc(tc, "No str attribute reference type registered for current HLL");
380
0
}
381
382
/* Creation of native references for positionals. */
383
3
static MVMObject * posref(MVMThreadContext *tc, MVMObject *type, MVMObject *obj, MVMint64 idx) {
384
3
    MVMNativeRef *ref;
385
3
    MVMROOT(tc, obj, {
386
3
        ref = (MVMNativeRef *)MVM_gc_allocate_object(tc, STABLE(type));
387
3
        MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.positional.obj, obj);
388
3
        ref->body.u.positional.idx = idx;
389
3
    });
390
3
    return (MVMObject *)ref;
391
3
}
392
1
MVMObject * MVM_nativeref_pos_i(MVMThreadContext *tc, MVMObject *obj, MVMint64 idx) {
393
1
    MVMObject *ref_type = MVM_hll_current(tc)->int_pos_ref;
394
1
    if (ref_type)
395
1
        return posref(tc, ref_type, obj, idx);
396
0
    MVM_exception_throw_adhoc(tc, "No int positional reference type registered for current HLL");
397
0
}
398
1
MVMObject * MVM_nativeref_pos_n(MVMThreadContext *tc, MVMObject *obj, MVMint64 idx) {
399
1
    MVMObject *ref_type = MVM_hll_current(tc)->num_pos_ref;
400
1
    if (ref_type)
401
1
        return posref(tc, ref_type, obj, idx);
402
0
    MVM_exception_throw_adhoc(tc, "No num positional reference type registered for current HLL");
403
0
}
404
1
MVMObject * MVM_nativeref_pos_s(MVMThreadContext *tc, MVMObject *obj, MVMint64 idx) {
405
1
    MVMObject *ref_type = MVM_hll_current(tc)->str_pos_ref;
406
1
    if (ref_type)
407
1
        return posref(tc, ref_type, obj, idx);
408
0
    MVM_exception_throw_adhoc(tc, "No str positional reference type registered for current HLL");
409
0
}
410
411
/* Creation of native references for multi-dimensional positionals. */
412
12
static MVMObject * md_posref(MVMThreadContext *tc, MVMObject *type, MVMObject *obj, MVMObject *indices) {
413
12
    MVMNativeRef *ref;
414
12
    MVMROOT2(tc, obj, indices, {
415
12
        ref = (MVMNativeRef *)MVM_gc_allocate_object(tc, STABLE(type));
416
12
        MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.multidim.obj, obj);
417
12
        MVM_ASSIGN_REF(tc, &(ref->common.header), ref->body.u.multidim.indices, indices);
418
12
    });
419
12
    return (MVMObject *)ref;
420
12
}
421
4
MVMObject * MVM_nativeref_multidim_i(MVMThreadContext *tc, MVMObject *obj, MVMObject *indices) {
422
4
    MVMObject *ref_type = MVM_hll_current(tc)->int_multidim_ref;
423
4
    if (ref_type)
424
4
        return md_posref(tc, ref_type, obj, indices);
425
0
    MVM_exception_throw_adhoc(tc, "No int multidim positional reference type registered for current HLL");
426
0
}
427
4
MVMObject * MVM_nativeref_multidim_n(MVMThreadContext *tc, MVMObject *obj, MVMObject *indices) {
428
4
    MVMObject *ref_type = MVM_hll_current(tc)->num_multidim_ref;
429
4
    if (ref_type)
430
4
        return md_posref(tc, ref_type, obj, indices);
431
0
    MVM_exception_throw_adhoc(tc, "No num multidim positional reference type registered for current HLL");
432
0
}
433
4
MVMObject * MVM_nativeref_multidim_s(MVMThreadContext *tc, MVMObject *obj, MVMObject *indices) {
434
4
    MVMObject *ref_type = MVM_hll_current(tc)->str_multidim_ref;
435
4
    if (ref_type)
436
4
        return md_posref(tc, ref_type, obj, indices);
437
0
    MVM_exception_throw_adhoc(tc, "No str multidim positional reference type registered for current HLL");
438
0
}
439
440
/* Reference read functions. These do no checks that the reference is of the
441
 * right kind and primitive type, they just go ahead and do the read. Thus
442
 * they are more suited to calling from optimized code. The checking path is
443
 * in the native ref container implementation, in containers.c; after checks,
444
 * they delegate here. */
445
5
MVMint64 MVM_nativeref_read_lex_i(MVMThreadContext *tc, MVMObject *ref_obj) {
446
5
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
447
5
    MVMRegister *var = &(ref->body.u.lex.frame->env[ref->body.u.lex.env_idx]);
448
5
    switch (ref->body.u.lex.type) {
449
0
        case MVM_reg_int8:
450
0
            return var->i8;
451
0
        case MVM_reg_int16:
452
0
            return var->i16;
453
0
        case MVM_reg_int32:
454
0
            return var->i32;
455
5
        default:
456
5
            return var->i64;
457
5
    }
458
5
}
459
5
MVMnum64 MVM_nativeref_read_lex_n(MVMThreadContext *tc, MVMObject *ref_obj) {
460
5
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
461
5
    MVMRegister *var = &(ref->body.u.lex.frame->env[ref->body.u.lex.env_idx]);
462
5
    switch (ref->body.u.lex.type) {
463
0
        case MVM_reg_num32:
464
0
            return var->n32;
465
5
        default:
466
5
            return var->n64;
467
5
    }
468
5
}
469
5
MVMString * MVM_nativeref_read_lex_s(MVMThreadContext *tc, MVMObject *ref_obj) {
470
5
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
471
5
    return ref->body.u.lex.frame->env[ref->body.u.lex.env_idx].s;
472
5
}
473
1
MVMint64 MVM_nativeref_read_attribute_i(MVMThreadContext *tc, MVMObject *ref_obj) {
474
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
475
1
    return MVM_repr_get_attr_i(tc, ref->body.u.attribute.obj,
476
1
        ref->body.u.attribute.class_handle, ref->body.u.attribute.name, MVM_NO_HINT);
477
1
}
478
1
MVMnum64 MVM_nativeref_read_attribute_n(MVMThreadContext *tc, MVMObject *ref_obj) {
479
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
480
1
    return MVM_repr_get_attr_n(tc, ref->body.u.attribute.obj,
481
1
        ref->body.u.attribute.class_handle, ref->body.u.attribute.name, MVM_NO_HINT);
482
1
}
483
1
MVMString * MVM_nativeref_read_attribute_s(MVMThreadContext *tc, MVMObject *ref_obj) {
484
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
485
1
    return MVM_repr_get_attr_s(tc, ref->body.u.attribute.obj,
486
1
        ref->body.u.attribute.class_handle, ref->body.u.attribute.name, MVM_NO_HINT);
487
1
}
488
1
MVMint64 MVM_nativeref_read_positional_i(MVMThreadContext *tc, MVMObject *ref_obj) {
489
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
490
1
    return MVM_repr_at_pos_i(tc, ref->body.u.positional.obj, ref->body.u.positional.idx);
491
1
}
492
1
MVMnum64 MVM_nativeref_read_positional_n(MVMThreadContext *tc, MVMObject *ref_obj) {
493
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
494
1
    return MVM_repr_at_pos_n(tc, ref->body.u.positional.obj, ref->body.u.positional.idx);
495
1
}
496
1
MVMString * MVM_nativeref_read_positional_s(MVMThreadContext *tc, MVMObject *ref_obj) {
497
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
498
1
    return MVM_repr_at_pos_s(tc, ref->body.u.positional.obj, ref->body.u.positional.idx);
499
1
}
500
2
MVMint64 MVM_nativeref_read_multidim_i(MVMThreadContext *tc, MVMObject *ref_obj) {
501
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
502
2
    return MVM_repr_at_pos_multidim_i(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices);
503
2
}
504
2
MVMnum64 MVM_nativeref_read_multidim_n(MVMThreadContext *tc, MVMObject *ref_obj) {
505
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
506
2
    return MVM_repr_at_pos_multidim_n(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices);
507
2
}
508
2
MVMString * MVM_nativeref_read_multidim_s(MVMThreadContext *tc, MVMObject *ref_obj) {
509
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
510
2
    return MVM_repr_at_pos_multidim_s(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices);
511
2
}
512
513
/* Reference write functions. Same (non-checking) rules as the reads above. */
514
2
void MVM_nativeref_write_lex_i(MVMThreadContext *tc, MVMObject *ref_obj, MVMint64 value) {
515
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
516
2
    MVMRegister *var = &(ref->body.u.lex.frame->env[ref->body.u.lex.env_idx]);
517
2
    switch (ref->body.u.lex.type) {
518
0
        case MVM_reg_int8:
519
0
            var->i8 = (MVMint8)value;
520
0
            break;
521
0
        case MVM_reg_int16:
522
0
            var->i16 = (MVMint16)value;
523
0
            break;
524
0
        case MVM_reg_int32:
525
0
            var->i32 = (MVMint32)value;
526
0
            break;
527
2
        default:
528
2
            var->i64 = value;
529
2
            break;
530
2
    }
531
2
}
532
2
void MVM_nativeref_write_lex_n(MVMThreadContext *tc, MVMObject *ref_obj, MVMnum64 value) {
533
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
534
2
    MVMRegister *var = &(ref->body.u.lex.frame->env[ref->body.u.lex.env_idx]);
535
2
    switch (ref->body.u.lex.type) {
536
0
        case MVM_reg_num32:
537
0
            var->n32 = (MVMnum32)value;
538
0
            break;
539
2
        default:
540
2
            var->n64 = value;
541
2
            break;
542
2
    }
543
2
}
544
2
void MVM_nativeref_write_lex_s(MVMThreadContext *tc, MVMObject *ref_obj, MVMString *value) {
545
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
546
2
    MVM_ASSIGN_REF(tc, &(ref->body.u.lex.frame->header),
547
2
        ref->body.u.lex.frame->env[ref->body.u.lex.env_idx].s, value);
548
2
}
549
4
void MVM_nativeref_write_attribute_i(MVMThreadContext *tc, MVMObject *ref_obj, MVMint64 value) {
550
4
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
551
4
    MVMRegister r;
552
4
    r.i64 = value;
553
4
    MVM_repr_bind_attr_inso(tc, ref->body.u.attribute.obj, ref->body.u.attribute.class_handle,
554
4
        ref->body.u.attribute.name, MVM_NO_HINT, r, MVM_reg_int64);
555
4
}
556
2
void MVM_nativeref_write_attribute_n(MVMThreadContext *tc, MVMObject *ref_obj, MVMnum64 value) {
557
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
558
2
    MVMRegister r;
559
2
    r.n64 = value;
560
2
    MVM_repr_bind_attr_inso(tc, ref->body.u.attribute.obj, ref->body.u.attribute.class_handle,
561
2
        ref->body.u.attribute.name, MVM_NO_HINT, r, MVM_reg_num64);
562
2
}
563
2
void MVM_nativeref_write_attribute_s(MVMThreadContext *tc, MVMObject *ref_obj, MVMString *value) {
564
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
565
2
    MVMRegister r;
566
2
    r.s = value;
567
2
    MVM_repr_bind_attr_inso(tc, ref->body.u.attribute.obj, ref->body.u.attribute.class_handle,
568
2
        ref->body.u.attribute.name, MVM_NO_HINT, r, MVM_reg_str);
569
2
}
570
1
void MVM_nativeref_write_positional_i(MVMThreadContext *tc, MVMObject *ref_obj, MVMint64 value) {
571
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
572
1
    MVM_repr_bind_pos_i(tc, ref->body.u.positional.obj, ref->body.u.positional.idx, value);
573
1
}
574
1
void MVM_nativeref_write_positional_n(MVMThreadContext *tc, MVMObject *ref_obj, MVMnum64 value) {
575
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
576
1
    MVM_repr_bind_pos_n(tc, ref->body.u.positional.obj, ref->body.u.positional.idx, value);
577
1
}
578
1
void MVM_nativeref_write_positional_s(MVMThreadContext *tc, MVMObject *ref_obj, MVMString *value) {
579
1
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
580
1
    MVM_repr_bind_pos_s(tc, ref->body.u.positional.obj, ref->body.u.positional.idx, value);
581
1
}
582
583
2
void MVM_nativeref_write_multidim_i(MVMThreadContext *tc, MVMObject *ref_obj, MVMint64 value) {
584
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
585
2
    MVM_repr_bind_pos_multidim_i(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices, value);
586
2
}
587
2
void MVM_nativeref_write_multidim_n(MVMThreadContext *tc, MVMObject *ref_obj, MVMnum64 value) {
588
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
589
2
    MVM_repr_bind_pos_multidim_n(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices, value);
590
2
}
591
2
void MVM_nativeref_write_multidim_s(MVMThreadContext *tc, MVMObject *ref_obj, MVMString *value) {
592
2
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
593
2
    MVM_repr_bind_pos_multidim_s(tc, ref->body.u.multidim.obj, ref->body.u.multidim.indices, value);
594
2
}
595
596
/* Functions to turn native integer references into an AO_t * that can be used
597
 * in an atomic operation. The reference *must* be used and discarded *before*
598
 * the next safepoint, after which it could become invalidated. */
599
0
AO_t * MVM_nativeref_as_atomic_lex_i(MVMThreadContext *tc, MVMObject *ref_obj) {
600
0
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
601
0
    MVMRegister *var = &(ref->body.u.lex.frame->env[ref->body.u.lex.env_idx]);
602
0
    if (sizeof(AO_t) == 8 && ref->body.u.lex.type == MVM_reg_int64)
603
0
        return (AO_t *)&(var->i64);
604
0
    if (sizeof(AO_t) == 4 && ref->body.u.lex.type == MVM_reg_int32)
605
0
        return (AO_t *)&(var->i32);
606
0
    MVM_exception_throw_adhoc(tc,
607
0
        "Cannot atomic load from an integer lexical not of the machine's native size");
608
0
}
609
0
AO_t * MVM_nativeref_as_atomic_attribute_i(MVMThreadContext *tc, MVMObject *ref_obj) {
610
0
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
611
0
    MVMObject *obj = ref->body.u.attribute.obj;
612
0
    return REPR(obj)->attr_funcs.attribute_as_atomic(tc, STABLE(obj), OBJECT_BODY(obj),
613
0
        ref->body.u.attribute.class_handle, ref->body.u.attribute.name, MVM_reg_int64);
614
0
}
615
0
AO_t * MVM_nativeref_as_atomic_positional_i(MVMThreadContext *tc, MVMObject *ref_obj) {
616
0
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
617
0
    MVMObject *obj = ref->body.u.positional.obj;
618
0
    return REPR(obj)->pos_funcs.pos_as_atomic(tc, STABLE(obj), obj, OBJECT_BODY(obj),
619
0
        ref->body.u.positional.idx);
620
0
}
621
0
AO_t * MVM_nativeref_as_atomic_multidim_i(MVMThreadContext *tc, MVMObject *ref_obj) {
622
0
    MVMNativeRef *ref = (MVMNativeRef *)ref_obj;
623
0
    MVMObject *obj = ref->body.u.multidim.obj;
624
0
    MVMint64 num_indices;
625
0
    MVM_repr_populate_indices_array(tc, ref->body.u.multidim.indices, &num_indices);
626
0
    return REPR(obj)->pos_funcs.pos_as_atomic_multidim(tc, STABLE(obj), obj, OBJECT_BODY(obj),
627
0
        num_indices, tc->multi_dim_indices);
628
0
}