Coverage Report

Created: 2017-04-15 07:07

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