Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/6model/containers.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
0
MVMint64 MVM_6model_container_iscont_rw(MVMThreadContext *tc, MVMObject *cont) {
4
0
    if (cont && IS_CONCRETE(cont)) {
5
0
        const MVMContainerSpec *cs = STABLE(cont)->container_spec;
6
0
        if (cs && cs->can_store(tc, cont)) {
7
0
            return 1;
8
0
        }
9
0
    }
10
0
    return 0;
11
0
}
12
13
/* ***************************************************************************
14
 * CodePair container configuration: container with FETCH/STORE code refs
15
 * ***************************************************************************/
16
17
 typedef struct {
18
    MVMObject *fetch_code;
19
    MVMObject *store_code;
20
} CodePairContData;
21
22
15
static void code_pair_fetch_internal(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res, MVMReturnType res_type) {
23
15
    CodePairContData        *data = (CodePairContData *)STABLE(cont)->container_data;
24
15
    MVMObject               *code = MVM_frame_find_invokee(tc, data->fetch_code, NULL);
25
15
    MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
26
15
    MVM_args_setup_thunk(tc, res, res_type, inv_arg_callsite);
27
15
    tc->cur_frame->args[0].o      = cont;
28
15
    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
29
15
}
30
31
15
static void code_pair_fetch(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
32
15
    code_pair_fetch_internal(tc, cont, res, MVM_RETURN_OBJ);
33
15
}
34
35
0
static void code_pair_fetch_i(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
36
0
    code_pair_fetch_internal(tc, cont, res, MVM_RETURN_INT);
37
0
}
38
39
0
static void code_pair_fetch_n(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
40
0
    code_pair_fetch_internal(tc, cont, res, MVM_RETURN_NUM);
41
0
}
42
43
0
static void code_pair_fetch_s(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
44
0
    code_pair_fetch_internal(tc, cont, res, MVM_RETURN_STR);
45
0
}
46
47
12
static void code_pair_store_internal(MVMThreadContext *tc, MVMObject *cont, MVMRegister value, MVMCallsite *cs) {
48
12
    CodePairContData         *data = (CodePairContData *)STABLE(cont)->container_data;
49
12
    MVMObject                *code = MVM_frame_find_invokee(tc, data->store_code, NULL);
50
12
    MVM_args_setup_thunk(tc, NULL, MVM_RETURN_VOID, cs);
51
12
    tc->cur_frame->args[0].o       = cont;
52
12
    tc->cur_frame->args[1]         = value;
53
12
    STABLE(code)->invoke(tc, code, cs, tc->cur_frame->args);
54
12
}
55
56
12
static void code_pair_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
57
12
    MVMRegister r;
58
12
    r.o = obj;
59
12
    code_pair_store_internal(tc, cont, r, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_TWO_OBJ));
60
12
}
61
62
0
static void code_pair_store_i(MVMThreadContext *tc, MVMObject *cont, MVMint64 value) {
63
0
    MVMRegister r;
64
0
    r.i64 = value;
65
0
    code_pair_store_internal(tc, cont, r, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_OBJ_INT));
66
0
}
67
68
0
static void code_pair_store_n(MVMThreadContext *tc, MVMObject *cont, MVMnum64 value) {
69
0
    MVMRegister r;
70
0
    r.n64 = value;
71
0
    code_pair_store_internal(tc, cont, r, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_OBJ_NUM));
72
0
}
73
74
0
static void code_pair_store_s(MVMThreadContext *tc, MVMObject *cont, MVMString *value) {
75
0
    MVMRegister r;
76
0
    r.s = value;
77
0
    code_pair_store_internal(tc, cont, r, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_OBJ_STR));
