Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/core/coerce.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
#include "math/grisu.h"
3
4
#if defined(_MSC_VER)
5
#define strtoll _strtoi64
6
#define snprintf _snprintf
7
#endif
8
9
/* Special return structure for boolification handling. */
10
typedef struct {
11
    MVMuint8    *true_addr;
12
    MVMuint8    *false_addr;
13
    MVMuint8     flip;
14
    MVMRegister  res_reg;
15
} BoolMethReturnData;
16
17
171k
MVMint64 MVM_coerce_istrue_s(MVMThreadContext *tc, MVMString *str) {
18
171k
    return str == NULL || !IS_CONCRETE(str) || MVM_string_graphs_nocheck(tc, str) == 0 ? 0 : 1;
19
171k
}
20
21
/* Tries to do the boolification. It may be that a method call is needed. In
22
 * this case, a return hook is set up to handle doing the right thing. The
23
 * result register to put the result in should be indicated in res_reg, or
24
 * alternatively the true/false addresses to set the PC to should be set.
25
 * In the register case, expects that the current PC is already at the
26
 * next instruction before this is called. */
27
static void boolify_return(MVMThreadContext *tc, void *sr_data);
28
static void flip_return(MVMThreadContext *tc, void *sr_data);
29
void MVM_coerce_istrue(MVMThreadContext *tc, MVMObject *obj, MVMRegister *res_reg,
30
6.43M
        MVMuint8 *true_addr, MVMuint8 *false_addr, MVMuint8 flip) {
31
6.43M
    MVMint64 result = 0;
32
6.43M
    if (!MVM_is_null(tc, obj)) {
33
6.43M
        MVMBoolificationSpec *bs = obj->st->boolification_spec;
34
6.40M
        switch (bs == NULL ? MVM_BOOL_MODE_NOT_TYPE_OBJECT : bs->mode) {
35
158k
            case MVM_BOOL_MODE_CALL_METHOD: {
36
158k
                MVMObject *code = MVM_frame_find_invokee(tc, bs->method, NULL);
37
158k
                MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
38
158k
                if (res_reg) {
39
113k
                    /* We need to do the invocation, and set this register
40
113k
                     * the result. Then we just do the call. For the flip
41
113k
                     * case, just set up special return handler to flip
42
113k
                     * the register. */
43
113k
                    MVM_args_setup_thunk(tc, res_reg, MVM_RETURN_INT, inv_arg_callsite);
44
113k
                    tc->cur_frame->args[0].o = obj;
45
113k
                    if (flip)
46
12.0k
                        MVM_frame_special_return(tc, tc->cur_frame, flip_return, NULL,
47
12.0k
                            res_reg, NULL);
48
113k
                    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
49
113k
                }
50
44.5k
                else {
51
44.5k
                    /* Need to set up special return hook. */
52
44.5k
                    BoolMethReturnData *data = MVM_malloc(sizeof(BoolMethReturnData));
53
44.5k
                    data->true_addr  = true_addr;
54
44.5k
                    data->false_addr = false_addr;
55
44.5k
                    data->flip       = flip;
56
44.5k
                    MVM_frame_special_return(tc, tc->cur_frame, boolify_return, NULL, data, NULL);
57
44.5k
                    MVM_args_setup_thunk(tc, &data->res_reg, MVM_RETURN_INT, inv_arg_callsite);
58
44.5k
                    tc->cur_frame->args[0].o = obj;
59
44.5k
                    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
60
44.5k
                }
61
158k
                return;
62
158k
            }
63
1.01M
            case MVM_BOOL_MODE_UNBOX_INT:
64
1.01M
                result = !IS_CONCRETE(obj) || REPR(obj)->box_funcs.get_int(tc, STABLE(obj), obj, OBJECT_BODY(obj)) == 0 ? 0 : 1;
65
1.01M
                break;
66
443
            case MVM_BOOL_MODE_UNBOX_NUM:
67
443
                result = !IS_CONCRETE(obj) || REPR(obj)->box_funcs.get_num(tc, STABLE(obj), obj, OBJECT_BODY(obj)) == 0.0 ? 0 : 1;
68
443
                break;
69
171k
            case MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY: {
70
171k
                MVMString *str;
71
171k
                if (!IS_CONCRETE(obj)) {
72
1
                    result = 0;
73
1
                    break;
74
1
                }
75
171k
                str = REPR(obj)->box_funcs.get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj));
76
171k
                result = MVM_coerce_istrue_s(tc, str);
77
171k
                break;
78
171k
            }
79
4
            case MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY_OR_ZERO: {
80
4
                MVMString *str;
81
4
                MVMint64 chars;
82
4
                if (!IS_CONCRETE(obj)) {
83
1
                    result = 0;
84
1
                    break;
85
1
                }
86
3
                str = REPR(obj)->box_funcs.get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj));
