Coverage Report

Created: 2017-04-15 07:07

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