78
0
}
79
80
0
static void code_pair_gc_mark_data(MVMThreadContext *tc, MVMSTable *st, MVMGCWorklist *worklist) {
81
0
    CodePairContData *data = (CodePairContData *)st->container_data;
82
0
83
0
    MVM_gc_worklist_add(tc, worklist, &data->fetch_code);
84
0
    MVM_gc_worklist_add(tc, worklist, &data->store_code);
85
0
}
86
87
0
static void code_pair_gc_free_data(MVMThreadContext *tc, MVMSTable *st) {
88
0
    MVM_free_null(st->container_data);
89
0
}
90
91
0
static void code_pair_serialize(MVMThreadContext *tc, MVMSTable *st, MVMSerializationWriter *writer) {
92
0
    CodePairContData *data = (CodePairContData *)st->container_data;
93
0
94
0
    MVM_serialization_write_ref(tc, writer, data->fetch_code);
95
0
    MVM_serialization_write_ref(tc, writer, data->store_code);
96
0
}
97
98
0
static void code_pair_deserialize(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) {
99
0
    CodePairContData *data = (CodePairContData *)st->container_data;
100
0
101
0
    MVM_ASSIGN_REF(tc, &(st->header), data->fetch_code, MVM_serialization_read_ref(tc, reader));
102
0
    MVM_ASSIGN_REF(tc, &(st->header), data->store_code, MVM_serialization_read_ref(tc, reader));
103
0
}
104
105
1
static MVMint32 code_pair_can_store(MVMThreadContext *tc, MVMObject *cont) {
106
1
    return 1;
107
1
}
108
109
static const MVMContainerSpec code_pair_spec = {
110
    "code_pair",
111
    code_pair_fetch,
112
    code_pair_fetch_i,
113
    code_pair_fetch_n,
114
    code_pair_fetch_s,
115
    code_pair_store,
116
    code_pair_store_i,
117
    code_pair_store_n,
118
    code_pair_store_s,
119
    code_pair_store,
120
    NULL, /* spesh */
121
    code_pair_gc_mark_data,
122
    code_pair_gc_free_data,
123
    code_pair_serialize,
124
    code_pair_deserialize,
125
    code_pair_can_store,
126
    0
127
};
128
129
3
static void code_pair_set_container_spec(MVMThreadContext *tc, MVMSTable *st) {
130
3
    CodePairContData *data = MVM_malloc(sizeof(CodePairContData));
131
3
132
3
    data->fetch_code   = NULL;
133
3
    data->store_code   = NULL;
134
3
    st->container_data = data;
135
3
    st->container_spec = &code_pair_spec;
136
3
}
137
138
3
static void code_pair_configure_container_spec(MVMThreadContext *tc, MVMSTable *st, MVMObject *config) {
139
3
    CodePairContData *data = (CodePairContData *)st->container_data;
140
3
141
3
    MVMROOT(tc, config, {
142
3
        MVMString *fetch = MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "fetch");
143
3
        MVMString *store;
144
3
145
3
        if (!MVM_repr_exists_key(tc, config, fetch))
146
3
            MVM_exception_throw_adhoc(tc, "Container spec 'code_pair' must be configured with a fetch");
147
3
148
3
        MVM_ASSIGN_REF(tc, &(st->header), data->fetch_code, MVM_repr_at_key_o(tc, config, fetch));
149
3
150
3
        store = MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "store");
151
3
152
3
        if (!MVM_repr_exists_key(tc, config, store))
153
3
            MVM_exception_throw_adhoc(tc, "Container spec 'code_pair' must be configured with a store");
154
3
155
3
        MVM_ASSIGN_REF(tc, &(st->header), data->store_code, MVM_repr_at_key_o(tc, config, store));
156
3
    });
157
3
}
158
159
static const MVMContainerConfigurer CodePairContainerConfigurer = {
160
    code_pair_set_container_spec,
161
    code_pair_configure_container_spec
162
};
163
164
/* ***************************************************************************
165
 * Native reference container configuration
166
 * ***************************************************************************/