87
3
88
3
                if (str == NULL || !IS_CONCRETE(str)) {
89
0
                    result = 0;
90
0
                    break;
91
0
                }
92
3
93
3
                chars = MVM_string_graphs_nocheck(tc, str);
94
3
95
3
                result = chars == 0 ||
96
2
                        (chars == 1 && MVM_string_get_grapheme_at_nocheck(tc, str, 0) == 48)
97
2
                        ? 0 : 1;
98
3
                break;
99
3
            }
100
1.06M
            case MVM_BOOL_MODE_NOT_TYPE_OBJECT:
101
1.06M
                result = !IS_CONCRETE(obj) ? 0 : 1;
102
1.06M
                break;
103
3
            case MVM_BOOL_MODE_BIGINT:
104
3
                result = IS_CONCRETE(obj) ? MVM_bigint_bool(tc, obj) : 0;
105
3
                break;
106
1.96M
            case MVM_BOOL_MODE_ITER:
107
1.96M
                result = IS_CONCRETE(obj) ? MVM_iter_istrue(tc, (MVMIter *)obj) : 0;
108
1.96M
                break;
109
2.05M
            case MVM_BOOL_MODE_HAS_ELEMS:
110
2.05M
                result = IS_CONCRETE(obj) ? MVM_repr_elems(tc, obj) != 0 : 0;
111
2.05M
                break;
112
0
            default:
113
0
                MVM_exception_throw_adhoc(tc, "Invalid boolification spec mode used");
114
6.43M
        }
115
6.43M
    }
116
6.43M
117
6.27M
    if (flip)
118
2.21M
        result = result ? 0 : 1;
119
6.27M
120
6.27M
    if (res_reg) {
121
3.68M
        res_reg->i64 = result;
122
3.68M
    }
123
2.59M
    else {
124
2.59M
        if (result)
125
1.44M
            *(tc->interp_cur_op) = true_addr;
126
2.59M
        else
127
1.14M
            *(tc->interp_cur_op) = false_addr;
128
2.59M
    }
129
6.27M
}
130
131
/* Callback after running boolification method. */
132
44.5k
static void boolify_return(MVMThreadContext *tc, void *sr_data) {
133
44.5k
    BoolMethReturnData *data = (BoolMethReturnData *)sr_data;
134
44.5k
    MVMint64 result = data->res_reg.i64;
135
44.5k
    if (data->flip)
136
36.2k
        result = result ? 0 : 1;
137
44.5k
    if (result)
138
14.2k
        *(tc->interp_cur_op) = data->true_addr;
139
44.5k
    else
140
30.3k
        *(tc->interp_cur_op) = data->false_addr;
141
44.5k
    MVM_free(data);
142
44.5k
}
143
144
/* Callback to flip result. */
145
12.0k
static void flip_return(MVMThreadContext *tc, void *sr_data) {
146
12.0k
    MVMRegister *r = (MVMRegister *)sr_data;
147
11.5k
    r->i64 = r->i64 ? 0 : 1;
148
12.0k
}
149
150
401k
MVMString * MVM_coerce_i_s(MVMThreadContext *tc, MVMint64 i) {
151
401k
    char buffer[64];
152
401k
    int len;
153
401k
    /* See if we can hit the cache. */
154
399k
    int cache = 0 <= i && i < MVM_INT_TO_STR_CACHE_SIZE;
155
401k
    if (cache) {
156
319k
        MVMString *cached = tc->instance->int_to_str_cache[i];
157
319k
        if (cached)
158
313k
            return cached;
159
319k
    }
160
401k
161
401k
    /* Otherwise, need to do the work; cache it if in range. */
162
87.3k
    len = snprintf(buffer, 64, "%"PRIi64"", i);
163
87.3k
    if (0 <= len) {
164
87.3k
        MVMString *result = MVM_string_ascii_decode(tc, tc->instance->VMString, buffer, len);
165
87.3k
        if (cache)
166
5.48k
            tc->instance->int_to_str_cache[i] = result;
167
87.3k
        return result;
168
87.3k
    }
169
0
    else {
170
0
        MVM_exception_throw_adhoc(tc, "Could not stringify integer");
171
0
    }
172
87.3k
}
173
174
0
MVMString * MVM_coerce_u_s(MVMThreadContext *tc, MVMuint64 i) {
175
0
    char buffer[64];
176
0
    int len;
177
0
    /* See if we can hit the cache. */
178
0
    int cache = 0 <= i && i < MVM_INT_TO_STR_CACHE_SIZE;
179
0
    if (cache) {
180
0
        MVMString *cached = tc->instance->int_to_str_cache[i];
181
0
        if (cached)
182
0
            return cached;
183
0
    }
184
0
185
0
    /* Otherwise, need to do the work; cache it if in range. */
186
0
    len = snprintf(buffer, 64, "%"PRIu64"", i);
187
0
    if (0 <= len) {
188
0
        MVMString *result = MVM_string_ascii_decode(tc, tc->instance->VMString, buffer, len);
189
0
        if (cache)
190
0
            tc->instance->int_to_str_cache[i] = result;
191
0
        return result;
192
0
    }
193
0
    else {
194
0
        MVM_exception_throw_adhoc(tc, "Could not stringify integer");
195
0
    }
196
0
}
197
198
29.0k
MVMString * MVM_coerce_n_s(MVMThreadContext *tc, MVMnum64 n) {
199
29.0k
    if (n == MVM_num_posinf(tc)) {
200
5
        return MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "Inf");
201
5
    }