167
168
7
static void native_ref_fetch_i(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
169
7
    MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(cont)->REPR_data;
170
7
    if (repr_data->primitive_type != MVM_STORAGE_SPEC_BP_INT)
171
0
        MVM_exception_throw_adhoc(tc, "This container does not reference a native integer");
172
7
    switch (repr_data->ref_kind) {
173
5
        case MVM_NATIVEREF_LEX:
174
5
            res->i64 = MVM_nativeref_read_lex_i(tc, cont);
175
5
            break;
176
1
        case MVM_NATIVEREF_ATTRIBUTE:
177
1
            res->i64 = MVM_nativeref_read_attribute_i(tc, cont);
178
1
            break;
179
1
        case MVM_NATIVEREF_POSITIONAL:
180
1
            res->i64 = MVM_nativeref_read_positional_i(tc, cont);
181
1
            break;
182
0
        case MVM_NATIVEREF_MULTIDIM:
183
0
            res->i64 = MVM_nativeref_read_multidim_i(tc, cont);
184
0
            break;
185
0
        default:
186
0
            MVM_exception_throw_adhoc(tc, "Unknown native int reference kind");
187
7
    }
188
7
}
189
190
7
static void native_ref_fetch_n(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
191
7
    MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(cont)->REPR_data;
192
7
    if (repr_data->primitive_type != MVM_STORAGE_SPEC_BP_NUM)
193
0
        MVM_exception_throw_adhoc(tc, "This container does not reference a native number");
194
7
    switch (repr_data->ref_kind) {
195
5
        case MVM_NATIVEREF_LEX:
196
5
            res->n64 = MVM_nativeref_read_lex_n(tc, cont);
197
5
            break;
198
1
        case MVM_NATIVEREF_ATTRIBUTE:
199
1
            res->n64 = MVM_nativeref_read_attribute_n(tc, cont);
200
1
            break;
201
1
        case MVM_NATIVEREF_POSITIONAL:
202
1
            res->n64 = MVM_nativeref_read_positional_n(tc, cont);
203
1
            break;
204
0
        case MVM_NATIVEREF_MULTIDIM:
205
0
            res->n64 = MVM_nativeref_read_multidim_n(tc, cont);
206
0
            break;
207
0
        default:
208
0
            MVM_exception_throw_adhoc(tc, "Unknown native num reference kind");
209
7
    }
210
7
}
211
212
7
static void native_ref_fetch_s(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
213
7
    MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(cont)->REPR_data;
214
7
    if (repr_data->primitive_type != MVM_STORAGE_SPEC_BP_STR)
215
0
        MVM_exception_throw_adhoc(tc, "This container does not reference a native string");
216
7
    switch (repr_data->ref_kind) {
217
5
        case MVM_NATIVEREF_LEX:
218
5
            res->s = MVM_nativeref_read_lex_s(tc, cont);
219
5
            break;
220
1
        case MVM_NATIVEREF_ATTRIBUTE:
221
1
            res->s = MVM_nativeref_read_attribute_s(tc, cont);
222
1
            break;
223
1
        case MVM_NATIVEREF_POSITIONAL:
224
1
            res->s = MVM_nativeref_read_positional_s(tc, cont);
225
1
            break;
226
0
        case MVM_NATIVEREF_MULTIDIM:
227
0
            res->s = MVM_nativeref_read_multidim_s(tc, cont);
228
0
            break;
229
0
        default:
230
0
            MVM_exception_throw_adhoc(tc, "Unknown native str reference kind");
231
7
    }
232
7
}
233
234
12
static void native_ref_fetch(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
235
12
    MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(cont)->REPR_data;
236
12
    MVMHLLConfig         *hll       = STABLE(cont)->hll_owner;
237
12
    MVMRegister           tmp;
238
12
    if (!hll)
239
11
        hll = MVM_hll_current(tc);
240
12
    switch (repr_data->primitive_type) {
241
4
        case MVM_STORAGE_SPEC_BP_INT:
242
4
            native_ref_fetch_i(tc, cont, &tmp);
243
4
            res->o = MVM_repr_box_int(tc, hll->int_box_type, tmp.i64);
244
4
            break;
245
4
        case MVM_STORAGE_SPEC_BP_NUM:
246
4
            native_ref_fetch_n(tc, cont, &tmp);
247
4
            res->o = MVM_repr_box_num(tc, hll->num_box_type, tmp.n64);
248
4
            break;
249
4
        case MVM_STORAGE_SPEC_BP_STR:
250
4
            native_ref_fetch_s(tc, cont, &tmp);
251
4
            res->o = MVM_repr_box_str(tc, hll->str_box_type, tmp.s);
252
4
            break;
253
0
        default:
254
0
            MVM_exception_throw_adhoc(tc, "Unknown native reference primitive type");
255
12
    }
256
12
}
257
258
5
static void native_ref_store_i(MVMThreadContext *tc, MVMObject *cont, MVMint64 value) {
259
5
    MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(cont)->REPR_data;
260
5
    if (repr_data->primitive_type != MVM_STORAGE_SPEC_BP_INT)
261
0
        MVM_exception_throw_adhoc(tc, "This container does not reference a native integer");
262
5
    switch (repr_data->ref_kind) {
263
2
        case MVM_NATIVEREF_LEX:
264
2
            MVM_nativeref_write_lex_i(tc, cont, value);
265
2
            break;
266
2
        case MVM_NATIVEREF_ATTRIBUTE:
267
2
            MVM_nativeref_write_attribute_i(tc, cont, value);
268
2
            break;
269
1
        case MVM_NATIVEREF_POSITIONAL:
270
1
            MVM_nativeref_write_positional_i(tc, cont, value);
271
1
            break;
272
0
        case MVM_NATIVEREF_MULTIDIM:
273
0
            MVM_nativeref_write_multidim_i(tc, cont, value);
274
0
            break;
275
0
        default:
276
0
            MVM_exception_throw_adhoc(tc, "Unknown native int reference kind");
277
5
    }
278
5
}
279
280
5
static void native_ref_store_n(MVMThreadContext *tc, MVMObject *cont, MVMnum64 value) {
281
5
    MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(cont)->REPR_data;
282
5
    if (repr_data->primitive_type != MVM_STORAGE_SPEC_BP_NUM)
283
0
        MVM_exception_throw_adhoc(tc, "This container does not reference a native number");
284
5
    switch (repr_data->ref_kind) {
285
2
        case MVM_NATIVEREF_LEX:
286
2
            MVM_nativeref_write_lex_n(tc, cont, value);
287
2
            break;
288
2
        case MVM_NATIVEREF_ATTRIBUTE:
289
2
            MVM_nativeref_write_attribute_n(tc, cont, value);
290
2
            break;
291
1
        case MVM_NATIVEREF_POSITIONAL:
292
1
            MVM_nativeref_write_positional_n(tc, cont, value);
293
1
            break;
294
0
        case MVM_NATIVEREF_MULTIDIM:
295
0
            MVM_nativeref_write_multidim_n(tc, cont, value);
296
0
            break;
297
0
        default:
298
0
            MVM_exception_throw_adhoc(tc, "Unknown native num reference kind");
299
5
    }
300
5
}
301
302
5
static void native_ref_store_s(MVMThreadContext *tc, MVMObject *cont, MVMString *value) {
303
5
    MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(cont)->REPR_data;
304
5
    if (repr_data->primitive_type != MVM_STORAGE_SPEC_BP_STR)
305
0
        MVM_exception_throw_adhoc(tc, "This container does not reference a native string");
306
5
    switch (repr_data->ref_kind) {
307
2
        case MVM_NATIVEREF_LEX:
308
2
            MVM_nativeref_write_lex_s(tc, cont, value);
309
2
            break;
310
2
        case MVM_NATIVEREF_ATTRIBUTE:
311
2
            MVM_nativeref_write_attribute_s(tc, cont, value);
312
2
            break;
313
1
        case MVM_NATIVEREF_POSITIONAL:
314
1
            MVM_nativeref_write_positional_s(tc, cont, value);
315
1
            break;
316
0
        case MVM_NATIVEREF_MULTIDIM:
317
0
            MVM_nativeref_write_multidim_s(tc, cont, value);
318
0
            break;
319
0
        default:
320
0
            MVM_exception_throw_adhoc(tc, "Unknown native str reference kind");
321
5
    }
322
5
}
323
324
3
static void native_ref_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
325
3
    MVMNativeRefREPRData *repr_data = (MVMNativeRefREPRData *)STABLE(cont)->REPR_data;