202
28.9k
    else if (n == MVM_num_neginf(tc)) {
203
5
        return MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "-Inf");
204
5
    }
205
28.9k
    else if (n != n) {
206
1
        return MVM_string_ascii_decode_nt(tc, tc->instance->VMString, "NaN");
207
1
    }
208
28.9k
    else {
209
28.9k
        char buf[64];
210
28.9k
        int i;
211
28.9k
        if (dtoa_grisu3(n, buf, 64) < 0)
212
0
            MVM_exception_throw_adhoc(tc, "Could not stringify number");
213
28.9k
        return MVM_string_ascii_decode(tc, tc->instance->VMString, buf, strlen(buf));
214
28.9k
    }
215
29.0k
}
216
217
3.35M
void MVM_coerce_smart_stringify(MVMThreadContext *tc, MVMObject *obj, MVMRegister *res_reg) {
218
3.35M
    MVMObject *strmeth;
219
3.35M
    const MVMStorageSpec *ss;
220
3.35M
221
3.35M
    /* Handle null case. */
222
3.35M
    if (MVM_is_null(tc, obj)) {
223
2
        res_reg->s = tc->instance->str_consts.empty;
224
2
        return;
225
2
    }
226
3.35M
227
3.35M
    /* If it can unbox as a string, that wins right off. */
228
3.35M
    ss = REPR(obj)->get_storage_spec(tc, STABLE(obj));
229
3.35M
    if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_STR && IS_CONCRETE(obj)) {
230
2.75M
        res_reg->s = REPR(obj)->box_funcs.get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj));
231
2.75M
        return;
232
2.75M
    }
233
3.35M
234
3.35M
    /* Check if there is a Str method. */
235
601k
    MVMROOT(tc, obj, {
236
601k
        strmeth = MVM_6model_find_method_cache_only(tc, obj,
237
601k
            tc->instance->str_consts.Str);
238
601k
    });
239
601k
240
601k
    if (!MVM_is_null(tc, strmeth)) {
241
146k
        /* We need to do the invocation; just set it up with our result reg as
242
146k
         * the one for the call. */
243
146k
        MVMObject *code = MVM_frame_find_invokee(tc, strmeth, NULL);
244
146k
        MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
245
146k
246
146k
        MVM_args_setup_thunk(tc, res_reg, MVM_RETURN_STR, inv_arg_callsite);
247
146k
        tc->cur_frame->args[0].o = obj;
248
146k
        STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
249
146k
        return;
250
146k
    }
251
601k
252
601k
    /* Otherwise, guess something appropriate. */
253
455k
    if (!IS_CONCRETE(obj))
254
44.6k
        res_reg->s = tc->instance->str_consts.empty;
255
411k
    else {
256
411k
        if (REPR(obj)->ID == MVM_REPR_ID_MVMException)
257
49
            res_reg->s = ((MVMException *)obj)->body.message;
258
411k
        else if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_INT)
259
386k
            res_reg->s = MVM_coerce_i_s(tc, REPR(obj)->box_funcs.get_int(tc, STABLE(obj), obj, OBJECT_BODY(obj)));
260
24.6k
        else if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_NUM)