326
3
    switch (repr_data->primitive_type) {
327
1
        case MVM_STORAGE_SPEC_BP_INT:
328
1
            native_ref_store_i(tc, cont, MVM_repr_get_int(tc, obj));
329
1
            break;
330
1
        case MVM_STORAGE_SPEC_BP_NUM:
331
1
            native_ref_store_n(tc, cont, MVM_repr_get_num(tc, obj));
332
1
            break;
333
1
        case MVM_STORAGE_SPEC_BP_STR:
334
1
            native_ref_store_s(tc, cont, MVM_repr_get_str(tc, obj));
335
1
            break;
336
0
        default:
337
0
            MVM_exception_throw_adhoc(tc, "Unknown native reference primitive type");
338
3
    }
339
3
}
340
341
0
static void native_ref_serialize(MVMThreadContext *tc, MVMSTable *st, MVMSerializationWriter *writer) {
342
0
    /* Nothing to do. */
343
0
}
344
345
0
static void native_ref_deserialize(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) {
346
0
    /* Nothing to do. */
347
0
}
348
349
0
static MVMint32 native_ref_can_store(MVMThreadContext *tc, MVMObject *cont) {
350
0
    return 1;
351
0
}
352
353
static const MVMContainerSpec native_ref_spec = {
354
    "native_ref",
355
    native_ref_fetch,
356
    native_ref_fetch_i,
357
    native_ref_fetch_n,
358
    native_ref_fetch_s,
359
    native_ref_store,
360
    native_ref_store_i,
361
    native_ref_store_n,
362
    native_ref_store_s,
363
    native_ref_store,
364
    NULL, /* spesh */
365
    NULL, /* gc_mark_data */
366
    NULL, /* gc_free_data */
367
    native_ref_serialize,
368
    native_ref_deserialize,
369
    native_ref_can_store,
370
    1
371
};
372
373
16
static void native_ref_set_container_spec(MVMThreadContext *tc, MVMSTable *st) {
374
16
    st->container_spec = &native_ref_spec;
375
16
}
376
377
16
static void native_ref_configure_container_spec(MVMThreadContext *tc, MVMSTable *st, MVMObject *config) {
378
16
    /* Nothing to do. */
379
16
}
380
381
static const MVMContainerConfigurer NativeRefContainerConfigurer = {
382
    native_ref_set_container_spec,
383
    native_ref_configure_container_spec
384
};
385
386
/* ***************************************************************************
387
 * Container registry and configuration
388
 * ***************************************************************************/
389
390
/* Adds a container configurer to the registry. */
391
void MVM_6model_add_container_config(MVMThreadContext *tc, MVMString *name,
392
260
        const MVMContainerConfigurer *configurer) {
393
260
    MVMContainerRegistry *entry;
394
260
395
260
    uv_mutex_lock(&tc->instance->mutex_container_registry);
396
260
397
260
    MVM_HASH_GET(tc, tc->instance->container_registry, name, entry);
398
260
399
260
    if (!entry) {
400
260
        entry = MVM_malloc(sizeof(MVMContainerRegistry));
401
260
        entry->name = name;
402
260
        entry->configurer  = configurer;
403
260
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->name,
404
260
            "Container configuration name");
405
260
        MVM_HASH_BIND(tc, tc->instance->container_registry, name, entry);
406
260
        MVM_gc_root_add_permanent_desc(tc, (MVMCollectable **)&entry->hash_handle.key,
407
260
            "Container configuration hash key");
408
260
    }
409
260
410
260
    uv_mutex_unlock(&tc->instance->mutex_container_registry);
411
260
}
412
413
/* Gets a container configurer from the registry. */
414
19
const MVMContainerConfigurer * MVM_6model_get_container_config(MVMThreadContext *tc, MVMString *name) {
415
19
    MVMContainerRegistry *entry;
416
19
    MVM_HASH_GET(tc, tc->instance->container_registry, name, entry);
417
19
    return entry != NULL ? entry->configurer : NULL;
418
19
}
419
420
/* Does initial setup work of the container registry, including registering
421
 * the various built-in container types. */
422
130
void MVM_6model_containers_setup(MVMThreadContext *tc) {
423
130
    /* Add built-in configurations. */
424
130
    MVM_6model_add_container_config(tc,
425
130
        MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "code_pair"), &CodePairContainerConfigurer);
426
130
    MVM_6model_add_container_config(tc,
427
130
        MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "native_ref"), &NativeRefContainerConfigurer);
428
130
}
429
430
/* ***************************************************************************
431
 * Native container/reference operations
432
 * ***************************************************************************/