261
24.6k
            res_reg->s = MVM_coerce_n_s(tc, REPR(obj)->box_funcs.get_num(tc, STABLE(obj), obj, OBJECT_BODY(obj)));
262
24.6k
        else
263
0
            MVM_exception_throw_adhoc(tc, "cannot stringify this");
264
411k
    }
265
455k
}
266
267
1.83k
MVMint64 MVM_coerce_s_i(MVMThreadContext *tc, MVMString *s) {
268
1.83k
    char     *enc = MVM_string_ascii_encode(tc, s, NULL, 0);
269
1.83k
    MVMint64  i   = strtoll(enc, NULL, 10);
270
1.83k
    MVM_free(enc);
271
1.83k
    return i;
272
1.83k
}
273
274
26.7M
void MVM_coerce_smart_numify(MVMThreadContext *tc, MVMObject *obj, MVMRegister *res_reg) {
275
26.7M
    MVMObject *nummeth;
276
26.7M
277
26.7M
    /* Handle null case. */
278
26.7M
    if (MVM_is_null(tc, obj)) {
279
0
        res_reg->n64 = 0.0;
280
0
        return;
281
0
    }
282
26.7M
283
26.7M
    /* Check if there is a Num method. */
284
26.7M
    MVMROOT(tc, obj, {
285
26.7M
        nummeth = MVM_6model_find_method_cache_only(tc, obj,
286
26.7M
            tc->instance->str_consts.Num);
287
26.7M
    });
288
26.7M
289
26.7M
    if (!MVM_is_null(tc, nummeth)) {
290
627
        /* We need to do the invocation; just set it up with our result reg as
291
627
         * the one for the call. */
292
627
        MVMObject *code = MVM_frame_find_invokee(tc, nummeth, NULL);
293
627
        MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
294
627
295
627
        MVM_args_setup_thunk(tc, res_reg, MVM_RETURN_NUM, inv_arg_callsite);
296
627
        tc->cur_frame->args[0].o = obj;
297
627
        STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
298
627
        return;
299
627
    }
300
26.7M
301
26.7M
    /* Otherwise, guess something appropriate. */
302
26.7M
    if (!IS_CONCRETE(obj)) {
303
2.85k
        res_reg->n64 = 0.0;
304
2.85k
    }
305
26.7M
    else {
306
26.7M
        const MVMStorageSpec *ss = REPR(obj)->get_storage_spec(tc, STABLE(obj));
307
26.7M
        if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_INT)
308
18.0M
            res_reg->n64 = (MVMnum64)REPR(obj)->box_funcs.get_int(tc, STABLE(obj), obj, OBJECT_BODY(obj));
309
8.68M
        else if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_NUM)
310
8.42M
            res_reg->n64 = REPR(obj)->box_funcs.get_num(tc, STABLE(obj), obj, OBJECT_BODY(obj));
311
258k
        else if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_STR)
312
4.10k
            res_reg->n64 = MVM_coerce_s_n(tc, REPR(obj)->box_funcs.get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj)));
313
254k
        else if (REPR(obj)->ID == MVM_REPR_ID_VMArray)
314
245k
            res_reg->n64 = (MVMnum64)REPR(obj)->elems(tc, STABLE(obj), obj, OBJECT_BODY(obj));
315
8.49k
        else if (REPR(obj)->ID == MVM_REPR_ID_MVMHash)
316
8.49k
            res_reg->n64 = (MVMnum64)REPR(obj)->elems(tc, STABLE(obj), obj, OBJECT_BODY(obj));
317
8.49k
        else
318
0
            MVM_exception_throw_adhoc(tc, "cannot numify this");
319
26.7M
    }
320
26.7M
}
321
322
684k
MVMint64 MVM_coerce_simple_intify(MVMThreadContext *tc, MVMObject *obj) {
323
684k
    /* Handle null and non-concrete case. */
324
684k
    if (MVM_is_null(tc, obj) || !IS_CONCRETE(obj)) {
325
0
        return 0;
326
0
    }
327
684k
328
684k
    /* Otherwise, guess something appropriate. */
329
684k
    else {
330
684k
        const MVMStorageSpec *ss = REPR(obj)->get_storage_spec(tc, STABLE(obj));
331
684k
        if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_INT)
332
609k
            return REPR(obj)->box_funcs.get_int(tc, STABLE(obj), obj, OBJECT_BODY(obj));
333
75.2k
        else if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_NUM)