433
434
/* Check if this is a container referencing a given native. */
435
27
static MVMint64 get_container_primitive(MVMThreadContext *tc, MVMObject *cont) {
436
27
    if (cont && IS_CONCRETE(cont)) {
437
27
        const MVMContainerSpec *cs = STABLE(cont)->container_spec;
438
27
        if (cs == &native_ref_spec && REPR(cont)->ID == MVM_REPR_ID_NativeRef)
439
18
            return ((MVMNativeRefREPRData *)STABLE(cont)->REPR_data)->primitive_type;
440
27
    }
441
9
    return MVM_STORAGE_SPEC_BP_NONE;
442
27
}
443
9
MVMint64 MVM_6model_container_iscont_i(MVMThreadContext *tc, MVMObject *cont) {
444
9
    return get_container_primitive(tc, cont) == MVM_STORAGE_SPEC_BP_INT;
445
9
}
446
9
MVMint64 MVM_6model_container_iscont_n(MVMThreadContext *tc, MVMObject *cont) {
447
9
    return get_container_primitive(tc, cont) == MVM_STORAGE_SPEC_BP_NUM;
448
9
}
449
9
MVMint64 MVM_6model_container_iscont_s(MVMThreadContext *tc, MVMObject *cont) {
450
9
    return get_container_primitive(tc, cont) == MVM_STORAGE_SPEC_BP_STR;
451
9
}
452
453
/* If it's a container, do a fetch_i. Otherwise, try to unbox the received
454
 * value as a native integer. */
455
7
void MVM_6model_container_decont_i(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
456
7
    const MVMContainerSpec *cs = STABLE(cont)->container_spec;
457
7
    if (cs && IS_CONCRETE(cont))
458
3
        cs->fetch_i(tc, cont, res);
459
7
    else
460
4
        res->i64 = MVM_repr_get_int(tc, cont);
461
7
}
462
463
/* If it's a container, do a fetch_n. Otherwise, try to unbox the received
464
 * value as a native number. */
465
5
void MVM_6model_container_decont_n(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
466
5
    const MVMContainerSpec *cs = STABLE(cont)->container_spec;
467
5
    if (cs && IS_CONCRETE(cont))
468
3
        cs->fetch_n(tc, cont, res);
469
5
    else
470
2
        res->n64 = MVM_repr_get_num(tc, cont);
471
5
}
472
473
/* If it's a container, do a fetch_s. Otherwise, try to unbox the received
474
 * value as a native string. */
475
5
void MVM_6model_container_decont_s(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
476
5
    const MVMContainerSpec *cs = STABLE(cont)->container_spec;
477
5
    if (cs && IS_CONCRETE(cont))
478
3
        cs->fetch_s(tc, cont, res);
479
5
    else
480
2
        res->s = MVM_repr_get_str(tc, cont);
481
5
}
482
483
/* If it's a container, do a fetch_i. Otherwise, try to unbox the received
484
 * value as a native unsigned integer. */
485
0
void MVM_6model_container_decont_u(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
486
0
    const MVMContainerSpec *cs = STABLE(cont)->container_spec;
487
0
    if (cs && IS_CONCRETE(cont))
488
0
        /* XXX We need a fetch_u at some point. */
489
0
        cs->fetch_i(tc, cont, res);
490
0
    else
491
0
        res->u64 = MVM_repr_get_uint(tc, cont);
492
0
}
493
494
/* Checks we have a container, and provided we do, assigns an int into it. */
495
4
void MVM_6model_container_assign_i(MVMThreadContext *tc, MVMObject *cont, MVMint64 value) {
496
4
    const MVMContainerSpec *cs = STABLE(cont)->container_spec;
497
4
    if (cs && IS_CONCRETE(cont))
498
4
        cs->store_i(tc, cont, value);
499
4
    else
500
0
        MVM_exception_throw_adhoc(tc, "Cannot assign to an immutable value");
501
4
}
502
503
/* Checks we have a container, and provided we do, assigns a num into it. */
504
4
void MVM_6model_container_assign_n(MVMThreadContext *tc, MVMObject *cont, MVMnum64 value) {
505
4
    const MVMContainerSpec *cs = STABLE(cont)->container_spec;
506
4
    if (cs && IS_CONCRETE(cont))
507
4
        cs->store_n(tc, cont, value);
508
4
    else
509
0
        MVM_exception_throw_adhoc(tc, "Cannot assign to an immutable value");
510
4
}
511
512
/* Checks we have a container, and provided we do, assigns a str into it. */
513
4
void MVM_6model_container_assign_s(MVMThreadContext *tc, MVMObject *cont, MVMString *value) {
514
4
    const MVMContainerSpec *cs = STABLE(cont)->container_spec;
515
4
    if (cs && IS_CONCRETE(cont))
516
4
        cs->store_s(tc, cont, value);
517
4
    else
518
0
        MVM_exception_throw_adhoc(tc, "Cannot assign to an immutable value");
519
4
}