334
75.2k
            return (MVMint64)REPR(obj)->box_funcs.get_num(tc, STABLE(obj), obj, OBJECT_BODY(obj));
335
0
        else if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_STR)
336
0
            return MVM_coerce_s_i(tc, REPR(obj)->box_funcs.get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj)));
337
0
        else if (REPR(obj)->ID == MVM_REPR_ID_VMArray)
338
0
            return REPR(obj)->elems(tc, STABLE(obj), obj, OBJECT_BODY(obj));
339
0
        else if (REPR(obj)->ID == MVM_REPR_ID_MVMHash)
340
0
            return REPR(obj)->elems(tc, STABLE(obj), obj, OBJECT_BODY(obj));
341
0
        else
342
0
            MVM_exception_throw_adhoc(tc, "cannot intify this");
343
684k
    }
344
684k
}
345
346
/* concatenating with "" ensures that only literal strings are accepted as argument. */
347
#define STR_WITH_LEN(str)  ("" str ""), (sizeof(str) - 1)
348
349
6.66k
MVMObject * MVM_radix(MVMThreadContext *tc, MVMint64 radix, MVMString *str, MVMint64 offset, MVMint64 flag) {
350
6.66k
    MVMObject *result;
351
6.66k
    MVMint64 zvalue = 0;
352
6.66k
    MVMint64 zbase  = 1;
353
6.66k
    MVMint64 chars  = MVM_string_graphs(tc, str);
354
6.66k
    MVMint64 value  = zvalue;
355
6.66k
    MVMint64 base   = zbase;
356
6.66k
    MVMint64   pos  = -1;
357
6.66k
    MVMuint16  neg  = 0;
358
6.66k
    MVMint64   ch;
359
6.66k
360
6.66k
    if (radix > 36) {
361
0
        MVM_exception_throw_adhoc(tc, "Cannot convert radix of %"PRId64" (max 36)", radix);
362
0
    }
363
6.66k
364
6.57k
    ch = (offset < chars) ? MVM_string_get_grapheme_at_nocheck(tc, str, offset) : 0;
365
6.66k
    if ((flag & 0x02) && (ch == '+' || ch == '-')) {
366
4
        neg = (ch == '-');
367
4
        offset++;
368
4
        ch = (offset < chars) ? MVM_string_get_grapheme_at_nocheck(tc, str, offset) : 0;
369
4
    }
370
6.66k
371
9.82k
    while (offset < chars) {
372
9.73k
        if (ch >= '0' && ch <= '9') ch = ch - '0'; /* fast-path for ASCII 0..9 */
373
282
        else if (ch >= 'a' && ch <= 'z') ch = ch - 'a' + 10;
374
81
        else if (ch >= 'A' && ch <= 'Z') ch = ch - 'A' + 10;
375
25
        else if (ch >= 0xFF21 && ch <= 0xFF3A) ch = ch - 0xFF21 + 10; /* uppercase fullwidth */
376
21
        else if (ch >= 0xFF41 && ch <= 0xFF5A) ch = ch - 0xFF41 + 10; /* lowercase fullwidth */
377
17
        else if (ch > 0 && MVM_unicode_codepoint_get_property_int(tc, ch, MVM_UNICODE_PROPERTY_NUMERIC_TYPE)
378
17
         == MVM_UNICODE_PVALUE_Numeric_Type_DECIMAL) {
379
4
            /* as of Unicode 9.0.0, characters with the 'de' Numeric Type (and are
380
4
             * thus also of General Category Nd, since 4.0.0) are contiguous
381
4
             * sequences of 10 chars whose Numeric Values ascend from 0 through 9.
382
4
             */
383
4
384
4
            /* the string returned for NUMERIC_VALUE_NUMERATOR contains an integer
385
4
             * value. We can use numerator because they all are from 0-9 and have
386
4
             * denominator of 1 */
387
4
            ch = fast_atoi(MVM_unicode_codepoint_get_property_cstr(tc, ch, MVM_UNICODE_PROPERTY_NUMERIC_VALUE_NUMERATOR));
388
4
        }
389
13
        else break;
390
9.72k
        if (ch >= radix) break;
391
9.63k
        zvalue = zvalue * radix + ch;
392
9.63k
        zbase = zbase * radix;
393
9.63k
        offset++; pos = offset;
394
9.63k
        if (ch != 0 || !(flag & 0x04)) { value=zvalue; base=zbase; }
395
9.63k
        if (offset >= chars) break;
396
3.16k
        ch = MVM_string_get_grapheme_at_nocheck(tc, str, offset);
397
3.16k
        if (ch != '_') continue;
398
28
        offset++;
399
28
        if (offset >= chars) break;
400
28
        ch = MVM_string_get_grapheme_at_nocheck(tc, str, offset);
401
28
    }
402
6.66k
403
6.66k
    if (neg || flag & 0x01) { value = -value; }
404
6.66k
405
6.66k
    /* initialize the object */
406
6.66k
    result = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type);
407
6.66k
    MVMROOT(tc, result, {
408
6.66k
        MVMObject *box_type = MVM_hll_current(tc)->int_box_type;
409
6.66k
        MVMROOT(tc, box_type, {
410
6.66k
            MVMObject *boxed = MVM_repr_box_int(tc, box_type, value);
411
6.66k
            MVM_repr_push_o(tc, result, boxed);
412
6.66k
            boxed = MVM_repr_box_int(tc, box_type, base);
413
6.66k
            MVM_repr_push_o(tc, result, boxed);
414
6.66k
            boxed = MVM_repr_box_int(tc, box_type, pos);
415
6.66k
            MVM_repr_push_o(tc, result, boxed);
416
6.66k
        });
417
6.66k
    });
418
6.66k
419
6.66k
    return result;
420
6.66k
}
421
422
423
void MVM_box_int(MVMThreadContext *tc, MVMint64 value, MVMObject *type,
424
8.43M
             MVMRegister * dst) {
425
8.43M
    MVMObject *box = MVM_intcache_get(tc, type, value);
426
8.43M
    if (box == 0) {
427
5.80M
        box = REPR(type)->allocate(tc, STABLE(type));
428
5.80M
        if (REPR(box)->initialize)
429
419
            REPR(box)->initialize(tc, STABLE(box), box, OBJECT_BODY(box));
430
5.80M
        REPR(box)->box_funcs.set_int(tc, STABLE(box), box,
431
5.80M
                                     OBJECT_BODY(box), value);
432
5.80M
    }
433
8.43M
    dst->o = box;
434
8.43M
}
435
436
void MVM_box_num(MVMThreadContext *tc, MVMnum64 value, MVMObject *type,
437
7.23M
                 MVMRegister * dst) {
438
7.23M
    MVMObject *box = REPR(type)->allocate(tc, STABLE(type));
439
7.23M
    if (REPR(box)->initialize)
440
4
        REPR(box)->initialize(tc, STABLE(box), box, OBJECT_BODY(box));
441
7.23M
    REPR(box)->box_funcs.set_num(tc, STABLE(box), box,
442
7.23M
                                 OBJECT_BODY(box), value);
443
7.23M
    dst->o = box;
444
7.23M
445
7.23M
}
446
447
1.05M
MVMString * MVM_unbox_str(MVMThreadContext *tc, MVMObject *obj) {
448
1.05M
    if (!IS_CONCRETE(obj))
449
0
        MVM_exception_throw_adhoc(tc, "Cannot unbox a type object (%s) to a str.",
450
0
            MVM_6model_get_debug_name(tc, obj));
451
1.05M
    return REPR(obj)->box_funcs.get_str(tc,
452
1.05M
        STABLE(obj), obj, OBJECT_BODY(obj));
453
1.05M
}
454
455
void MVM_box_str(MVMThreadContext *tc, MVMString *value, MVMObject *type,
456
2.62M
                 MVMRegister *dst) {
457
2.62M
    MVMObject *box;
458
2.62M
    MVMROOT(tc, value, {
459
2.62M
        box = REPR(type)->allocate(tc, STABLE(type));
460
2.62M
        if (REPR(box)->initialize)
461
2.62M
            REPR(box)->initialize(tc, STABLE(box), box, OBJECT_BODY(box));
462
2.62M
        REPR(box)->box_funcs.set_str(tc, STABLE(box), box,
463
2.62M
                                     OBJECT_BODY(box), value);
464
2.62M
        dst->o = box;
465
2.62M
    });
466
2.62M
}
467
468
void MVM_box_uint(MVMThreadContext *tc, MVMuint64 value, MVMObject *type,
469
0
             MVMRegister * dst) {
470
0
    MVMObject *box = REPR(type)->allocate(tc, STABLE(type));
471
0
    if (REPR(box)->initialize)
472
0
        REPR(box)->initialize(tc, STABLE(box), box, OBJECT_BODY(box));
473
0
    REPR(box)->box_funcs.set_uint(tc, STABLE(box), box, OBJECT_BODY(box), value);
474
0
    dst->o = box;
475
0
}