Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/jit/graph.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
#include "math.h"
3
4
#include "platform/sys.h"
5
#include "platform/time.h"
6
7
8
893k
static void jg_append_node(MVMJitGraph *jg, MVMJitNode *node) {
9
893k
    if (jg->last_node) {
10
882k
        jg->last_node->next = node;
11
882k
        jg->last_node = node;
12
11.1k
    } else {
13
11.1k
        jg->first_node = node;
14
11.1k
        jg->last_node = node;
15
11.1k
    }
16
893k
    node->next = NULL;
17
893k
}
18
19
static void jg_append_primitive(MVMThreadContext *tc, MVMJitGraph *jg,
20
139k
                                MVMSpeshIns * ins) {
21
139k
    MVMJitNode * node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
22
139k
    node->type = MVM_JIT_NODE_PRIMITIVE;
23
139k
    node->u.prim.ins = ins;
24
139k
    jg_append_node(jg, node);
25
139k
}
26
27
static void jg_append_call_c(MVMThreadContext *tc, MVMJitGraph *jg,
28
                              void * func_ptr, MVMint16 num_args,
29
                              MVMJitCallArg *call_args,
30
68.8k
                              MVMJitRVMode rv_mode, MVMint16 rv_idx) {
31
68.8k
    MVMJitNode * node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
32
68.8k
    size_t args_size =  num_args * sizeof(MVMJitCallArg);
33
68.8k
    node->type             = MVM_JIT_NODE_CALL_C;
34
68.8k
    node->u.call.func_ptr  = func_ptr;
35
68.8k
    node->u.call.num_args  = num_args;
36
68.8k
    node->u.call.has_vargs = 0; /* don't support them yet */
37
68.8k
    /* Call argument array is typically stack allocated,
38
68.8k
     * so they need to be copied */
39
68.8k
    node->u.call.args      = MVM_spesh_alloc(tc, jg->sg, args_size);
40
68.8k
    memcpy(node->u.call.args, call_args, args_size);
41
68.8k
    node->u.call.rv_mode   = rv_mode;
42
68.8k
    node->u.call.rv_idx    = rv_idx;
43
68.8k
    jg_append_node(jg, node);
44
68.8k
}
45
46
47
25.1k
static void add_deopt_idx(MVMThreadContext *tc, MVMJitGraph *jg, MVMint32 label_name, MVMint32 deopt_idx) {
48
25.1k
    MVMJitDeopt deopt;
49
25.1k
    deopt.label = label_name;
50
25.1k
    deopt.idx   = deopt_idx;
51
25.1k
    MVM_VECTOR_PUSH(jg->deopts, deopt);
52
25.1k
}
53
54
55
static void jg_append_branch(MVMThreadContext *tc, MVMJitGraph *jg,
56
23.3k
                              MVMint32 name, MVMSpeshIns *ins) {
57
23.3k
    MVMJitNode * node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
58
23.3k
    node->type = MVM_JIT_NODE_BRANCH;
59
23.3k
    if (ins == NULL) {
60
0
        node->u.branch.ins = NULL;
61
0
        node->u.branch.dest = name;
62
0
    }
63
23.3k
    else {
64
23.3k
        MVMSpeshBB *bb;
65
23.3k
        node->u.branch.ins = ins;
66
23.3k
        if (ins->info->opcode == MVM_OP_goto) {
67
5.71k
            bb = ins->operands[0].ins_bb;
68
5.71k
        }
69
17.6k
        else if (ins->info->opcode == MVM_OP_indexat ||
70
17.2k
                 ins->info->opcode == MVM_OP_indexnat) {
71
395
            bb = ins->operands[3].ins_bb;
72
395
        }
73
17.2k
        else {
74
17.2k
            bb = ins->operands[1].ins_bb;
75
17.2k
        }
76
23.3k
        node->u.branch.dest = MVM_jit_label_before_bb(tc, jg, bb);
77
23.3k
    }
78
23.3k
    jg_append_node(jg, node);
79
23.3k
}
80
81
377k
static void jg_append_label(MVMThreadContext *tc, MVMJitGraph *jg, MVMint32 name) {
82
377k
    MVMJitNode *node;
83
377k
    /* does this label already exist? */
84
377k
    MVM_VECTOR_ENSURE_SIZE(jg->label_nodes, name);
85
377k
    if (jg->label_nodes[name] != NULL)
86
43.8k
        return;
87
377k
88
333k
    node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
89
333k
    node->type = MVM_JIT_NODE_LABEL;
90
333k
    node->u.label.name = name;
91
333k
    jg_append_node(jg, node);
92
333k
93
333k
    jg->label_nodes[name] = node;
94
333k
    MVM_jit_log(tc, "append label: %d\n", node->u.label.name);
95
333k
}
96
97
48.7k
static void * op_to_func(MVMThreadContext *tc, MVMint16 opcode) {
98
48.7k
    switch(opcode) {
99
0
    case MVM_OP_checkarity: return MVM_args_checkarity;
100
0
    case MVM_OP_say: return MVM_string_say;
101
0
    case MVM_OP_print: return MVM_string_print;
102
0
    case MVM_OP_isnull: return MVM_is_null;
103
0
    case MVM_OP_capturelex: return MVM_frame_capturelex;
104
0
    case MVM_OP_captureinnerlex: return MVM_frame_capture_inner;
105
0
    case MVM_OP_takeclosure: return MVM_frame_takeclosure;
106
0
    case MVM_OP_usecapture: return MVM_args_use_capture;
107
0
    case MVM_OP_savecapture: return MVM_args_save_capture;
108
0
    case MVM_OP_captureposprimspec: return MVM_capture_pos_primspec;
109
6
    case MVM_OP_return: return MVM_args_assert_void_return_ok;
110
1.15k
    case MVM_OP_return_i: return MVM_args_set_result_int;
111
452
    case MVM_OP_return_s: return MVM_args_set_result_str;
112
2.76k
    case MVM_OP_return_o: return MVM_args_set_result_obj;
113
2
    case MVM_OP_return_n: return MVM_args_set_result_num;
114
185
    case MVM_OP_coerce_is: return MVM_coerce_i_s;
115
53
    case MVM_OP_coerce_ns: return MVM_coerce_n_s;
116
748
    case MVM_OP_coerce_si: return MVM_coerce_s_i;
117
0
    case MVM_OP_coerce_sn: return MVM_coerce_s_n;
118
0
    case MVM_OP_coerce_In: return MVM_bigint_to_num;
119
0
    case MVM_OP_coerce_nI: return MVM_bigint_from_num;
120
0
    case MVM_OP_coerce_II: return MVM_bigint_from_bigint;
121
0
    case MVM_OP_iterkey_s: return MVM_iterkey_s;
122
403
    case MVM_OP_iter: return MVM_iter;
123
140
    case MVM_OP_iterval: return MVM_iterval;
124
326
    case MVM_OP_die: return MVM_exception_die;
125
0
    case MVM_OP_throwdyn:
126
0
    case MVM_OP_throwlex:
127
0
    case MVM_OP_throwlexotic:
128
0
    case MVM_OP_rethrow: return MVM_exception_throwobj;
129
9
    case MVM_OP_throwcatdyn:
130
9
    case MVM_OP_throwcatlex:
131
9
    case MVM_OP_throwcatlexotic: return MVM_exception_throwcat;
132
1.22k
    case MVM_OP_throwpayloadlex: return MVM_exception_throwpayload;
133
0
    case MVM_OP_bindexpayload: return MVM_bind_exception_payload;
134
0
    case MVM_OP_getexpayload: return MVM_get_exception_payload;
135
0
    case MVM_OP_resume: return MVM_exception_resume;
136
0
    case MVM_OP_continuationreset: return MVM_continuation_reset;
137
0
    case MVM_OP_continuationcontrol: return MVM_continuation_control;
138
0
    case MVM_OP_continuationinvoke: return MVM_continuation_invoke;
139
1.28k
    case MVM_OP_smrt_numify: return MVM_coerce_smart_numify;
140
717
    case MVM_OP_smrt_strify: return MVM_coerce_smart_stringify;
141
9
    case MVM_OP_gethow: return MVM_6model_get_how_obj;
142
1.66k
    case MVM_OP_box_i: return MVM_box_int;
143
95
    case MVM_OP_box_s: return MVM_box_str;
144
401
    case MVM_OP_box_n: return MVM_box_num;
145
987
    case MVM_OP_unbox_i: return MVM_repr_get_int;
146
277
    case MVM_OP_unbox_s: return MVM_repr_get_str;
147
0
    case MVM_OP_unbox_n: return MVM_repr_get_num;
148
270
    case MVM_OP_istrue: case MVM_OP_isfalse: return MVM_coerce_istrue;
149
152
    case MVM_OP_istype: return MVM_6model_istype;
150
0
    case MVM_OP_isint: case MVM_OP_isnum: case MVM_OP_isstr: /* continued */
151
0
    case MVM_OP_islist: case MVM_OP_ishash: return MVM_repr_compare_repr_id;
152
10.4k
    case MVM_OP_wval: case MVM_OP_wval_wide: return MVM_sc_get_sc_object;
153
9
    case MVM_OP_scgetobjidx: return MVM_sc_find_object_idx_jit;
154
243
    case MVM_OP_getdynlex: return MVM_frame_getdynlex;
155
65
    case MVM_OP_binddynlex: return MVM_frame_binddynlex;
156
0
    case MVM_OP_getlexouter: return MVM_frame_find_lexical_by_name_outer;
157
0
    case MVM_OP_getlexcaller: return MVM_frame_find_lexical_by_name_rel_caller;
158
526
    case MVM_OP_findmeth: case MVM_OP_findmeth_s: return MVM_6model_find_method;
159
593
    case MVM_OP_tryfindmeth: case MVM_OP_tryfindmeth_s: return MVM_6model_find_method;
160
78
    case MVM_OP_multicacheadd: return MVM_multi_cache_add;
161
0
    case MVM_OP_multicachefind: return MVM_multi_cache_find;
162
11
    case MVM_OP_can: case MVM_OP_can_s: return MVM_6model_can_method;
163
445
    case MVM_OP_push_i: return MVM_repr_push_i;
164
0
    case MVM_OP_push_n: return MVM_repr_push_n;
165
0
    case MVM_OP_push_s: return MVM_repr_push_s;
166
1.12k
    case MVM_OP_push_o: return MVM_repr_push_o;
167
0
    case MVM_OP_unshift_i: return MVM_repr_unshift_i;
168
0
    case MVM_OP_unshift_n: return MVM_repr_unshift_n;
169
0
    case MVM_OP_unshift_s: return MVM_repr_unshift_s;
170
84
    case MVM_OP_unshift_o: return MVM_repr_unshift_o;
171
0
    case MVM_OP_pop_i: return MVM_repr_pop_i;
172
0
    case MVM_OP_pop_n: return MVM_repr_pop_n;
173
0
    case MVM_OP_pop_s: return MVM_repr_pop_s;
174
13
    case MVM_OP_pop_o: return MVM_repr_pop_o;
175
0
    case MVM_OP_shift_i: return MVM_repr_shift_i;
176
0
    case MVM_OP_shift_n: return MVM_repr_shift_n;
177
0
    case MVM_OP_shift_s: return MVM_repr_shift_s;
178
1
    case MVM_OP_shift_o: return MVM_repr_shift_o;
179
0
    case MVM_OP_setelemspos: return MVM_repr_pos_set_elems;
180
0
    case MVM_OP_slice:  return MVM_repr_pos_slice;
181
163
    case MVM_OP_splice: return MVM_repr_pos_splice;
182
11
183
60
    case MVM_OP_existskey: return MVM_repr_exists_key;
184
372
    case MVM_OP_deletekey: return MVM_repr_delete_key;
185
11
186
88
    case MVM_OP_atpos_i: return MVM_repr_at_pos_i;
187
0
    case MVM_OP_atpos_n: return MVM_repr_at_pos_n;
188
0
    case MVM_OP_atpos_s: return MVM_repr_at_pos_s;
189
2.11k
    case MVM_OP_atpos_o: return MVM_repr_at_pos_o;
190
11
191
0
    case MVM_OP_existspos: return MVM_repr_exists_pos;
192
11
193
0
    case MVM_OP_atkey_i: return MVM_repr_at_key_i;
194
0
    case MVM_OP_atkey_n: return MVM_repr_at_key_n;
195
0
    case MVM_OP_atkey_s: return MVM_repr_at_key_s;
196
1.00k
    case MVM_OP_atkey_o: return MVM_repr_at_key_o;
197
11
198
0
    case MVM_OP_bindpos_i: return MVM_repr_bind_pos_i;
199
0
    case MVM_OP_bindpos_n: return MVM_repr_bind_pos_n;
200
0
    case MVM_OP_bindpos_s: return MVM_repr_bind_pos_s;
201
932
    case MVM_OP_bindpos_o: return MVM_repr_bind_pos_o;
202
11
203
0
    case MVM_OP_bindkey_i: return MVM_repr_bind_key_i;
204
0
    case MVM_OP_bindkey_n: return MVM_repr_bind_key_n;
205
0
    case MVM_OP_bindkey_s: return MVM_repr_bind_key_s;
206
676
    case MVM_OP_bindkey_o: return MVM_repr_bind_key_o;
207
11
208
482
    case MVM_OP_getattr_s: return MVM_repr_get_attr_s;
209
0
    case MVM_OP_getattr_n: return MVM_repr_get_attr_n;
210
2.07k
    case MVM_OP_getattr_i: return MVM_repr_get_attr_i;
211
1.88k
    case MVM_OP_getattr_o: return MVM_repr_get_attr_o;
212
11
213
0
    case MVM_OP_getattrs_s: return MVM_repr_get_attr_s;
214
0
    case MVM_OP_getattrs_n: return MVM_repr_get_attr_n;
215
0
    case MVM_OP_getattrs_i: return MVM_repr_get_attr_i;
216
98
    case MVM_OP_getattrs_o: return MVM_repr_get_attr_o;
217
11
218
49
    case MVM_OP_attrinited: return MVM_repr_attribute_inited;
219
11
220
3.01k
    case MVM_OP_bindattr_i: case MVM_OP_bindattr_n: case MVM_OP_bindattr_s: case MVM_OP_bindattr_o: return MVM_repr_bind_attr_inso;
221
481
    case MVM_OP_bindattrs_i: case MVM_OP_bindattrs_n: case MVM_OP_bindattrs_s: case MVM_OP_bindattrs_o: return MVM_repr_bind_attr_inso;
222
481
223
60
    case MVM_OP_hintfor: return MVM_repr_hint_for;
224
481
225
0
    case MVM_OP_gt_s: case MVM_OP_ge_s: case MVM_OP_lt_s: case MVM_OP_le_s: case MVM_OP_cmp_s: return MVM_string_compare;
226
0
227
0
    case MVM_OP_queuepoll: return MVM_concblockingqueue_jit_poll;
228
0
229
0
    case MVM_OP_open_fh: return MVM_file_open_fh;
230
0
    case MVM_OP_close_fh: return MVM_io_close;
231
0
    case MVM_OP_eof_fh: return MVM_io_eof;
232
8
    case MVM_OP_write_fhb: return MVM_io_write_bytes;
233
0
    case MVM_OP_read_fhb: return MVM_io_read_bytes;
234
0
235
8
    case MVM_OP_encode: return MVM_string_encode_to_buf;
236
0
    case MVM_OP_decoderaddbytes: return MVM_decoder_add_bytes;
237
0
    case MVM_OP_decodertakeline: return MVM_decoder_take_line;
238
0
239
824
    case MVM_OP_elems: return MVM_repr_elems;
240
990
    case MVM_OP_concat_s: return MVM_string_concatenate;
241
4
    case MVM_OP_repeat_s: return MVM_string_repeat;
242
0
    case MVM_OP_flip: return MVM_string_flip;
243
1
    case MVM_OP_split: return MVM_string_split;
244
0
    case MVM_OP_escape: return MVM_string_escape;
245
0
    case MVM_OP_uc: return MVM_string_uc;
246
0
    case MVM_OP_tc: return MVM_string_tc;
247
0
    case MVM_OP_lc: return MVM_string_lc;
248
0
    case MVM_OP_fc: return MVM_string_fc;
249
203
    case MVM_OP_eq_s: return MVM_string_equal;
250
86
    case MVM_OP_eqat_s: return MVM_string_equal_at;
251
123
    case MVM_OP_eqatic_s: return MVM_string_equal_at_ignore_case;
252
0
    case MVM_OP_eqatim_s: return MVM_string_equal_at_ignore_mark;
253
0
    case MVM_OP_eqaticim_s: return MVM_string_equal_at_ignore_case_ignore_mark;
254
791
    case MVM_OP_chars: case MVM_OP_graphs_s: return MVM_string_graphs;
255
2
    case MVM_OP_chr: return MVM_string_chr;
256
10
    case MVM_OP_codes_s: return MVM_string_codes;
257
0
    case MVM_OP_getcp_s: return MVM_string_get_grapheme_at;
258
10
    case MVM_OP_index_s: return MVM_string_index;
259
306
    case MVM_OP_substr_s: return MVM_string_substring;
260
1
    case MVM_OP_join: return MVM_string_join;
261
0
    case MVM_OP_replace: return MVM_string_replace;
262
12
    case MVM_OP_iscclass: return MVM_string_is_cclass;
263
2
    case MVM_OP_findcclass: return MVM_string_find_cclass;
264
32
    case MVM_OP_findnotcclass: return MVM_string_find_not_cclass;
265
20
    case MVM_OP_nfarunalt: return MVM_nfa_run_alt;
266
0
    case MVM_OP_nfarunproto: return MVM_nfa_run_proto;
267
644
    case MVM_OP_nfafromstatelist: return MVM_nfa_from_statelist;
268
0
    case MVM_OP_hllize: return MVM_hll_map;
269
10
    case MVM_OP_gethllsym: return MVM_hll_sym_get;
270
27
    case MVM_OP_clone: return MVM_repr_clone;
271
0
    case MVM_OP_create: return MVM_repr_alloc_init;
272
1
    case MVM_OP_getcodeobj: return MVM_frame_get_code_object;
273
0
    case MVM_OP_isbig_I: return MVM_bigint_is_big;
274
0
    case MVM_OP_cmp_I: return MVM_bigint_cmp;
275
0
    case MVM_OP_add_I: return MVM_bigint_add;
276
0
    case MVM_OP_sub_I: return MVM_bigint_sub;
277
0
    case MVM_OP_mul_I: return MVM_bigint_mul;
278
0
    case MVM_OP_div_I: return MVM_bigint_div;
279
0
    case MVM_OP_bor_I: return MVM_bigint_or;
280
0
    case MVM_OP_band_I: return MVM_bigint_and;
281
0
    case MVM_OP_bxor_I: return MVM_bigint_xor;
282
0
    case MVM_OP_mod_I: return MVM_bigint_mod;
283
0
    case MVM_OP_lcm_I: return MVM_bigint_lcm;
284
0
    case MVM_OP_gcd_I: return MVM_bigint_gcd;
285
0
    case MVM_OP_bool_I: return MVM_bigint_bool;
286
0
    case MVM_OP_isprime_I: return MVM_bigint_is_prime;
287
0
    case MVM_OP_brshift_I: return MVM_bigint_shr;
288
0
    case MVM_OP_blshift_I: return MVM_bigint_shl;
289
0
    case MVM_OP_bnot_I: return MVM_bigint_not;
290
0
    case MVM_OP_div_In: return MVM_bigint_div_num;
291
0
    case MVM_OP_coerce_Is: case MVM_OP_base_I: return MVM_bigint_to_str;
292
6
    case MVM_OP_radix: return MVM_radix;
293
0
    case MVM_OP_radix_I: return MVM_bigint_radix;
294
0
    case MVM_OP_sqrt_n: return sqrt;
295
0
    case MVM_OP_sin_n: return sin;
296
0
    case MVM_OP_cos_n: return cos;
297
0
    case MVM_OP_tan_n: return tan;
298
0
    case MVM_OP_asin_n: return asin;
299
0
    case MVM_OP_acos_n: return acos;
300
0
    case MVM_OP_atan_n: return atan;
301
0
    case MVM_OP_atan2_n: return atan2;
302
0
    case MVM_OP_floor_n: return floor;
303
0
    case MVM_OP_pow_I: return MVM_bigint_pow;
304
0
    case MVM_OP_rand_I: return MVM_bigint_rand;
305
0
    case MVM_OP_pow_n: return pow;
306
6
    case MVM_OP_time_n: return MVM_proc_time_n;
307
2
    case MVM_OP_randscale_n: return MVM_proc_randscale_n;
308
0
    case MVM_OP_isnanorinf: return MVM_num_isnanorinf;
309
0
    case MVM_OP_nativecallcast: return MVM_nativecall_cast;
310
0
    case MVM_OP_nativecallinvoke: return MVM_nativecall_invoke;
311
0
    case MVM_OP_nativeinvoke_o: return MVM_nativecall_invoke_jit;
312
0
    case MVM_OP_typeparameterized: return MVM_6model_parametric_type_parameterized;
313
0
    case MVM_OP_typeparameters: return MVM_6model_parametric_type_parameters;
314
0
    case MVM_OP_typeparameterat: return MVM_6model_parametric_type_parameter_at;
315
2
    case MVM_OP_objectid: return MVM_gc_object_id;
316
0
    case MVM_OP_iscont_i: return MVM_6model_container_iscont_i;
317
0
    case MVM_OP_iscont_n: return MVM_6model_container_iscont_n;
318
0
    case MVM_OP_iscont_s: return MVM_6model_container_iscont_s;
319
0
    case MVM_OP_isrwcont: return MVM_6model_container_iscont_rw;
320
0
    case MVM_OP_assign_i: return MVM_6model_container_assign_i;
321
0
    case MVM_OP_assign_n: return MVM_6model_container_assign_n;
322
0
    case MVM_OP_assign_s: return MVM_6model_container_assign_s;
323
0
    case MVM_OP_decont_i: return MVM_6model_container_decont_i;
324
0
    case MVM_OP_decont_n: return MVM_6model_container_decont_n;
325
0
    case MVM_OP_decont_s: return MVM_6model_container_decont_s;
326
0
    case MVM_OP_getrusage: return MVM_proc_getrusage;
327
0
    case MVM_OP_cpucores: return MVM_platform_cpu_count;
328
0
    case MVM_OP_getsignals: return MVM_io_get_signals;
329
0
    case MVM_OP_sleep: return MVM_platform_sleep;
330
0
    case MVM_OP_getlexref_i32: case MVM_OP_getlexref_i16: case MVM_OP_getlexref_i8: case MVM_OP_getlexref_i: return MVM_nativeref_lex_i;
331
0
    case MVM_OP_getlexref_n32: case MVM_OP_getlexref_n: return MVM_nativeref_lex_n;
332
0
    case MVM_OP_getlexref_s: return MVM_nativeref_lex_s;
333
0
    case MVM_OP_getattrref_i: return MVM_nativeref_attr_i;
334
0
    case MVM_OP_getattrref_n: return MVM_nativeref_attr_n;
335
0
    case MVM_OP_getattrref_s: return MVM_nativeref_attr_s;
336
0
    case MVM_OP_getattrsref_i: return MVM_nativeref_attr_i;
337
0
    case MVM_OP_getattrsref_n: return MVM_nativeref_attr_n;
338
0
    case MVM_OP_getattrsref_s: return MVM_nativeref_attr_s;
339
0
    case MVM_OP_atposref_i: return MVM_nativeref_pos_i;
340
0
    case MVM_OP_atposref_n: return MVM_nativeref_pos_n;
341
0
    case MVM_OP_atposref_s: return MVM_nativeref_pos_s;
342
0
    case MVM_OP_indexingoptimized: return MVM_string_indexing_optimized;
343
0
    case MVM_OP_sp_boolify_iter: return MVM_iter_istrue;
344
0
    case MVM_OP_prof_allocated: return MVM_profile_log_allocated;
345
0
    case MVM_OP_prof_exit: return MVM_profile_log_exit;
346
4.02k
    case MVM_OP_sp_resolvecode: return MVM_frame_resolve_invokee_spesh;
347
0
348
0
    case MVM_OP_cas_o: return MVM_6model_container_cas;
349
0
    case MVM_OP_cas_i: return MVM_6model_container_cas_i;
350
0
    case MVM_OP_atomicinc_i: return MVM_6model_container_atomic_inc;
351
0
    case MVM_OP_atomicdec_i: return MVM_6model_container_atomic_dec;
352
0
    case MVM_OP_atomicadd_i: return MVM_6model_container_atomic_add;
353
0
    case MVM_OP_atomicload_o: return MVM_6model_container_atomic_load;
354
0
    case MVM_OP_atomicload_i: return MVM_6model_container_atomic_load_i;
355
0
    case MVM_OP_atomicstore_o: return MVM_6model_container_atomic_store;
356
0
    case MVM_OP_atomicstore_i: return MVM_6model_container_atomic_store_i;
357
2
    case MVM_OP_lock: return MVM_reentrantmutex_lock_checked;
358
2
    case MVM_OP_unlock: return MVM_reentrantmutex_unlock_checked;
359
0
    case MVM_OP_getexcategory: return MVM_get_exception_category;
360
0
    case MVM_OP_bindexcategory: return MVM_bind_exception_category;
361
0
    case MVM_OP_exreturnafterunwind: return MVM_exception_returnafterunwind;
362
0
363
0
    case MVM_OP_breakpoint: return MVM_debugserver_breakpoint_check;
364
0
    case MVM_OP_sp_getstringfrom: return MVM_cu_string;
365
0
    case MVM_OP_encoderepconf: return MVM_string_encode_to_buf_config;
366
0
    default:
367
0
        MVM_oops(tc, "JIT: No function for op %d in op_to_func (%s)", opcode, MVM_op_get_op(opcode)->name);
368
48.7k
    }
369
48.7k
}
370
371
static void jg_append_guard(MVMThreadContext *tc, MVMJitGraph *jg,
372
37.5k
                             MVMSpeshIns *ins, MVMuint32 target_operand) {
373
37.5k
    MVMSpeshAnn   *ann = ins->annotations;
374
37.5k
    MVMJitNode   *node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
375
37.5k
    MVMint32 deopt_idx;
376
37.5k
    node->type = MVM_JIT_NODE_GUARD;
377
37.5k
    node->u.guard.ins = ins;
378
40.0k
    while (ann) {
379
40.0k
        if (ann->type == MVM_SPESH_ANN_DEOPT_ONE_INS ||
380
37.5k
            ann->type == MVM_SPESH_ANN_DEOPT_INLINE) {
381
37.5k
            deopt_idx = ann->data.deopt_idx;
382
37.5k
            break;
383
37.5k
        }
384
2.48k
        ann = ann->next;
385
2.48k
    }
386
37.5k
    if (!ann) {
387
0
        MVM_oops(tc, "Can't find deopt idx annotation on spesh ins <%s>",
388
0
            ins->info->name);
389
0
    }
390
37.5k
    node->u.guard.deopt_target = ins->operands[target_operand].lit_ui32;
391
37.5k
    node->u.guard.deopt_offset = jg->sg->deopt_addrs[2 * deopt_idx + 1];
392
37.5k
    jg_append_node(jg, node);
393
37.5k
}
394
395
static MVMint32 consume_invoke(MVMThreadContext *tc, MVMJitGraph *jg,
396
27.0k
                               MVMSpeshIterator *iter, MVMSpeshIns *ins) {
397
27.0k
    MVMCompUnit       *cu = iter->graph->sf->body.cu;
398
27.0k
    MVMint16 callsite_idx = ins->operands[0].callsite_idx;
399
27.0k
    MVMCallsite       *cs = cu->body.callsites[callsite_idx];
400
27.0k
    MVMSpeshIns **arg_ins = MVM_spesh_alloc(tc, iter->graph, sizeof(MVMSpeshIns*) * cs->arg_count);
401
27.0k
    MVMint16            i = 0;
402
27.0k
    MVMJitNode      *node;
403
27.0k
    MVMint32      reentry_label;
404
27.0k
    MVMReturnType return_type;
405
27.0k
    MVMint16      return_register;
406
27.0k
    MVMint16      code_register_or_name;
407
27.0k
    MVMint16      spesh_cand_or_sf_slot;
408
27.0k
    MVMint16      is_fast;
409
27.0k
    MVMint16      is_resolve = 0;
410
27.0k
    MVMuint32     resolve_offset = 0;
411
27.0k
412
83.5k
    while ((ins = ins->next)) {
413
83.5k
        switch(ins->info->opcode) {
414
56.4k
        case MVM_OP_arg_i:
415
56.4k
        case MVM_OP_arg_n:
416
56.4k
        case MVM_OP_arg_s:
417
56.4k
        case MVM_OP_arg_o:
418
56.4k
        case MVM_OP_argconst_i:
419
56.4k
        case MVM_OP_argconst_n:
420
56.4k
        case MVM_OP_argconst_s:
421
56.4k
            MVM_jit_log(tc, "Invoke arg: <%s>\n", ins->info->name);
422
56.4k
            arg_ins[i++] = ins;
423
56.4k
            break;
424
184
        case MVM_OP_invoke_v:
425
184
            return_type           = MVM_RETURN_VOID;
426
184
            return_register       = -1;
427
184
            code_register_or_name = ins->operands[0].reg.orig;
428
184
            spesh_cand_or_sf_slot = -1;
429
184
            is_fast               = 0;
430
184
            goto checkargs;
431
0
        case MVM_OP_invoke_i:
432
0
            return_type           = MVM_RETURN_INT;
433
0
            return_register       = ins->operands[0].reg.orig;
434
0
            code_register_or_name = ins->operands[1].reg.orig;
435
0
            spesh_cand_or_sf_slot = -1;
436
0
            is_fast               = 0;
437
0
            goto checkargs;
438
0
        case MVM_OP_invoke_n:
439
0
            return_type           = MVM_RETURN_NUM;
440
0
            return_register       = ins->operands[0].reg.orig;
441
0
            code_register_or_name = ins->operands[1].reg.orig;
442
0
            spesh_cand_or_sf_slot = -1;
443
0
            is_fast               = 0;
444
0
            goto checkargs;
445
10
        case MVM_OP_invoke_s:
446
10
            return_type           = MVM_RETURN_STR;
447
10
            return_register       = ins->operands[0].reg.orig;
448
10
            code_register_or_name = ins->operands[1].reg.orig;
449
10
            spesh_cand_or_sf_slot = -1;
450
10
            is_fast               = 0;
451
10
            goto checkargs;
452
19.7k
        case MVM_OP_invoke_o:
453
19.7k
            return_type           = MVM_RETURN_OBJ;
454
19.7k
            return_register       = ins->operands[0].reg.orig;
455
19.7k
            code_register_or_name = ins->operands[1].reg.orig;
456
19.7k
            spesh_cand_or_sf_slot = -1;
457
19.7k
            is_fast               = 0;
458
19.7k
            goto checkargs;
459
0
        case MVM_OP_nativeinvoke_o: {
460
0
            MVMint16 dst     = ins->operands[0].reg.orig;
461
0
            MVMint16 site    = ins->operands[1].reg.orig;
462
0
            MVMint16 restype = ins->operands[2].reg.orig;
463
0
            MVMNativeCallBody *body;
464
0
            MVMJitGraph *nc_jg;
465
0
            MVMObject *nc_site;
466
0
467
0
            MVMSpeshFacts *object_facts = MVM_spesh_get_facts(tc, iter->graph, ins->operands[1]);
468
0
469
0
            MVM_jit_log(tc, "Invoke instruction: <%s>\n", ins->info->name);
470
0
471
0
            if (!(object_facts->flags & MVM_SPESH_FACT_KNOWN_VALUE)) {
472
0
                MVM_jit_log(tc, "BAIL: op <%s> (Can't find nc_site value on spesh ins)\n", ins->info->name);
473
0
                return 0;
474
0
            }
475
0
476
0
            body = MVM_nativecall_get_nc_body(tc, object_facts->value.o);
477
0
            nc_jg = MVM_nativecall_jit_graph_for_caller_code(tc, iter->graph, body, restype, dst, arg_ins);
478
0
            if (nc_jg == NULL)
479
0
                return 0;
480
0
481
0
            jg->last_node->next = nc_jg->first_node;
482
0
            jg->last_node = nc_jg->last_node;
483
0
484
0
            goto success;
485
0
        }
486
351
        case MVM_OP_sp_fastinvoke_v:
487
351
            return_type           = MVM_RETURN_VOID;
488
351
            return_register       = -1;
489
351
            code_register_or_name = ins->operands[0].reg.orig;
490
351
            spesh_cand_or_sf_slot = ins->operands[1].lit_i16;
491
351
            is_fast               = 1;
492
351
            goto checkargs;
493
6.75k
        case MVM_OP_sp_fastinvoke_o:
494
6.75k
            return_type           = MVM_RETURN_OBJ;
495
6.75k
            return_register       = ins->operands[0].reg.orig;;
496
6.75k
            code_register_or_name = ins->operands[1].reg.orig;
497
6.75k
            spesh_cand_or_sf_slot = ins->operands[2].lit_i16;
498
6.75k
            is_fast               = 1;
499
6.75k
            goto checkargs;
500
0
        case MVM_OP_sp_fastinvoke_s:
501
0
            return_type           = MVM_RETURN_STR;
502
0
            return_register       = ins->operands[0].reg.orig;;
503
0
            code_register_or_name = ins->operands[1].reg.orig;
504
0
            spesh_cand_or_sf_slot = ins->operands[2].lit_i16;
505
0
            is_fast               = 1;
506
0
            goto checkargs;
507
0
        case MVM_OP_sp_fastinvoke_i:
508
0
            return_type           = MVM_RETURN_INT;
509
0
            return_register       = ins->operands[0].reg.orig;;
510
0
            code_register_or_name = ins->operands[1].reg.orig;
511
0
            spesh_cand_or_sf_slot = ins->operands[2].lit_i16;
512
0
            is_fast               = 1;
513
0
            goto checkargs;
514
0
        case MVM_OP_sp_fastinvoke_n:
515
0
            return_type           = MVM_RETURN_NUM;
516
0
            return_register       = ins->operands[0].reg.orig;;
517
0
            code_register_or_name = ins->operands[1].reg.orig;
518
0
            spesh_cand_or_sf_slot = ins->operands[2].lit_i16;
519
0
            is_fast               = 1;
520
0
            goto checkargs;
521
0
        case MVM_OP_sp_speshresolve:
522
0
            return_type           = MVM_RETURN_OBJ;
523
0
            return_register       = ins->operands[0].reg.orig;;
524
0
            code_register_or_name = ins->operands[1].lit_ui32;
525
0
            resolve_offset        = ins->operands[2].lit_ui32;
526
0
            spesh_cand_or_sf_slot = ins->operands[3].lit_i16;
527
0
            is_fast               = 0;
528
0
            is_resolve            = 1;
529
0
            goto checkargs;
530
0
        default:
531
0
            MVM_jit_log(tc, "Unexpected opcode in invoke sequence: <%s>\n",
532
0
                        ins->info->name);
533
0
            return 0;
534
83.5k
        }
535
83.5k
    }
536
27.0k
 checkargs:
537
27.0k
    if (!ins || i < cs->arg_count) {
538
0
        MVM_jit_log(tc, "Could not find invoke opcode or enough arguments\n"
539
0
                    "BAIL: op <%s>, expected args: %d, num of args: %d\n",
540
0
                    ins? ins->info->name : "NULL", i, cs->arg_count);
541
0
        return 0;
542
0
    }
543
27.0k
    MVM_jit_log(tc, "Invoke instruction: <%s>\n", ins->info->name);
544
27.0k
    /* get label /after/ current (invoke) ins, where we'll need to reenter the JIT */
545
27.0k
    reentry_label = MVM_jit_label_after_ins(tc, jg, iter->bb, ins);
546
27.0k
    /* create invoke node */
547
27.0k
    node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
548
27.0k
    node->type                           = MVM_JIT_NODE_INVOKE;
549
27.0k
    node->u.invoke.callsite_idx          = callsite_idx;
550
27.0k
    node->u.invoke.arg_count             = cs->arg_count;
551
27.0k
    node->u.invoke.arg_ins               = arg_ins;
552
27.0k
    node->u.invoke.return_type           = return_type;
553
27.0k
    node->u.invoke.return_register       = return_register;
554
27.0k
    node->u.invoke.code_register_or_name = code_register_or_name;
555
27.0k
    node->u.invoke.spesh_cand_or_sf_slot = spesh_cand_or_sf_slot;
556
27.0k
    node->u.invoke.resolve_offset        = resolve_offset;
557
27.0k
    node->u.invoke.reentry_label         = reentry_label;
558
27.0k
    node->u.invoke.is_fast               = is_fast;
559
27.0k
    node->u.invoke.is_resolve            = is_resolve;
560
27.0k
    jg_append_node(jg, node);
561
27.0k
562
27.0k
    /* append reentry label */
563
27.0k
    jg_append_label(tc, jg, reentry_label);
564
27.0k
  success:
565
27.0k
    /* move forward to invoke ins */
566
27.0k
    iter->ins = ins;
567
27.0k
    return 1;
568
27.0k
}
569
570
static void jg_append_control(MVMThreadContext *tc, MVMJitGraph *jg,
571
0
                              MVMSpeshIns *ins, MVMJitControlType ctrl) {
572
0
    MVMJitNode *node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
573
0
    node->type = MVM_JIT_NODE_CONTROL;
574
0
    node->u.control.ins  = ins;
575
0
    node->u.control.type = ctrl;
576
0
    jg_append_node(jg, node);
577
0
}
578
579
static MVMint32 consume_jumplist(MVMThreadContext *tc, MVMJitGraph *jg,
580
713
                                 MVMSpeshIterator *iter, MVMSpeshIns *ins) {
581
713
    MVMint64 num_labels  = ins->operands[0].lit_i64;
582
713
    MVMint16 idx_reg     = ins->operands[1].reg.orig;
583
713
    MVMint32 *in_labels  = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMint32) * num_labels);
584
713
    MVMint32 *out_labels = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMint32) * num_labels);
585
713
    MVMSpeshBB *bb       = iter->bb;
586
713
    MVMJitNode *node;
587
713
    MVMint64 i;
588
6.68k
    for (i = 0; i < num_labels; i++) {
589
5.97k
        bb = bb->linear_next; /* take the next basic block */
590
5.97k
        if (!bb || bb->first_ins != bb->last_ins) return 0; /*  which must exist */
591
5.97k
        ins = bb->first_ins;  /*  and it's first and only entry */
592
5.97k
        if (ins->info->opcode != MVM_OP_goto)  /* which must be a goto */
593
0
            return 0;
594
5.97k
        in_labels[i]  = MVM_jit_label_before_bb(tc, jg, bb);
595
5.97k
        out_labels[i] = MVM_jit_label_before_bb(tc, jg, ins->operands[0].ins_bb);
596
5.97k
    }
597
713
    /* build the node */
598
713
    node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
599
713
    node->type = MVM_JIT_NODE_JUMPLIST;
600
713
    node->u.jumplist.num_labels = num_labels;
601
713
    node->u.jumplist.reg = idx_reg;
602
713
    node->u.jumplist.in_labels = in_labels;
603
713
    node->u.jumplist.out_labels = out_labels;
604
713
    jg_append_node(jg, node);
605
713
    /* set iterator bb and ins to the end of our jumplist */
606
713
    iter->bb = bb;
607
713
    iter->ins = ins;
608
713
    return 1;
609
713
}
610
611
0
static MVMString* wrap_MVM_cu_string(MVMThreadContext *tc, MVMCompUnit *cu, MVMuint32 idx) {
612
0
    return MVM_cu_string(tc, cu, idx);
613
0
}
614
615
0
static MVMint32 jg_add_data_node(MVMThreadContext *tc, MVMJitGraph *jg, void *data, size_t size) {
616
0
    MVMJitNode *node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
617
0
    MVMint32 label   = MVM_jit_label_for_obj(tc, jg, data);
618
0
    node->type         = MVM_JIT_NODE_DATA;
619
0
    node->u.data.data  = data;
620
0
    node->u.data.size  = size;
621
0
    node->u.data.label = label;
622
0
    jg_append_node(jg, node);
623
0
    return label;
624
0
}
625
626
0
static MVMuint16 * try_fake_extop_regs(MVMThreadContext *tc, MVMSpeshGraph *sg, MVMSpeshIns *ins, size_t *bufsize) {
627
0
    MVMuint16 *regs = MVM_spesh_alloc(tc, sg, (*bufsize = (ins->info->num_operands * sizeof(MVMuint16))));
628
0
    MVMuint16 i;
629
0
    for (i = 0; i < ins->info->num_operands; i++) {
630
0
        switch (ins->info->operands[i] & MVM_operand_rw_mask) {
631
0
        case MVM_operand_read_reg:
632
0
        case MVM_operand_write_reg:
633
0
            regs[i] = ins->operands[i].reg.orig;
634
0
            break;
635
0
        default:
636
0
            MVM_free(regs);
637
0
            return NULL;
638
0
        }
639
0
    }
640
0
    return regs;
641
0
}
642
643
0
static void log_inline(MVMThreadContext *tc, MVMSpeshGraph *sg, MVMint32 inline_idx, MVMint32 is_entry) {
644
0
    MVMStaticFrame *sf = sg->inlines[inline_idx].sf;
645
0
    char *name         = MVM_string_utf8_encode_C_string(tc, sf->body.name);
646
0
    char *cuuid        = MVM_string_utf8_encode_C_string(tc, sf->body.cuuid);
647
0
    MVM_jit_log(tc, "%s inline %d (name: %s, cuuid: %s)\n", is_entry ? "Entering" : "Leaving",
648
0
                inline_idx, name, cuuid);
649
0
    MVM_free(name);
650
0
    MVM_free(cuuid);
651
0
}
652
653
static void before_ins(MVMThreadContext *tc, MVMJitGraph *jg,
654
285k
                       MVMSpeshIterator *iter, MVMSpeshIns  *ins) {
655
285k
    MVMSpeshBB   *bb = iter->bb;
656
285k
    MVMSpeshAnn *ann = ins->annotations;
657
285k
658
285k
    MVMint32 has_label = 0, label;
659
285k
    /* Search annotations for stuff that may need a label. */
660
429k
    while (ann) {
661
144k
        switch(ann->type) {
662
160
        case MVM_SPESH_ANN_DEOPT_OSR: {
663
160
            /* get label before our instruction */
664
160
            label = MVM_jit_label_before_ins(tc, jg, bb, ins);
665
160
            add_deopt_idx(tc, jg, label, ann->data.deopt_idx);
666
160
            has_label = 1;
667
160
            break;
668
160
        }
669
118
        case MVM_SPESH_ANN_FH_START: {
670
118
            label = MVM_jit_label_before_ins(tc, jg, bb, ins);
671
118
            jg->handlers[ann->data.frame_handler_index].start_label = label;
672
118
            has_label = 1;
673
118
            /* Load the current position into the jit entry label, so that
674
118
             * when throwing we'll know which handler to use */
675
118
            break;
676
160
        }
677
1.62k
        case MVM_SPESH_ANN_FH_END: {
678
1.62k
            label = MVM_jit_label_before_ins(tc, jg, bb, ins);
679
1.62k
            jg->handlers[ann->data.frame_handler_index].end_label = label;
680
1.62k
            /* Same as above. Note that the dynamic label control
681
1.62k
             * actually loads a position a few bytes away from the
682
1.62k
             * label appended above. This is in this case intentional
683
1.62k
             * because the frame handler end is exclusive; once it is
684
1.62k
             * passed we should not use the same handler again.  If we
685
1.62k
             * loaded the exact same position, we would not be able to
686
1.62k
             * distinguish between the end of the basic block to which
687
1.62k
             * the handler applies and the start of the basic block to
688
1.62k
             * which it doesn't. */
689
1.62k
            has_label = 1;
690
1.62k
            break;
691
160
        }
692
3.59k
        case MVM_SPESH_ANN_FH_GOTO: {
693
3.59k
            label = MVM_jit_label_before_ins(tc, jg, bb, ins);
694
3.59k
            jg->handlers[ann->data.frame_handler_index].goto_label = label;
695
3.59k
            has_label = 1;
696
3.59k
            break;
697
160
        }
698
7
        case MVM_SPESH_ANN_INLINE_START: {
699
7
            label = MVM_jit_label_before_ins(tc, jg, bb, ins);
700
7
            jg->inlines[ann->data.inline_idx].start_label = label;
701
7
            if (tc->instance->jit_log_fh)
702
0
                log_inline(tc, jg->sg, ann->data.inline_idx, 1);
703
7
            has_label = 1;
704
7
            break;
705
160
        }
706
144k
        } /* switch */
707
144k
        ann = ann->next;
708
144k
    }
709
285k
710
285k
    if (has_label) {
711
5.14k
        jg_append_label(tc, jg, label);
712
5.14k
    }
713
285k
}
714
715
static void after_ins(MVMThreadContext *tc, MVMJitGraph *jg,
716
284k
                      MVMSpeshIterator *iter, MVMSpeshIns *ins) {
717
284k
    MVMSpeshBB   *bb = iter->bb;
718
284k
    MVMSpeshAnn *ann = ins->annotations;
719
284k
720
284k
    /* This order of processing is necessary to ensure that a label
721
284k
     * calculated by one of the control guards as well as the labels
722
284k
     * calculated below point to the exact same instruction. This is a
723
284k
     * relatively fragile construction! One could argue that the
724
284k
     * control guards should in fact use the same (dynamic) labels. */
725
475k
    while (ann) {
726
190k
        if (ann->type == MVM_SPESH_ANN_INLINE_END) {
727
1.40k
            MVMint32 label = MVM_jit_label_after_ins(tc, jg, bb, ins);
728
1.40k
            jg_append_label(tc, jg, label);
729
1.40k
            jg->inlines[ann->data.inline_idx].end_label = label;
730
1.40k
            if (tc->instance->jit_log_fh)
731
0
                log_inline(tc, jg->sg, ann->data.inline_idx, 0);
732
188k
        } else if (ann->type == MVM_SPESH_ANN_DEOPT_ALL_INS) {
733
25.0k
            /* An underlying assumption here is that this instruction
734
25.0k
             * will in fact set the jit_entry_label to a correct
735
25.0k
             * value. This is clearly true for invoking ops as well
736
25.0k
             * as invokish ops, and in fact there is no other way
737
25.0k
             * to get a deopt_all_ins annotation. Still, be warned. */
738
25.0k
            MVMint32 label = MVM_jit_label_after_ins(tc, jg, bb, ins);
739
25.0k
            jg_append_label(tc, jg, label);
740
25.0k
            add_deopt_idx(tc, jg, label, ann->data.deopt_idx);
741
25.0k
        }
742
190k
        ann = ann->next;
743
190k
    }
744
284k
}
745
746
8.97k
static void jg_sc_wb(MVMThreadContext *tc, MVMJitGraph *jg, MVMSpeshOperand check) {
747
8.97k
    MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
748
8.97k
                             { MVM_JIT_REG_VAL,     check.reg.orig } };
749
8.97k
    jg_append_call_c(tc, jg, &MVM_SC_WB_OBJ, 2, args, MVM_JIT_RV_VOID, -1);
750
8.97k
}
751
752
753
static MVMint32 consume_reprop(MVMThreadContext *tc, MVMJitGraph *jg,
754
22.4k
                               MVMSpeshIterator *iterator, MVMSpeshIns *ins) {
755
22.4k
    MVMint16 op = ins->info->opcode;
756
22.4k
    MVMSpeshOperand type_operand;
757
22.4k
    MVMSpeshFacts *type_facts = 0;
758
22.4k
    MVMint32 alternative = 0;
759
22.4k
760
22.4k
    switch (op) {
761
9.72k
        case MVM_OP_unshift_i:
762
9.72k
        case MVM_OP_unshift_n:
763
9.72k
        case MVM_OP_unshift_s:
764
9.72k
        case MVM_OP_unshift_o:
765
9.72k
        case MVM_OP_bindkey_i:
766
9.72k
        case MVM_OP_bindkey_n:
767
9.72k
        case MVM_OP_bindkey_s:
768
9.72k
        case MVM_OP_bindkey_o:
769
9.72k
        case MVM_OP_bindpos_i:
770
9.72k
        case MVM_OP_bindpos_n:
771
9.72k
        case MVM_OP_bindpos_s:
772
9.72k
        case MVM_OP_bindpos_o:
773
9.72k
        case MVM_OP_bindattr_i:
774
9.72k
        case MVM_OP_bindattr_n:
775
9.72k
        case MVM_OP_bindattr_s:
776
9.72k
        case MVM_OP_bindattr_o:
777
9.72k
        case MVM_OP_bindattrs_i:
778
9.72k
        case MVM_OP_bindattrs_n:
779
9.72k
        case MVM_OP_bindattrs_s:
780
9.72k
        case MVM_OP_bindattrs_o:
781
9.72k
        case MVM_OP_push_i:
782
9.72k
        case MVM_OP_push_n:
783
9.72k
        case MVM_OP_push_s:
784
9.72k
        case MVM_OP_push_o:
785
9.72k
        case MVM_OP_deletekey:
786
9.72k
        case MVM_OP_setelemspos:
787
9.72k
        case MVM_OP_splice:
788
9.72k
            type_operand = ins->operands[0];
789
9.72k
            break;
790
12.7k
        case MVM_OP_atpos_i:
791
12.7k
        case MVM_OP_atpos_n:
792
12.7k
        case MVM_OP_atpos_s:
793
12.7k
        case MVM_OP_atpos_o:
794
12.7k
        case MVM_OP_atkey_i:
795
12.7k
        case MVM_OP_atkey_n:
796
12.7k
        case MVM_OP_atkey_s:
797
12.7k
        case MVM_OP_atkey_o:
798
12.7k
        case MVM_OP_elems:
799
12.7k
        case MVM_OP_shift_i:
800
12.7k
        case MVM_OP_shift_n:
801
12.7k
        case MVM_OP_shift_s:
802
12.7k
        case MVM_OP_shift_o:
803
12.7k
        case MVM_OP_pop_i:
804
12.7k
        case MVM_OP_pop_n:
805
12.7k
        case MVM_OP_pop_s:
806
12.7k
        case MVM_OP_pop_o:
807
12.7k
        case MVM_OP_existskey:
808
12.7k
        case MVM_OP_existspos:
809
12.7k
        case MVM_OP_getattr_i:
810
12.7k
        case MVM_OP_getattr_n:
811
12.7k
        case MVM_OP_getattr_s:
812
12.7k
        case MVM_OP_getattr_o:
813
12.7k
        case MVM_OP_getattrs_i:
814
12.7k
        case MVM_OP_getattrs_n:
815
12.7k
        case MVM_OP_getattrs_s:
816
12.7k
        case MVM_OP_getattrs_o:
817
12.7k
        case MVM_OP_attrinited:
818
12.7k
        case MVM_OP_hintfor:
819
12.7k
        case MVM_OP_slice:
820
12.7k
            type_operand = ins->operands[1];
821
12.7k
            break;
822
0
        case MVM_OP_box_i:
823
0
        case MVM_OP_box_n:
824
0
        case MVM_OP_box_s:
825
0
            type_operand = ins->operands[2];
826
0
            break;
827
0
        default:
828
0
            MVM_jit_log(tc, "devirt: couldn't figure out type operand for op %s\n", ins->info->name);
829
0
            return 0;
830
22.4k
831
22.4k
    }
832
22.4k
833
22.4k
    type_facts = MVM_spesh_get_facts(tc, jg->sg, type_operand);
834
22.4k
835
22.4k
    if (type_facts && type_facts->flags & MVM_SPESH_FACT_KNOWN_TYPE && type_facts->type &&
836
6.86k
            type_facts->flags & MVM_SPESH_FACT_CONCRETE) {
837
6.84k
        switch(op) {
838
1.03k
            case MVM_OP_atkey_i:
839
1.03k
            case MVM_OP_atkey_n:
840
1.03k
            case MVM_OP_atkey_s:
841
1.03k
            case MVM_OP_atkey_o:
842
1.03k
                alternative = 1;
843
1.76k
            case MVM_OP_atpos_i:
844
1.76k
            case MVM_OP_atpos_n:
845
1.76k
            case MVM_OP_atpos_s:
846
1.76k
            case MVM_OP_atpos_o: {
847
1.76k
                /* atpos_i             w(int64) r(obj) r(int64) */
848
1.76k
                /* atkey_i             w(int64) r(obj) r(str)*/
849
1.76k
850
1.76k
                /*void (*at_pos) (MVMThreadContext *tc, MVMSTable *st,
851
1.76k
                 *    MVMObject *root, void *data, MVMint64 index,
852
1.76k
                 *    MVMRegister *result, MVMuint16 kind);*/
853
1.76k
854
1.76k
                /*REPR(obj)->pos_funcs.at_pos(tc, STABLE(obj), obj, OBJECT_BODY(obj),
855
1.76k
                 *  idx, &value, MVM_reg_int64);*/
856
1.76k
857
1.76k
                MVMint32 dst      = ins->operands[0].reg.orig;
858
1.76k
                MVMint32 invocant = ins->operands[1].reg.orig;
859
1.76k
                MVMint32 value    = ins->operands[2].reg.orig;
860
1.76k
861
1.76k
                void *function = alternative
862
1.03k
                    ? (void *)((MVMObject*)type_facts->type)->st->REPR->ass_funcs.at_key
863
729
                    : (void *)((MVMObject*)type_facts->type)->st->REPR->pos_funcs.at_pos;
864
1.76k
865
1.76k
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
866
1.76k
                                         { MVM_JIT_REG_STABLE,  invocant },
867
1.76k
                                         { MVM_JIT_REG_VAL,     invocant },
868
1.76k
                                         { MVM_JIT_REG_OBJBODY, invocant },
869
1.76k
                                         { MVM_JIT_REG_VAL,  value },
870
1.76k
                                         { MVM_JIT_REG_ADDR, dst },
871
1.76k
                                         { MVM_JIT_LITERAL,
872
1.76k
                                             op == MVM_OP_atpos_i || op == MVM_OP_atkey_i ? MVM_reg_int64 :
873
1.70k
                                             op == MVM_OP_atpos_n || op == MVM_OP_atkey_n ? MVM_reg_num64 :
874
1.70k
                                             op == MVM_OP_atpos_s || op == MVM_OP_atkey_s ? MVM_reg_str :
875
1.70k
                                                                    MVM_reg_obj } };
876
1.76k
                jg_append_call_c(tc, jg, function, 7, args, MVM_JIT_RV_VOID, -1);
877
1.76k
                MVM_jit_log(tc, "devirt: emitted an %s via consume_reprop\n", ins->info->name);
878
1.76k
                return 1;
879
1.76k
            }
880
182
            case MVM_OP_bindkey_i:
881
182
            case MVM_OP_bindkey_n:
882
182
            case MVM_OP_bindkey_s:
883
182
            case MVM_OP_bindkey_o:
884
182
                alternative = 1;
885
305
            case MVM_OP_bindpos_i:
886
305
            case MVM_OP_bindpos_n:
887
305
            case MVM_OP_bindpos_s:
888
305
            case MVM_OP_bindpos_o: {
889
305
                /*bindpos_i           r(obj) r(int64) r(int64)*/
890
305
                /*bindkey_i           r(obj) r(str) r(int64)*/
891
305
892
305
                /* void (*bind_pos) (MVMThreadContext *tc, MVMSTable *st,
893
305
                      MVMObject *root, void *data, MVMint64 index,
894
305
                      MVMRegister value, MVMuint16 kind); */
895
305
896
305
                /* void (*bind_key) (MVMThreadContext *tc, MVMSTable *st, MVMObject *root,
897
305
                      void *data, MVMObject *key, MVMRegister value, MVMuint16 kind); */
898
305
899
305
                MVMint32 invocant = ins->operands[0].reg.orig;
900
305
                MVMint32 key      = ins->operands[1].reg.orig;
901
305
                MVMint32 value    = ins->operands[2].reg.orig;
902
305
903
305
                void *function = alternative
904
182
                    ? (void *)((MVMObject*)type_facts->type)->st->REPR->ass_funcs.bind_key
905
123
                    : (void *)((MVMObject*)type_facts->type)->st->REPR->pos_funcs.bind_pos;
906
305
907
305
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
908
305
                                         { MVM_JIT_REG_STABLE,  invocant },
909
305
                                         { MVM_JIT_REG_VAL,     invocant },
910
305
                                         { MVM_JIT_REG_OBJBODY, invocant },
911
305
                                         { MVM_JIT_REG_VAL, key },
912
305
                                         { MVM_JIT_REG_VAL, value },
913
305
                                         { MVM_JIT_LITERAL,
914
305
                                             op == MVM_OP_bindpos_i || op == MVM_OP_bindkey_i ? MVM_reg_int64 :
915
305
                                             op == MVM_OP_bindpos_n || op == MVM_OP_bindkey_n ? MVM_reg_num64 :
916
305
                                             op == MVM_OP_bindpos_s || op == MVM_OP_bindkey_s ? MVM_reg_str :
917
305
                                                                    MVM_reg_obj } };
918
305
                jg_append_call_c(tc, jg, function, 7, args, MVM_JIT_RV_VOID, -1);
919
305
                MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
920
305
                jg_sc_wb(tc, jg, ins->operands[0]);
921
305
                return 1;
922
305
            }
923
1.27k
            case MVM_OP_elems: {
924
1.27k
                /*elems               w(int64) r(obj) :pure*/
925
1.27k
926
1.27k
                MVMint32 dst       = ins->operands[0].reg.orig;
927
1.27k
                MVMint32 invocant  = ins->operands[1].reg.orig;
928
1.27k
929
1.27k
                void *function = ((MVMObject*)type_facts->type)->st->REPR->elems;
930
1.27k
931
1.27k
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
932
1.27k
                                         { MVM_JIT_REG_STABLE,  invocant },
933
1.27k
                                         { MVM_JIT_REG_VAL,     invocant },
934
1.27k
                                         { MVM_JIT_REG_OBJBODY, invocant } };
935
1.27k
                jg_append_call_c(tc, jg, function, 4, args, MVM_JIT_RV_INT, dst);
936
1.27k
                MVM_jit_log(tc, "devirt: emitted an elems via consume_reprop\n");
937
1.27k
                return 1;
938
305
            }
939
880
            case MVM_OP_getattr_i:
940
880
            case MVM_OP_getattr_n:
941
880
            case MVM_OP_getattr_s:
942
880
            case MVM_OP_getattr_o:
943
880
            case MVM_OP_getattrs_i:
944
880
            case MVM_OP_getattrs_n:
945
880
            case MVM_OP_getattrs_s:
946
880
            case MVM_OP_getattrs_o: {
947
880
                /*getattr_i           w(int64) r(obj) r(obj) str int16*/
948
880
                /*getattrs_i          w(int64) r(obj) r(obj) r(str)*/
949
880
                /*static void get_attribute(MVMThreadContext *tc, MVMSTable *st, MVMObject *root,*/
950
880
                /*        void *data, MVMObject *class_handle, MVMString *name, MVMint64 hint,*/
951
880
                /*      MVMRegister *result_reg, MVMuint16 kind) {*/
952
880
953
880
                /* reprconv and interp.c check for concreteness, so we'd either
954
880
                 * have to emit a bit of code to check and throw or just rely
955
880
                 * on a concreteness fact */
956
880
957
880
                MVMSpeshFacts *object_facts = MVM_spesh_get_facts(tc, jg->sg, ins->operands[1]);
958
880
959
880
                if (object_facts->flags & MVM_SPESH_FACT_CONCRETE) {
960
880
                    MVMint32 is_name_direct = ins->info->num_operands == 5;
961
880
962
880
                    MVMint32 dst       = ins->operands[0].reg.orig;
963
880
                    MVMint32 invocant  = ins->operands[1].reg.orig;
964
880
                    MVMint32 type      = ins->operands[2].reg.orig;
965
880
                    MVMint32 attrname  = is_name_direct ? ins->operands[3].lit_str_idx : ins->operands[3].reg.orig;
966
880
                    MVMint32 attrhint  = is_name_direct ? ins->operands[4].lit_i16 : -1;
967
880
968
880
                    void *function = ((MVMObject*)type_facts->type)->st->REPR->attr_funcs.get_attribute;
969
880
970
880
                    MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
971
880
                                             { MVM_JIT_REG_STABLE,  invocant },
972
880
                                             { MVM_JIT_REG_VAL,     invocant },
973
880
                                             { MVM_JIT_REG_OBJBODY, invocant },
974
880
                                             { MVM_JIT_REG_VAL,     type },
975
880
                                             { is_name_direct ? MVM_JIT_STR_IDX : MVM_JIT_REG_VAL,
976
880
                                                                    attrname },
977
880
                                             { MVM_JIT_LITERAL,     attrhint },
978
880
                                             { MVM_JIT_REG_ADDR,    dst },
979
880
                                             { MVM_JIT_LITERAL,
980
880
                                                 op == MVM_OP_getattr_i || op == MVM_OP_getattrs_i ? MVM_reg_int64 :
981
516
                                                 op == MVM_OP_getattr_n || op == MVM_OP_getattrs_n ? MVM_reg_num64 :
982
516
                                                 op == MVM_OP_getattr_s || op == MVM_OP_getattrs_s ? MVM_reg_str :
983
514
                                                                        MVM_reg_obj } };
984
880
                    MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
985
880
                    jg_append_call_c(tc, jg, function, 9, args, MVM_JIT_RV_VOID, -1);
986
880
987
880
                    return 1;
988
0
                } else {
989
0
                    MVM_jit_log(tc, "devirt: couldn't %s; concreteness not sure\n", ins->info->name);
990
0
                    break;
991
0
                }
992
880
            }
993
0
            case MVM_OP_attrinited: {
994
0
                /*attrinited          w(int64) r(obj) r(obj) r(str)*/
995
0
996
0
                /*MVMint64 (*is_attribute_initialized) (MVMThreadContext *tc, MVMSTable *st,*/
997
0
                    /*void *data, MVMObject *class_handle, MVMString *name,*/
998
0
                    /*MVMint64 hint);*/
999
0
1000
0
                /* reprconv and interp.c check for concreteness, so we'd either
1001
0
                 * have to emit a bit of code to check and throw or just rely
1002
0
                 * on a concreteness fact */
1003
0
1004
0
                MVMSpeshFacts *object_facts = MVM_spesh_get_facts(tc, jg->sg, ins->operands[1]);
1005
0
1006
0
                if (object_facts->flags & MVM_SPESH_FACT_CONCRETE) {
1007
0
                    MVMint32 dst       = ins->operands[0].reg.orig;
1008
0
                    MVMint32 invocant  = ins->operands[1].reg.orig;
1009
0
                    MVMint32 type      = ins->operands[2].reg.orig;
1010
0
                    MVMint32 attrname  = ins->operands[3].reg.orig;
1011
0
                    MVMint32 attrhint  = MVM_NO_HINT;
1012
0
1013
0
                    void *function = ((MVMObject*)type_facts->type)->st->REPR->attr_funcs.is_attribute_initialized;
1014
0
1015
0
                    MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1016
0
                                             { MVM_JIT_REG_STABLE,  invocant },
1017
0
                                             { MVM_JIT_REG_OBJBODY, invocant },
1018
0
                                             { MVM_JIT_REG_VAL,     type },
1019
0
                                             { MVM_JIT_REG_VAL,     attrname },
1020
0
                                             { MVM_JIT_LITERAL,     attrhint } };
1021
0
                    MVM_jit_log(tc, "devirt: emitted a %s via jgb_consume_reprop\n", ins->info->name);
1022
0
                    jg_append_call_c(tc, jg, function, 6, args, MVM_JIT_RV_INT, dst);
1023
0
1024
0
                    return 1;
1025
0
                } else {
1026
0
                    MVM_jit_log(tc, "devirt: couldn't %s; concreteness not sure\n", ins->info->name);
1027
0
                    break;
1028
0
                }
1029
0
            }
1030
398
            case MVM_OP_bindattr_i:
1031
398
            case MVM_OP_bindattr_n:
1032
398
            case MVM_OP_bindattr_s:
1033
398
            case MVM_OP_bindattr_o:
1034
398
            case MVM_OP_bindattrs_i:
1035
398
            case MVM_OP_bindattrs_n:
1036
398
            case MVM_OP_bindattrs_s:
1037
398
            case MVM_OP_bindattrs_o: {
1038
398
                /*bindattr_n          r(obj) r(obj) str    r(num64) int16*/
1039
398
                /*bindattrs_n         r(obj) r(obj) r(str) r(num64)*/
1040
398
1041
398
                /* static void bind_attribute(MVMThreadContext *tc, MVMSTable *st, MVMObject *root,
1042
398
                 *        void *data, MVMObject *class_handle, MVMString *name, MVMint64 hint,
1043
398
                 *        MVMRegister value_reg, MVMuint16 kind) */
1044
398
1045
398
                /* reprconv and interp.c check for concreteness, so we'd either
1046
398
                 * have to emit a bit of code to check and throw or just rely
1047
398
                 * on a concreteness fact */
1048
398
1049
398
                MVMSpeshFacts *object_facts = MVM_spesh_get_facts(tc, jg->sg, ins->operands[1]);
1050
398
1051
398
                if (object_facts->flags & MVM_SPESH_FACT_CONCRETE) {
1052
0
                    MVMint32 is_name_direct = ins->info->num_operands == 5;
1053
0
1054
0
                    MVMint32 invocant  = ins->operands[0].reg.orig;
1055
0
                    MVMint32 type      = ins->operands[1].reg.orig;
1056
0
                    MVMint32 attrname  = is_name_direct ? ins->operands[2].lit_str_idx : ins->operands[2].reg.orig;
1057
0
                    MVMint32 attrhint  = is_name_direct ? ins->operands[4].lit_i16 : -1;
1058
0
                    MVMint32 value     = ins->operands[3].reg.orig;
1059
0
1060
0
                    void *function = ((MVMObject*)type_facts->type)->st->REPR->attr_funcs.bind_attribute;
1061
0
1062
0
                    MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1063
0
                                             { MVM_JIT_REG_STABLE,  invocant },
1064
0
                                             { MVM_JIT_REG_VAL,     invocant },
1065
0
                                             { MVM_JIT_REG_OBJBODY, invocant },
1066
0
                                             { MVM_JIT_REG_VAL,     type },
1067
0
                                             { is_name_direct ? MVM_JIT_STR_IDX : MVM_JIT_REG_VAL,
1068
0
                                                                    attrname },
1069
0
                                             { MVM_JIT_LITERAL,     attrhint },
1070
0
                                             { MVM_JIT_REG_VAL,     value },
1071
0
                                             { MVM_JIT_LITERAL,
1072
0
                                                 op == MVM_OP_bindattr_i || op == MVM_OP_bindattrs_i ? MVM_reg_int64 :
1073
0
                                                 op == MVM_OP_bindattr_n || op == MVM_OP_bindattrs_n ? MVM_reg_num64 :
1074
0
                                                 op == MVM_OP_bindattr_s || op == MVM_OP_bindattrs_s ? MVM_reg_str :
1075
0
                                                                        MVM_reg_obj } };
1076
0
                    MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
1077
0
                    jg_append_call_c(tc, jg, function, 9, args, MVM_JIT_RV_VOID, -1);
1078
0
                    jg_sc_wb(tc, jg, ins->operands[0]);
1079
0
                    return 1;
1080
398
                } else {
1081
398
                    MVM_jit_log(tc, "devirt: couldn't %s; concreteness not sure\n", ins->info->name);
1082
398
                    break;
1083
398
                }
1084
398
            }
1085
0
            case MVM_OP_hintfor: {
1086
0
                /*
1087
0
                 *  MVMint64 (*hint_for) (MVMThreadContext *tc, MVMSTable *st,
1088
0
                 *      MVMObject *class_handle, MVMString *name);
1089
0
                 */
1090
0
1091
0
                MVMint32 result    = ins->operands[0].reg.orig;
1092
0
                MVMint32 type      = ins->operands[1].reg.orig;
1093
0
                MVMint32 attrname  = ins->operands[2].reg.orig;
1094
0
1095
0
                void *function = ((MVMObject*)type_facts->type)->st->REPR->attr_funcs.hint_for;
1096
0
1097
0
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1098
0
                                         { MVM_JIT_REG_STABLE,  type },
1099
0
                                         { MVM_JIT_REG_VAL,     type },
1100
0
                                         { MVM_JIT_REG_VAL,     attrname } };
1101
0
1102
0
1103
0
                MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
1104
0
                jg_append_call_c(tc, jg, function, 4, args, MVM_JIT_RV_INT, result);
1105
0
                return 1;
1106
0
                break;
1107
398
            }
1108
1.90k
            case MVM_OP_push_i:
1109
1.90k
            case MVM_OP_push_n:
1110
1.90k
            case MVM_OP_push_s:
1111
1.90k
            case MVM_OP_push_o:
1112
1.90k
                alternative = 1;
1113
1.90k
            case MVM_OP_unshift_i:
1114
1.90k
            case MVM_OP_unshift_n:
1115
1.90k
            case MVM_OP_unshift_s:
1116
1.90k
            case MVM_OP_unshift_o: {
1117
1.90k
                MVMint32 invocant = ins->operands[0].reg.orig;
1118
1.90k
                MVMint32 value    = ins->operands[1].reg.orig;
1119
1.90k
1120
1.90k
                void *function = alternative
1121
1.90k
                    ? (void *)((MVMObject*)type_facts->type)->st->REPR->pos_funcs.push
1122
5
                    : (void *)((MVMObject*)type_facts->type)->st->REPR->pos_funcs.unshift;
1123
1.90k
1124
1.90k
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1125
1.90k
                                         { MVM_JIT_REG_STABLE,  invocant },
1126
1.90k
                                         { MVM_JIT_REG_VAL,     invocant },
1127
1.90k
                                         { MVM_JIT_REG_OBJBODY, invocant },
1128
1.90k
                                         { MVM_JIT_REG_VAL,     value },
1129
1.90k
                                         { MVM_JIT_LITERAL,
1130
1.90k
                                             op == MVM_OP_push_i || op == MVM_OP_unshift_i ? MVM_reg_int64 :
1131
438
                                             op == MVM_OP_push_n || op == MVM_OP_unshift_n ? MVM_reg_num64 :
1132
438
                                             op == MVM_OP_push_s || op == MVM_OP_unshift_s ? MVM_reg_str :
1133
438
                                                                    MVM_reg_obj } };
1134
1.90k
                jg_append_call_c(tc, jg, function, 6, args, MVM_JIT_RV_VOID, -1);
1135
1.90k
                MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
1136
1.90k
                jg_sc_wb(tc, jg, ins->operands[0]);
1137
1.90k
                return 1;
1138
1.90k
            }
1139
0
            case MVM_OP_pop_i:
1140
0
            case MVM_OP_pop_n:
1141
0
            case MVM_OP_pop_s:
1142
0
            case MVM_OP_pop_o:
1143
0
                alternative = 1;
1144
1
            case MVM_OP_shift_i:
1145
1
            case MVM_OP_shift_n:
1146
1
            case MVM_OP_shift_s:
1147
1
            case MVM_OP_shift_o: {
1148
1
                MVMint32 dst      = ins->operands[0].reg.orig;
1149
1
                MVMint32 invocant = ins->operands[1].reg.orig;
1150
1
1151
1
                void *function = alternative
1152
0
                    ? (void *)((MVMObject*)type_facts->type)->st->REPR->pos_funcs.pop
1153
1
                    : (void *)((MVMObject*)type_facts->type)->st->REPR->pos_funcs.shift;
1154
1
1155
1
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1156
1
                                         { MVM_JIT_REG_STABLE,  invocant },
1157
1
                                         { MVM_JIT_REG_VAL,     invocant },
1158
1
                                         { MVM_JIT_REG_OBJBODY, invocant },
1159
1
                                         { MVM_JIT_REG_ADDR,     dst },
1160
1
                                         { MVM_JIT_LITERAL,
1161
1
                                             op == MVM_OP_pop_i || op == MVM_OP_shift_i ? MVM_reg_int64 :
1162
1
                                             op == MVM_OP_pop_n || op == MVM_OP_shift_n ? MVM_reg_num64 :
1163
1
                                             op == MVM_OP_pop_s || op == MVM_OP_shift_s ? MVM_reg_str :
1164
1
                                                                    MVM_reg_obj } };
1165
1
                jg_append_call_c(tc, jg, function, 6, args, MVM_JIT_RV_VOID, -1);
1166
1
                MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
1167
1
                return 1;
1168
1
            }
1169
178
            case MVM_OP_setelemspos: {
1170
178
                MVMint32 invocant = ins->operands[0].reg.orig;
1171
178
                MVMint32 amount   = ins->operands[1].reg.orig;
1172
178
1173
178
                void *function = ((MVMObject*)type_facts->type)->st->REPR->pos_funcs.set_elems;
1174
178
1175
178
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1176
178
                                         { MVM_JIT_REG_STABLE,  invocant },
1177
178
                                         { MVM_JIT_REG_VAL,     invocant },
1178
178
                                         { MVM_JIT_REG_OBJBODY, invocant },
1179
178
                                         { MVM_JIT_REG_VAL,     amount } };
1180
178
                jg_append_call_c(tc, jg, function, 5, args, MVM_JIT_RV_VOID, -1);
1181
178
                MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
1182
178
                return 1;
1183
1
            }
1184
64
            case MVM_OP_existskey: {
1185
64
                /*existskey           w(int64) r(obj) r(str) :pure*/
1186
64
                MVMint32 dst      = ins->operands[0].reg.orig;
1187
64
                MVMint32 invocant = ins->operands[1].reg.orig;
1188
64
                MVMint32 keyidx   = ins->operands[2].reg.orig;
1189
64
1190
64
                void *function = (void *)((MVMObject*)type_facts->type)->st->REPR->ass_funcs.exists_key;
1191
64
1192
64
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1193
64
                                         { MVM_JIT_REG_STABLE,  invocant },
1194
64
                                         { MVM_JIT_REG_VAL,     invocant },
1195
64
                                         { MVM_JIT_REG_OBJBODY, invocant },
1196
64
                                         { MVM_JIT_REG_VAL,     keyidx } };
1197
64
                jg_append_call_c(tc, jg, function, 5, args, MVM_JIT_RV_INT, dst);
1198
64
                MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
1199
64
                return 1;
1200
1
            }
1201
36
            case MVM_OP_splice: {
1202
36
                MVMint16 invocant = ins->operands[0].reg.orig;
1203
36
                MVMint16 source   = ins->operands[1].reg.orig;
1204
36
                MVMint16 offset   = ins->operands[2].reg.orig;
1205
36
                MVMint16 count    = ins->operands[3].reg.orig;
1206
36
1207
36
                void *function = ((MVMObject*)type_facts->type)->st->REPR->pos_funcs.splice;
1208
36
1209
36
                MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1210
36
                                         { MVM_JIT_REG_STABLE,  invocant },
1211
36
                                         { MVM_JIT_REG_VAL,     invocant },
1212
36
                                         { MVM_JIT_REG_OBJBODY, invocant },
1213
36
                                         { MVM_JIT_REG_VAL,     source   },
1214
36
                                         { MVM_JIT_REG_VAL,     offset   },
1215
36
                                         { MVM_JIT_REG_VAL,     count    } };
1216
36
                jg_append_call_c(tc, jg, function, 7, args, MVM_JIT_RV_VOID, -1);
1217
36
                MVM_jit_log(tc, "devirt: emitted a %s via consume_reprop\n", ins->info->name);
1218
36
                return 1;
1219
1
            }
1220
46
            default:
1221
46
                MVM_jit_log(tc, "devirt: please implement emitting repr op %s\n", ins->info->name);
1222
6.84k
        }
1223
15.6k
    } else {
1224
15.6k
        MVM_jit_log(tc, "devirt: repr op %s couldn't be devirtualized: type unknown\n", ins->info->name);
1225
15.6k
    }
1226
22.4k
1227
16.0k
skipdevirt:
1228
16.0k
1229
16.0k
    switch(op) {
1230
1.65k
    case MVM_OP_push_i:
1231
1.65k
    case MVM_OP_push_s:
1232
1.65k
    case MVM_OP_push_o:
1233
1.65k
    case MVM_OP_unshift_i:
1234
1.65k
    case MVM_OP_unshift_s:
1235
1.65k
    case MVM_OP_unshift_o: {
1236
1.65k
        MVMint32 invocant = ins->operands[0].reg.orig;
1237
1.65k
        MVMint32 value    = ins->operands[1].reg.orig;
1238
1.65k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1239
1.65k
                                 { MVM_JIT_REG_VAL, invocant },
1240
1.65k
                                 { MVM_JIT_REG_VAL, value } };
1241
1.65k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
1242
1.65k
        jg_sc_wb(tc, jg, ins->operands[0]);
1243
1.65k
        break;
1244
1.65k
    }
1245
0
    case MVM_OP_unshift_n:
1246
0
    case MVM_OP_push_n: {
1247
0
        MVMint32 invocant = ins->operands[0].reg.orig;
1248
0
        MVMint32 value    = ins->operands[1].reg.orig;
1249
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1250
0
                                 { MVM_JIT_REG_VAL, invocant },
1251
0
                                 { MVM_JIT_REG_VAL_F, value } };
1252
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
1253
0
        break;
1254
0
    }
1255
14
    case MVM_OP_shift_s:
1256
14
    case MVM_OP_pop_s:
1257
14
    case MVM_OP_shift_o:
1258
14
    case MVM_OP_pop_o: {
1259
14
        MVMint16 dst = ins->operands[0].reg.orig;
1260
14
        MVMint32 invocant = ins->operands[1].reg.orig;
1261
14
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1262
14
                                 { MVM_JIT_REG_VAL, invocant } };
1263
14
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
1264
14
        break;
1265
14
    }
1266
0
    case MVM_OP_shift_i:
1267
0
    case MVM_OP_pop_i: {
1268
0
        MVMint16 dst = ins->operands[0].reg.orig;
1269
0
        MVMint32 invocant = ins->operands[1].reg.orig;
1270
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1271
0
                                 { MVM_JIT_REG_VAL, invocant } };
1272
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
1273
0
        break;
1274
0
    }
1275
0
    case MVM_OP_shift_n:
1276
0
    case MVM_OP_pop_n: {
1277
0
        MVMint16 dst = ins->operands[0].reg.orig;
1278
0
        MVMint32 invocant = ins->operands[1].reg.orig;
1279
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1280
0
                                 { MVM_JIT_REG_VAL, invocant } };
1281
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_NUM, dst);
1282
0
        break;
1283
0
    }
1284
372
    case MVM_OP_deletekey:
1285
372
    case MVM_OP_setelemspos: {
1286
372
        MVMint32 invocant = ins->operands[0].reg.orig;
1287
372
        MVMint32 key_or_val = ins->operands[1].reg.orig;
1288
372
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1289
372
                                 { MVM_JIT_REG_VAL, invocant },
1290
372
                                 { MVM_JIT_REG_VAL, key_or_val } };
1291
372
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
1292
372
        break;
1293
372
    }
1294
60
    case MVM_OP_existskey: {
1295
60
        MVMint16 dst = ins->operands[0].reg.orig;
1296
60
        MVMint32 invocant = ins->operands[1].reg.orig;
1297
60
        MVMint32 key = ins->operands[2].reg.orig;
1298
60
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1299
60
                                 { MVM_JIT_REG_VAL, invocant },
1300
60
                                 { MVM_JIT_REG_VAL, key } };
1301
60
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, dst);
1302
60
        break;
1303
372
    }
1304
0
    case MVM_OP_slice: {
1305
0
        MVMint16 dst   = ins->operands[0].reg.orig;
1306
0
        MVMint16 src   = ins->operands[1].reg.orig;
1307
0
        MVMint16 start = ins->operands[2].reg.orig;
1308
0
        MVMint16 end   = ins->operands[3].reg.orig;
1309
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1310
0
                                 { MVM_JIT_REG_VAL, src   },
1311
0
                                 { MVM_JIT_REG_VAL, start },
1312
0
                                 { MVM_JIT_REG_VAL, end   } };
1313
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
1314
0
        break;
1315
372
    }
1316
163
    case MVM_OP_splice: {
1317
163
        MVMint16 invocant = ins->operands[0].reg.orig;
1318
163
        MVMint16 source = ins->operands[1].reg.orig;
1319
163
        MVMint16 offset = ins->operands[2].reg.orig;
1320
163
        MVMint16 count = ins->operands[3].reg.orig;
1321
163
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1322
163
                                 { MVM_JIT_REG_VAL, invocant },
1323
163
                                 { MVM_JIT_REG_VAL, source },
1324
163
                                 { MVM_JIT_REG_VAL, offset },
1325
163
                                 { MVM_JIT_REG_VAL, count } };
1326
163
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, MVM_JIT_RV_VOID, -1);
1327
163
        break;
1328
372
    }
1329
88
    case MVM_OP_existspos:
1330
88
    case MVM_OP_atkey_i:
1331
88
    case MVM_OP_atpos_i: {
1332
88
        MVMint16 dst = ins->operands[0].reg.orig;
1333
88
        MVMint32 invocant = ins->operands[1].reg.orig;
1334
88
        MVMint32 position = ins->operands[2].reg.orig;
1335
88
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1336
88
                                 { MVM_JIT_REG_VAL, invocant },
1337
88
                                 { MVM_JIT_REG_VAL, position } };
1338
88
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, dst);
1339
88
        break;
1340
88
    }
1341
0
    case MVM_OP_atkey_n:
1342
0
    case MVM_OP_atpos_n: {
1343
0
        MVMint16 dst = ins->operands[0].reg.orig;
1344
0
        MVMint32 invocant = ins->operands[1].reg.orig;
1345
0
        MVMint32 position = ins->operands[2].reg.orig;
1346
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1347
0
                                 { MVM_JIT_REG_VAL, invocant },
1348
0
                                 { MVM_JIT_REG_VAL, position } };
1349
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_NUM, dst);
1350
0
        break;
1351
0
    }
1352
3.12k
    case MVM_OP_atpos_o:
1353
3.12k
    case MVM_OP_atkey_o:
1354
3.12k
    case MVM_OP_atkey_s:
1355
3.12k
    case MVM_OP_atpos_s: {
1356
3.12k
        MVMint16 dst = ins->operands[0].reg.orig;
1357
3.12k
        MVMint32 invocant = ins->operands[1].reg.orig;
1358
3.12k
        MVMint32 position = ins->operands[2].reg.orig;
1359
3.12k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1360
3.12k
                                 { MVM_JIT_REG_VAL, invocant },
1361
3.12k
                                 { MVM_JIT_REG_VAL, position } };
1362
3.12k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
1363
3.12k
        break;
1364
3.12k
    }
1365
0
    case MVM_OP_bindkey_n:
1366
0
    case MVM_OP_bindpos_n: {
1367
0
        MVMint32 invocant = ins->operands[0].reg.orig;
1368
0
        MVMint32 key_pos = ins->operands[1].reg.orig;
1369
0
        MVMint32 value = ins->operands[2].reg.orig;
1370
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1371
0
                                 { MVM_JIT_REG_VAL, invocant },
1372
0
                                 { MVM_JIT_REG_VAL, key_pos },
1373
0
                                 { MVM_JIT_REG_VAL_F, value } };
1374
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
1375
0
        jg_sc_wb(tc, jg, ins->operands[0]);
1376
0
        break;
1377
0
    }
1378
1.60k
    case MVM_OP_bindpos_i:
1379
1.60k
    case MVM_OP_bindpos_s:
1380
1.60k
    case MVM_OP_bindpos_o:
1381
1.60k
    case MVM_OP_bindkey_i:
1382
1.60k
    case MVM_OP_bindkey_s:
1383
1.60k
    case MVM_OP_bindkey_o: {
1384
1.60k
        MVMint32 invocant = ins->operands[0].reg.orig;
1385
1.60k
        MVMint32 key_pos = ins->operands[1].reg.orig;
1386
1.60k
        MVMint32 value = ins->operands[2].reg.orig;
1387
1.60k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1388
1.60k
                                 { MVM_JIT_REG_VAL, invocant },
1389
1.60k
                                 { MVM_JIT_REG_VAL, key_pos },
1390
1.60k
                                 { MVM_JIT_REG_VAL, value } };
1391
1.60k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
1392
1.60k
        jg_sc_wb(tc, jg, ins->operands[0]);
1393
1.60k
        break;
1394
1.60k
    }
1395
4.43k
    case MVM_OP_getattr_i:
1396
4.43k
    case MVM_OP_getattr_n:
1397
4.43k
    case MVM_OP_getattr_s:
1398
4.43k
    case MVM_OP_getattr_o: {
1399
4.43k
        MVMuint16 kind = op == MVM_OP_getattr_i ? MVM_JIT_RV_INT :
1400
2.36k
                         op == MVM_OP_getattr_n ? MVM_JIT_RV_NUM :
1401
2.36k
                         op == MVM_OP_getattr_s ? MVM_JIT_RV_PTR :
1402
1.88k
                         /* MVM_OP_getattr_o ? */ MVM_JIT_RV_PTR;
1403
4.43k
        MVMint16 dst = ins->operands[0].reg.orig;
1404
4.43k
        MVMint16 obj = ins->operands[1].reg.orig;
1405
4.43k
        MVMint16 typ = ins->operands[2].reg.orig;
1406
4.43k
        MVMuint32 str_idx = ins->operands[3].lit_str_idx;
1407
4.43k
        MVMint16 hint = ins->operands[4].lit_i16;
1408
4.43k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1409
4.43k
                                 { MVM_JIT_REG_VAL, obj },
1410
4.43k
                                 { MVM_JIT_REG_VAL, typ },
1411
4.43k
                                 { MVM_JIT_STR_IDX, str_idx },
1412
4.43k
                                 { MVM_JIT_LITERAL, hint }};
1413
4.43k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, kind, dst);
1414
4.43k
        break;
1415
4.43k
    }
1416
98
    case MVM_OP_getattrs_i:
1417
98
    case MVM_OP_getattrs_n:
1418
98
    case MVM_OP_getattrs_s:
1419
98
    case MVM_OP_getattrs_o: {
1420
98
        MVMuint16 kind = op == MVM_OP_getattrs_i ? MVM_JIT_RV_INT :
1421
98
                         op == MVM_OP_getattrs_n ? MVM_JIT_RV_NUM :
1422
98
                         op == MVM_OP_getattrs_s ? MVM_JIT_RV_PTR :
1423
98
                         /* MVM_OP_getattrs_o ? */ MVM_JIT_RV_PTR;
1424
98
        MVMint16 dst = ins->operands[0].reg.orig;
1425
98
        MVMint16 obj = ins->operands[1].reg.orig;
1426
98
        MVMint16 typ = ins->operands[2].reg.orig;
1427
98
        MVMint16 str = ins->operands[3].reg.orig;
1428
98
        MVMint16 hint = -1;
1429
98
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1430
98
                                 { MVM_JIT_REG_VAL, obj },
1431
98
                                 { MVM_JIT_REG_VAL, typ },
1432
98
                                 { MVM_JIT_REG_VAL, str },
1433
98
                                 { MVM_JIT_LITERAL, hint }};
1434
98
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, kind, dst);
1435
98
        break;
1436
98
    }
1437
49
    case MVM_OP_attrinited: {
1438
49
        MVMint32 dst       = ins->operands[0].reg.orig;
1439
49
        MVMint32 invocant  = ins->operands[1].reg.orig;
1440
49
        MVMint32 type      = ins->operands[2].reg.orig;
1441
49
        MVMint32 attrname  = ins->operands[3].reg.orig;
1442
49
1443
49
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1444
49
                                 { MVM_JIT_REG_VAL, invocant },
1445
49
                                 { MVM_JIT_REG_VAL, type },
1446
49
                                 { MVM_JIT_REG_VAL, attrname } };
1447
49
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_INT, dst);
1448
49
        break;
1449
98
    }
1450
3.01k
    case MVM_OP_bindattr_i:
1451
3.01k
    case MVM_OP_bindattr_n:
1452
3.01k
    case MVM_OP_bindattr_s:
1453
3.01k
    case MVM_OP_bindattr_o: {
1454
3.01k
        MVMint16 obj = ins->operands[0].reg.orig;
1455
3.01k
        MVMint16 typ = ins->operands[1].reg.orig;
1456
3.01k
        MVMuint32 str_idx = ins->operands[2].lit_str_idx;
1457
3.01k
        MVMint16 val = ins->operands[3].reg.orig;
1458
3.01k
        MVMint16 hint = ins->operands[4].lit_i16;
1459
3.01k
        MVMuint16 kind = op == MVM_OP_bindattr_i ? MVM_reg_int64 :
1460
1.45k
                         op == MVM_OP_bindattr_n ? MVM_reg_num64 :
1461
1.45k
                         op == MVM_OP_bindattr_s ? MVM_reg_str :
1462
1.40k
                         /* MVM_OP_bindattr_o ? */ MVM_reg_obj;
1463
3.01k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1464
3.01k
                                 { MVM_JIT_REG_VAL, obj },
1465
3.01k
                                 { MVM_JIT_REG_VAL, typ },
1466
3.01k
                                 { MVM_JIT_STR_IDX, str_idx },
1467
3.01k
                                 { MVM_JIT_LITERAL, hint },
1468
3.01k
                                 { MVM_JIT_REG_VAL, val }, /* Takes MVMRegister, so no _F needed. */
1469
3.01k
                                 { MVM_JIT_LITERAL, kind } };
1470
3.01k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 7, args, MVM_JIT_RV_VOID, -1);
1471
3.01k
        jg_sc_wb(tc, jg, ins->operands[0]);
1472
3.01k
        break;
1473
3.01k
    }
1474
481
    case MVM_OP_bindattrs_i:
1475
481
    case MVM_OP_bindattrs_n:
1476
481
    case MVM_OP_bindattrs_s:
1477
481
    case MVM_OP_bindattrs_o: {
1478
481
        MVMint16 obj = ins->operands[0].reg.orig;
1479
481
        MVMint16 typ = ins->operands[1].reg.orig;
1480
481
        MVMint16 str = ins->operands[2].reg.orig;
1481
481
        MVMint16 val = ins->operands[3].reg.orig;
1482
481
        MVMint16 hint = -1;
1483
481
        MVMuint16 kind = op == MVM_OP_bindattrs_i ? MVM_reg_int64 :
1484
294
                         op == MVM_OP_bindattrs_n ? MVM_reg_num64 :
1485
294
                         op == MVM_OP_bindattrs_s ? MVM_reg_str :
1486
294
                         /* MVM_OP_bindattrs_o ? */ MVM_reg_obj;
1487
481
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1488
481
                                 { MVM_JIT_REG_VAL, obj },
1489
481
                                 { MVM_JIT_REG_VAL, typ },
1490
481
                                 { MVM_JIT_REG_VAL, str },
1491
481
                                 { MVM_JIT_LITERAL, hint },
1492
481
                                 { MVM_JIT_REG_VAL, val }, /* Takes MVMRegister, so no _F needed. */
1493
481
                                 { MVM_JIT_LITERAL, kind } };
1494
481
        jg_append_call_c(tc, jg, op_to_func(tc, op), 7, args, MVM_JIT_RV_VOID, -1);
1495
481
        jg_sc_wb(tc, jg, ins->operands[0]);
1496
481
        break;
1497
481
    }
1498
60
    case MVM_OP_hintfor: {
1499
60
        MVMint16 dst      = ins->operands[0].reg.orig;
1500
60
        MVMint32 type     = ins->operands[1].reg.orig;
1501
60
        MVMint32 attrname = ins->operands[2].reg.orig;
1502
60
1503
60
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  MVM_JIT_INTERP_TC },
1504
60
                                 { MVM_JIT_REG_VAL,     type },
1505
60
                                 { MVM_JIT_REG_VAL,     attrname } };
1506
60
1507
60
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, dst);
1508
60
        break;
1509
481
    }
1510
824
    case MVM_OP_elems: {
1511
824
        MVMint16 dst = ins->operands[0].reg.orig;
1512
824
        MVMint32 invocant = ins->operands[1].reg.orig;
1513
824
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
1514
824
                                 { MVM_JIT_REG_VAL, invocant } };
1515
824
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
1516
824
        break;
1517
481
    }
1518
0
    default:
1519
0
        return 0;
1520
16.0k
    }
1521
16.0k
1522
16.0k
    return 1;
1523
16.0k
}
1524
1525
static MVMint32 consume_ins(MVMThreadContext *tc, MVMJitGraph *jg,
1526
285k
                            MVMSpeshIterator *iter, MVMSpeshIns *ins) {
1527
285k
    MVMint16 op = ins->info->opcode;
1528
285k
    MVM_jit_log(tc, "append_ins: <%s>\n", ins->info->name);
1529
285k
    switch(op) {
1530
986
    case MVM_SSA_PHI:
1531
986
    case MVM_OP_no_op:
1532
986
        break;
1533
986
        /* arithmetic */
1534
139k
    case MVM_OP_add_i:
1535
139k
    case MVM_OP_sub_i:
1536
139k
    case MVM_OP_mul_i:
1537
139k
    case MVM_OP_div_i:
1538
139k
    case MVM_OP_mod_i:
1539
139k
    case MVM_OP_inc_i:
1540
139k
    case MVM_OP_dec_i:
1541
139k
    case MVM_OP_neg_i:
1542
139k
    case MVM_OP_band_i:
1543
139k
    case MVM_OP_bor_i:
1544
139k
    case MVM_OP_bxor_i:
1545
139k
    case MVM_OP_bnot_i:
1546
139k
    case MVM_OP_blshift_i:
1547
139k
    case MVM_OP_brshift_i:
1548
139k
    case MVM_OP_pow_i:
1549
139k
    case MVM_OP_add_n:
1550
139k
    case MVM_OP_sub_n:
1551
139k
    case MVM_OP_mul_n:
1552
139k
    case MVM_OP_div_n:
1553
139k
    case MVM_OP_neg_n:
1554
139k
        /* number coercion */
1555
139k
    case MVM_OP_coerce_ni:
1556
139k
    case MVM_OP_coerce_in:
1557
139k
    case MVM_OP_extend_i32:
1558
139k
    case MVM_OP_trunc_i16:
1559
139k
    case MVM_OP_trunc_i32:
1560
139k
        /* comparison (integer) */
1561
139k
    case MVM_OP_eq_i:
1562
139k
    case MVM_OP_ne_i:
1563
139k
    case MVM_OP_lt_i:
1564
139k
    case MVM_OP_le_i:
1565
139k
    case MVM_OP_gt_i:
1566
139k
    case MVM_OP_ge_i:
1567
139k
    case MVM_OP_cmp_i:
1568
139k
        /* comparison (numbers) */
1569
139k
    case MVM_OP_eq_n:
1570
139k
    case MVM_OP_ne_n:
1571
139k
    case MVM_OP_ge_n:
1572
139k
    case MVM_OP_gt_n:
1573
139k
    case MVM_OP_lt_n:
1574
139k
    case MVM_OP_le_n:
1575
139k
    case MVM_OP_cmp_n:
1576
139k
        /* comparison (objects) */
1577
139k
    case MVM_OP_eqaddr:
1578
139k
    case MVM_OP_isconcrete:
1579
139k
    case MVM_OP_isinvokable:
1580
139k
        /* comparison (big integer) */
1581
139k
    case MVM_OP_eq_I:
1582
139k
    case MVM_OP_ne_I:
1583
139k
    case MVM_OP_lt_I:
1584
139k
    case MVM_OP_le_I:
1585
139k
    case MVM_OP_gt_I:
1586
139k
    case MVM_OP_ge_I:
1587
139k
        /* constants */
1588
139k
    case MVM_OP_const_i64_16:
1589
139k
    case MVM_OP_const_i64_32:
1590
139k
    case MVM_OP_const_i64:
1591
139k
    case MVM_OP_const_n64:
1592
139k
    case MVM_OP_nan:
1593
139k
    case MVM_OP_inf:
1594
139k
    case MVM_OP_neginf:
1595
139k
    case MVM_OP_const_s:
1596
139k
    case MVM_OP_null:
1597
139k
        /* argument reading */
1598
139k
    case MVM_OP_getarg_i:
1599
139k
    case MVM_OP_getarg_o:
1600
139k
    case MVM_OP_getarg_n:
1601
139k
    case MVM_OP_getarg_s:
1602
139k
    case MVM_OP_sp_getarg_i:
1603
139k
    case MVM_OP_sp_getarg_o:
1604
139k
    case MVM_OP_sp_getarg_n:
1605
139k
    case MVM_OP_sp_getarg_s:
1606
139k
        /* accessors */
1607
139k
    case MVM_OP_sp_p6oget_o:
1608
139k
    case MVM_OP_sp_p6oget_s:
1609
139k
    case MVM_OP_sp_p6oget_i:
1610
139k
    case MVM_OP_sp_p6oget_n:
1611
139k
    case MVM_OP_sp_p6ogetvc_o:
1612
139k
    case MVM_OP_sp_p6ogetvt_o:
1613
139k
    case MVM_OP_sp_p6obind_i:
1614
139k
    case MVM_OP_sp_p6obind_n:
1615
139k
    case MVM_OP_sp_p6obind_s:
1616
139k
    case MVM_OP_sp_p6obind_o:
1617
139k
    case MVM_OP_sp_bind_i64:
1618
139k
    case MVM_OP_sp_bind_n:
1619
139k
    case MVM_OP_sp_bind_s:
1620
139k
    case MVM_OP_sp_bind_o:
1621
139k
    case MVM_OP_sp_get_i64:
1622
139k
    case MVM_OP_sp_get_n:
1623
139k
    case MVM_OP_sp_get_s:
1624
139k
    case MVM_OP_sp_get_o:
1625
139k
    case MVM_OP_sp_deref_bind_i64:
1626
139k
    case MVM_OP_sp_deref_bind_n:
1627
139k
    case MVM_OP_sp_deref_get_i64:
1628
139k
    case MVM_OP_sp_deref_get_n:
1629
139k
    case MVM_OP_set:
1630
139k
    case MVM_OP_getlex:
1631
139k
    case MVM_OP_sp_getlex_o:
1632
139k
    case MVM_OP_sp_getlex_ins:
1633
139k
    case MVM_OP_sp_getlexvia_o:
1634
139k
    case MVM_OP_sp_getlexvia_ins:
1635
139k
    case MVM_OP_getlexreldyn:
1636
139k
    case MVM_OP_getlex_no:
1637
139k
    case MVM_OP_sp_getlex_no:
1638
139k
    case MVM_OP_bindlex:
1639
139k
    case MVM_OP_getwhat:
1640
139k
    case MVM_OP_getwho:
1641
139k
    case MVM_OP_getwhere:
1642
139k
    case MVM_OP_sp_getspeshslot:
1643
139k
    case MVM_OP_takedispatcher:
1644
139k
    case MVM_OP_setdispatcher:
1645
139k
    case MVM_OP_ctx:
1646
139k
    case MVM_OP_ctxlexpad:
1647
139k
    case MVM_OP_curcode:
1648
139k
    case MVM_OP_getcode:
1649
139k
    case MVM_OP_callercode:
1650
139k
    case MVM_OP_sp_fastcreate:
1651
139k
    case MVM_OP_iscont:
1652
139k
    case MVM_OP_decont:
1653
139k
    case MVM_OP_sp_decont:
1654
139k
    case MVM_OP_sp_findmeth:
1655
139k
    case MVM_OP_hllboxtype_i:
1656
139k
    case MVM_OP_hllboxtype_n:
1657
139k
    case MVM_OP_hllboxtype_s:
1658
139k
    case MVM_OP_null_s:
1659
139k
    case MVM_OP_isnull_s:
1660
139k
    case MVM_OP_not_i:
1661
139k
    case MVM_OP_isnull:
1662
139k
    case MVM_OP_isnonnull:
1663
139k
    case MVM_OP_isint:
1664
139k
    case MVM_OP_isnum:
1665
139k
    case MVM_OP_isstr:
1666
139k
    case MVM_OP_islist:
1667
139k
    case MVM_OP_ishash:
1668
139k
    case MVM_OP_sp_boolify_iter_arr:
1669
139k
    case MVM_OP_sp_boolify_iter_hash:
1670
139k
    case MVM_OP_lexprimspec:
1671
139k
    case MVM_OP_objprimspec:
1672
139k
    case MVM_OP_objprimbits:
1673
139k
    case MVM_OP_objprimunsigned:
1674
139k
    case MVM_OP_takehandlerresult:
1675
139k
    case MVM_OP_exception:
1676
139k
    case MVM_OP_scgethandle:
1677
139k
    case MVM_OP_scobjcount:
1678
139k
    case MVM_OP_setobjsc:
1679
139k
    case MVM_OP_scwbdisable:
1680
139k
    case MVM_OP_scwbenable:
1681
139k
    case MVM_OP_assign:
1682
139k
    case MVM_OP_assignunchecked:
1683
139k
    case MVM_OP_getlexstatic_o:
1684
139k
    case MVM_OP_getlexperinvtype_o:
1685
139k
    case MVM_OP_paramnamesused:
1686
139k
    case MVM_OP_assertparamcheck:
1687
139k
    case MVM_OP_getobjsc:
1688
139k
    case MVM_OP_getstderr:
1689
139k
    case MVM_OP_getstdout:
1690
139k
    case MVM_OP_getstdin:
1691
139k
    case MVM_OP_ordat:
1692
139k
    case MVM_OP_ordfirst:
1693
139k
    case MVM_OP_getcodename:
1694
139k
    case MVM_OP_setcodeobj:
1695
139k
        /* Profiling */
1696
139k
    case MVM_OP_prof_enterspesh:
1697
139k
    case MVM_OP_prof_enterinline:
1698
139k
    case MVM_OP_invokewithcapture:
1699
139k
    case MVM_OP_captureposelems:
1700
139k
    case MVM_OP_capturehasnameds:
1701
139k
    case MVM_OP_captureposarg:
1702
139k
    case MVM_OP_captureposarg_i:
1703
139k
    case MVM_OP_captureposarg_n:
1704
139k
    case MVM_OP_captureposarg_s:
1705
139k
    case MVM_OP_captureexistsnamed:
1706
139k
    case MVM_OP_capturenamedshash:
1707
139k
        /* Exception handling */
1708
139k
    case MVM_OP_lastexpayload:
1709
139k
        /* Parameters */
1710
139k
    case MVM_OP_param_sp:
1711
139k
    case MVM_OP_param_sn:
1712
139k
        /* Specialized atomics */
1713
139k
    case MVM_OP_sp_cas_o:
1714
139k
    case MVM_OP_sp_atomicload_o:
1715
139k
    case MVM_OP_sp_atomicstore_o:
1716
139k
        jg_append_primitive(tc, jg, ins);
1717
139k
        break;
1718
139k
        /* Unspecialized parameter access */
1719
156
    case MVM_OP_param_rp_i: {
1720
156
        MVMint16  dst     = ins->operands[0].reg.orig;
1721
156
        MVMuint16 arg_idx = ins->operands[1].lit_ui16;
1722
156
1723
156
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1724
156
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_PARAMS } },
1725
156
                                 { MVM_JIT_LITERAL, { arg_idx } } };
1726
156
        jg_append_call_c(tc, jg, MVM_args_get_required_pos_int, 3, args, MVM_JIT_RV_INT, dst);
1727
156
        break;
1728
139k
    }
1729
0
    case MVM_OP_param_rp_s: {
1730
0
        MVMint16  dst     = ins->operands[0].reg.orig;
1731
0
        MVMuint16 arg_idx = ins->operands[1].lit_ui16;
1732
0
1733
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1734
0
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_PARAMS } },
1735
0
                                 { MVM_JIT_LITERAL, { arg_idx } } };
1736
0
        jg_append_call_c(tc, jg, MVM_args_get_required_pos_str, 3, args, MVM_JIT_RV_PTR, dst);
1737
0
        break;
1738
139k
    }
1739
0
    case MVM_OP_param_rp_o: {
1740
0
        MVMint16  dst     = ins->operands[0].reg.orig;
1741
0
        MVMuint16 arg_idx = ins->operands[1].lit_ui16;
1742
0
1743
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1744
0
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_PARAMS } },
1745
0
                                 { MVM_JIT_LITERAL, { arg_idx } } };
1746
0
        jg_append_call_c(tc, jg, MVM_args_get_required_pos_obj, 3, args, MVM_JIT_RV_PTR, dst);
1747
0
        break;
1748
139k
    }
1749
139k
        /* branches */
1750
23.3k
    case MVM_OP_goto:
1751
23.3k
    case MVM_OP_if_i:
1752
23.3k
    case MVM_OP_unless_i:
1753
23.3k
    case MVM_OP_if_n:
1754
23.3k
    case MVM_OP_unless_n:
1755
23.3k
    case MVM_OP_ifnonnull:
1756
23.3k
    case MVM_OP_indexat:
1757
23.3k
    case MVM_OP_indexnat:
1758
23.3k
    case MVM_OP_if_s0:
1759
23.3k
    case MVM_OP_unless_s0:
1760
23.3k
    case MVM_OP_if_s:
1761
23.3k
    case MVM_OP_unless_s:
1762
23.3k
        jg_append_branch(tc, jg, 0, ins);
1763
23.3k
        break;
1764
23.3k
        /* never any need to implement them anymore, since they're automatically
1765
23.3k
           lowered for us by spesh into istrue + if_i. We can't properly compile
1766
23.3k
           if_o / unless_o as-is because they're both invokish and branching. */
1767
0
    case MVM_OP_if_o:
1768
0
    case MVM_OP_unless_o:
1769
0
        MVM_oops(tc, "Trying to compile if_o/unless_o, should never happen");
1770
0
        break;
1771
0
        /* some functions */
1772
9
    case MVM_OP_gethow: {
1773
9
        MVMint16 dst = ins->operands[0].reg.orig;
1774
9
        MVMint16 obj = ins->operands[1].reg.orig;
1775
9
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1776
9
                                 { MVM_JIT_REG_VAL, { obj } } };
1777
9
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
1778
9
        break;
1779
0
    }
1780
152
    case MVM_OP_istype: {
1781
152
        MVMint16 dst = ins->operands[0].reg.orig;
1782
152
        MVMint16 obj = ins->operands[1].reg.orig;
1783
152
        MVMint16 type = ins->operands[2].reg.orig;
1784
152
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1785
152
                                 { MVM_JIT_REG_VAL, { obj } },
1786
152
                                 { MVM_JIT_REG_VAL, { type } },
1787
152
                                 { MVM_JIT_REG_ADDR, { dst } }};
1788
152
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
1789
152
        break;
1790
0
    }
1791
10
    case MVM_OP_gethllsym: {
1792
10
        MVMint16 dst = ins->operands[0].reg.orig;
1793
10
        MVMint16 hll = ins->operands[1].reg.orig;
1794
10
        MVMint16 sym = ins->operands[2].reg.orig;
1795
10
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1796
10
                                 { MVM_JIT_REG_VAL, { hll } },
1797
10
                                 { MVM_JIT_REG_VAL, { sym } } };
1798
10
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
1799
10
        break;
1800
0
    }
1801
0
    case MVM_OP_checkarity: {
1802
0
        MVMuint16 min = ins->operands[0].lit_i16;
1803
0
        MVMuint16 max = ins->operands[1].lit_i16;
1804
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1805
0
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_PARAMS } },
1806
0
                                 { MVM_JIT_LITERAL, { min } },
1807
0
                                 { MVM_JIT_LITERAL, { max } } };
1808
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
1809
0
        break;
1810
0
    }
1811
0
    case MVM_OP_say:
1812
0
    case MVM_OP_print: {
1813
0
        MVMint32 reg = ins->operands[0].reg.orig;
1814
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1815
0
                                 { MVM_JIT_REG_VAL, { reg } } };
1816
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
1817
0
        break;
1818
0
    }
1819
10.4k
    case MVM_OP_wval:
1820
10.4k
    case MVM_OP_wval_wide: {
1821
10.4k
        MVMint16 dst = ins->operands[0].reg.orig;
1822
10.4k
        MVMint16 dep = ins->operands[1].lit_i16;
1823
10.4k
        MVMint64 idx = op == MVM_OP_wval
1824
10.4k
            ? ins->operands[2].lit_i16
1825
0
            : ins->operands[2].lit_i64;
1826
10.4k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1827
10.4k
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_CU } },
1828
10.4k
                                 { MVM_JIT_LITERAL, { dep } },
1829
10.4k
                                 { MVM_JIT_LITERAL, { idx } } };
1830
10.4k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
1831
10.4k
        break;
1832
10.4k
    }
1833
9
    case MVM_OP_scgetobjidx: {
1834
9
        MVMint16 dst = ins->operands[0].reg.orig;
1835
9
        MVMint16 sc  = ins->operands[1].reg.orig;
1836
9
        MVMint64 obj = ins->operands[2].reg.orig;
1837
9
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1838
9
                                 { MVM_JIT_REG_VAL, { sc } },
1839
9
                                 { MVM_JIT_REG_VAL, { obj } } };
1840
9
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, dst);
1841
9
        break;
1842
10.4k
    }
1843
0
    case MVM_OP_throwdyn:
1844
0
    case MVM_OP_throwlex:
1845
0
    case MVM_OP_throwlexotic: {
1846
0
        MVMint16 regi   = ins->operands[0].reg.orig;
1847
0
        MVMint16 object = ins->operands[1].reg.orig;
1848
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1849
0
                                 { MVM_JIT_LITERAL, {
1850
0
                                   op == MVM_OP_throwlexotic ? MVM_EX_THROW_LEXOTIC :
1851
0
                                   op == MVM_OP_throwlex     ? MVM_EX_THROW_LEX :
1852
0
                                                               MVM_EX_THROW_DYN
1853
0
                                   } },
1854
0
                                 { MVM_JIT_REG_VAL, { object } },
1855
0
                                 { MVM_JIT_REG_ADDR, { regi } }};
1856
0
        jg_append_call_c(tc, jg, op_to_func(tc, op),
1857
0
                          4, args, MVM_JIT_RV_VOID, -1);
1858
0
        break;
1859
0
    }
1860
0
    case MVM_OP_rethrow: {
1861
0
        MVMint16 obj = ins->operands[0].reg.orig;
1862
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1863
0
                                 { MVM_JIT_LITERAL, { MVM_EX_THROW_DYN } },
1864
0
                                 { MVM_JIT_REG_VAL, { obj } },
1865
0
                                 { MVM_JIT_LITERAL, { 0 } } };
1866
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
1867
0
        break;
1868
0
    }
1869
9
    case MVM_OP_throwcatdyn:
1870
9
    case MVM_OP_throwcatlex:
1871
9
    case MVM_OP_throwcatlexotic: {
1872
9
        MVMint16 regi     = ins->operands[0].reg.orig;
1873
9
        MVMint32 category = (MVMuint32)ins->operands[1].lit_i64;
1874
9
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1875
9
                                 { MVM_JIT_LITERAL, {
1876
9
                                   op == MVM_OP_throwcatdyn ? MVM_EX_THROW_DYN :
1877
0
                                   op == MVM_OP_throwcatlex ? MVM_EX_THROW_LEX :
1878
0
                                                              MVM_EX_THROW_LEXOTIC
1879
9
                                   } },
1880
9
                                 { MVM_JIT_LITERAL, { category } },
1881
9
                                 { MVM_JIT_REG_ADDR, { regi } }};
1882
9
        jg_append_call_c(tc, jg, op_to_func(tc, op),
1883
9
                          4, args, MVM_JIT_RV_VOID, -1);
1884
9
        break;
1885
9
    }
1886
1.22k
    case MVM_OP_throwpayloadlex: {
1887
1.22k
        MVMint16 regi     = ins->operands[0].reg.orig;
1888
1.22k
        MVMint32 category = (MVMuint32)ins->operands[1].lit_i64;
1889
1.22k
        MVMint16 payload  = ins->operands[2].reg.orig;
1890
1.22k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1891
1.22k
                                 { MVM_JIT_LITERAL, { MVM_EX_THROW_LEX } },
1892
1.22k
                                 { MVM_JIT_LITERAL, { category } },
1893
1.22k
                                 { MVM_JIT_REG_VAL, { payload } },
1894
1.22k
                                 { MVM_JIT_REG_ADDR, { regi } }};
1895
1.22k
        jg_append_call_c(tc, jg, op_to_func(tc, op),
1896
1.22k
                          5, args, MVM_JIT_RV_VOID, -1);
1897
1.22k
        break;
1898
9
    }
1899
0
    case MVM_OP_getexpayload: {
1900
0
        MVMint16 dst = ins->operands[0].reg.orig;
1901
0
        MVMint16 obj = ins->operands[1].reg.orig;
1902
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1903
0
                                 { MVM_JIT_REG_VAL, { obj } } };
1904
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
1905
0
        break;
1906
9
    }
1907
0
    case MVM_OP_bindexpayload: {
1908
0
        MVMint16 obj = ins->operands[0].reg.orig;
1909
0
        MVMint16 payload = ins->operands[1].reg.orig;
1910
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1911
0
                                 { MVM_JIT_REG_VAL, { obj } },
1912
0
                                 { MVM_JIT_REG_VAL, { payload } } };
1913
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
1914
0
        break;
1915
9
    }
1916
0
    case MVM_OP_resume: {
1917
0
        MVMint16 exc = ins->operands[0].reg.orig;
1918
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1919
0
                                 { MVM_JIT_REG_VAL, { exc } } };
1920
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
1921
0
        break;
1922
9
    }
1923
326
    case MVM_OP_die: {
1924
326
        MVMint16 dst = ins->operands[0].reg.orig;
1925
326
        MVMint16 str = ins->operands[1].reg.orig;
1926
326
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1927
326
                                 { MVM_JIT_REG_VAL, { str } },
1928
326
                                 { MVM_JIT_REG_ADDR, { dst } }};
1929
326
        jg_append_call_c(tc, jg, op_to_func(tc, op),
1930
326
                          3, args, MVM_JIT_RV_VOID, -1);
1931
326
        break;
1932
9
    }
1933
243
    case MVM_OP_getdynlex: {
1934
243
        MVMint16 dst = ins->operands[0].reg.orig;
1935
243
        MVMint16 name = ins->operands[1].reg.orig;
1936
243
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1937
243
                                 { MVM_JIT_REG_VAL, { name } },
1938
243
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_CALLER } }};
1939
243
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
1940
243
        break;
1941
9
    }
1942
65
    case MVM_OP_binddynlex: {
1943
65
        MVMint16 name = ins->operands[0].reg.orig;
1944
65
        MVMint16 val  = ins->operands[1].reg.orig;
1945
65
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1946
65
                                 { MVM_JIT_REG_VAL, { name } },
1947
65
                                 { MVM_JIT_REG_VAL, { val }  },
1948
65
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_CALLER } }};
1949
65
        jg_append_call_c(tc, jg, op_to_func(tc, op),
1950
65
                          4, args, MVM_JIT_RV_VOID, -1);
1951
65
        break;
1952
9
    }
1953
0
    case MVM_OP_getlexouter: {
1954
0
        MVMint16 dst  = ins->operands[0].reg.orig;
1955
0
        MVMint16 name = ins->operands[1].reg.orig;
1956
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1957
0
                                 { MVM_JIT_REG_VAL, { name } }};
1958
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
1959
0
        break;
1960
9
    }
1961
0
    case MVM_OP_getlexcaller: {
1962
0
        MVMint16 dst  = ins->operands[0].reg.orig;
1963
0
        MVMint16 name = ins->operands[1].reg.orig;
1964
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1965
0
                                 { MVM_JIT_REG_VAL, { name } },
1966
0
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_CALLER } } };
1967
0
        jg_append_call_c(tc, jg, MVM_frame_find_lexical_by_name_rel_caller,
1968
0
                         3, args, MVM_JIT_RV_DEREF_OR_VMNULL, dst);
1969
0
        break;
1970
9
    }
1971
270
    case MVM_OP_isfalse:
1972
270
    case MVM_OP_istrue: {
1973
270
        MVMint16 obj = ins->operands[1].reg.orig;
1974
270
        MVMint16 dst = ins->operands[0].reg.orig;
1975
270
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1976
270
                                 { MVM_JIT_REG_VAL,  { obj } },
1977
270
                                 { MVM_JIT_REG_ADDR, { dst } },
1978
270
                                 { MVM_JIT_LITERAL, { 0 } },
1979
270
                                 { MVM_JIT_LITERAL, { 0 } },
1980
270
                                 { MVM_JIT_LITERAL, { op == MVM_OP_isfalse } }};
1981
270
        jg_append_call_c(tc, jg, op_to_func(tc, op), 6, args, MVM_JIT_RV_VOID, -1);
1982
270
        break;
1983
270
    }
1984
0
    case MVM_OP_capturelex: {
1985
0
        MVMint16 code = ins->operands[0].reg.orig;
1986
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1987
0
                                 { MVM_JIT_REG_VAL, { code } } };
1988
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
1989
0
        break;
1990
270
    }
1991
0
    case MVM_OP_captureinnerlex: {
1992
0
        MVMint16 code = ins->operands[0].reg.orig;
1993
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
1994
0
                                 { MVM_JIT_REG_VAL, { code } } };
1995
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
1996
0
        break;
1997
270
    }
1998
0
    case MVM_OP_takeclosure: {
1999
0
        MVMint16 dst = ins->operands[0].reg.orig;
2000
0
        MVMint16 src = ins->operands[1].reg.orig;
2001
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2002
0
                                 { MVM_JIT_REG_VAL, { src } } };
2003
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2004
0
        break;
2005
270
    }
2006
0
    case MVM_OP_usecapture:
2007
0
    case MVM_OP_savecapture: {
2008
0
        MVMint16 dst = ins->operands[0].reg.orig;
2009
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2010
0
                                 { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_FRAME } }};
2011
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2012
0
        break;
2013
0
    }
2014
0
    case MVM_OP_captureposprimspec: {
2015
0
        MVMint16 dst     = ins->operands[0].reg.orig;
2016
0
        MVMint16 capture = ins->operands[1].reg.orig;
2017
0
        MVMint16 index   = ins->operands[2].reg.orig;
2018
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2019
0
                                 { MVM_JIT_REG_VAL, { capture } },
2020
0
                                 { MVM_JIT_REG_VAL, { index } } };
2021
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, dst);
2022
0
        break;
2023
0
    }
2024
0
    case MVM_OP_gt_s:
2025
0
    case MVM_OP_ge_s:
2026
0
    case MVM_OP_lt_s:
2027
0
    case MVM_OP_le_s:
2028
0
    case MVM_OP_cmp_s: {
2029
0
        MVMint16 dst = ins->operands[0].reg.orig;
2030
0
        MVMint16 a   = ins->operands[1].reg.orig;
2031
0
        MVMint16 b   = ins->operands[2].reg.orig;
2032
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2033
0
                                 { MVM_JIT_REG_VAL, { a } },
2034
0
                                 { MVM_JIT_REG_VAL, { b } }};
2035
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, dst);
2036
0
        /* We rely on an implementation of the comparisons against -1, 0 and 1
2037
0
         * in emit.dasc */
2038
0
        if (op != MVM_OP_cmp_s) {
2039
0
            jg_append_primitive(tc, jg, ins);
2040
0
        }
2041
0
        break;
2042
0
    }
2043
0
    case MVM_OP_hllizefor:
2044
0
    case MVM_OP_hllize: {
2045
0
        MVMint16 dst = ins->operands[0].reg.orig;
2046
0
        MVMint16 src = ins->operands[1].reg.orig;
2047
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2048
0
                                 { MVM_JIT_REG_VAL, { src } },
2049
0
                                 { MVM_JIT_LITERAL_PTR, 0 },
2050
0
                                 { MVM_JIT_REG_ADDR, { dst } }};
2051
0
2052
0
        MVMHLLConfig *hll_config;
2053
0
        if (ins->info->opcode == MVM_OP_hllize) {
2054
0
            hll_config = jg->sg->sf->body.cu->body.hll_config;
2055
0
        } else {
2056
0
            MVMSpeshFacts *facts = MVM_spesh_get_facts(tc, jg->sg, ins->operands[2]);
2057
0
            if (facts->flags & MVM_SPESH_FACT_KNOWN_VALUE) {
2058
0
                hll_config = MVM_hll_get_config_for(tc, facts->value.s);
2059
0
            } else {
2060
0
                MVM_jit_log(tc, "BAIL: op <%s>", ins->info->name);
2061
0
                return 0;
2062
0
            }
2063
0
        }
2064
0
        args[2].v.ptr = hll_config;
2065
0
        jg_append_call_c(tc, jg, MVM_hll_map, 4, args, MVM_JIT_RV_VOID, -1);
2066
0
        break;
2067
0
    }
2068
27
    case MVM_OP_clone: {
2069
27
        MVMint16 dst = ins->operands[0].reg.orig;
2070
27
        MVMint16 obj = ins->operands[1].reg.orig;
2071
27
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2072
27
                                 { MVM_JIT_REG_VAL, { obj } } };
2073
27
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2074
27
        break;
2075
0
    }
2076
43
    case MVM_OP_create: {
2077
43
        MVMint16 dst  = ins->operands[0].reg.orig;
2078
43
        MVMint16 type = ins->operands[1].reg.orig;
2079
43
        MVMJitCallArg args_alloc[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2080
43
                                 { MVM_JIT_REG_VAL, { type } } };
2081
43
        MVMJitCallArg args_init[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2082
43
                                 { MVM_JIT_REG_VAL, { dst } } };
2083
43
        jg_append_call_c(tc, jg, MVM_repr_alloc, 2, args_alloc, MVM_JIT_RV_PTR, dst);
2084
43
        jg_append_call_c(tc, jg, MVM_repr_init, 2, args_init, MVM_JIT_RV_VOID, -1);
2085
43
        break;
2086
0
    }
2087
0
    case MVM_OP_cas_o: {
2088
0
        MVMint16 result = ins->operands[0].reg.orig;
2089
0
        MVMint16 target = ins->operands[1].reg.orig;
2090
0
        MVMint16 expected = ins->operands[2].reg.orig;
2091
0
        MVMint16 value = ins->operands[3].reg.orig;
2092
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2093
0
                                 { MVM_JIT_REG_VAL, { target } },
2094
0
                                 { MVM_JIT_REG_VAL, { expected } },
2095
0
                                 { MVM_JIT_REG_VAL, { value } },
2096
0
                                 { MVM_JIT_REG_ADDR, { result } } };
2097
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, MVM_JIT_RV_VOID, -1);
2098
0
        break;
2099
0
    }
2100
0
    case MVM_OP_cas_i: {
2101
0
        MVMint16 result = ins->operands[0].reg.orig;
2102
0
        MVMint16 target = ins->operands[1].reg.orig;
2103
0
        MVMint16 expected = ins->operands[2].reg.orig;
2104
0
        MVMint16 value = ins->operands[3].reg.orig;
2105
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2106
0
                                 { MVM_JIT_REG_VAL, { target } },
2107
0
                                 { MVM_JIT_REG_VAL, { expected } },
2108
0
                                 { MVM_JIT_REG_VAL, { value } } };
2109
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_INT, result);
2110
0
        break;
2111
0
    }
2112
0
    case MVM_OP_atomicinc_i:
2113
0
    case MVM_OP_atomicdec_i:
2114
0
    case MVM_OP_atomicload_i: {
2115
0
        MVMint16 result = ins->operands[0].reg.orig;
2116
0
        MVMint16 target = ins->operands[1].reg.orig;
2117
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2118
0
                                 { MVM_JIT_REG_VAL, { target } } };
2119
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, result);
2120
0
        break;
2121
0
    }
2122
0
    case MVM_OP_atomicadd_i: {
2123
0
        MVMint16 result = ins->operands[0].reg.orig;
2124
0
        MVMint16 target = ins->operands[1].reg.orig;
2125
0
        MVMint16 increment = ins->operands[2].reg.orig;
2126
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2127
0
                                 { MVM_JIT_REG_VAL, { target } },
2128
0
                                 { MVM_JIT_REG_VAL, { increment } } };
2129
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, result);
2130
0
        break;
2131
0
    }
2132
0
    case MVM_OP_atomicload_o: {
2133
0
        MVMint16 dst = ins->operands[0].reg.orig;
2134
0
        MVMint16 target = ins->operands[1].reg.orig;
2135
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2136
0
                                 { MVM_JIT_REG_VAL, { target } } };
2137
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2138
0
        break;
2139
0
    }
2140
0
    case MVM_OP_atomicstore_o:
2141
0
    case MVM_OP_atomicstore_i: {
2142
0
        MVMint16 target = ins->operands[0].reg.orig;
2143
0
        MVMint16 value = ins->operands[1].reg.orig;
2144
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2145
0
                                 { MVM_JIT_REG_VAL, { target } },
2146
0
                                 { MVM_JIT_REG_VAL, { value } } };
2147
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
2148
0
        break;
2149
0
    }
2150
2
    case MVM_OP_lock: {
2151
2
        MVMint16 lock = ins->operands[0].reg.orig;
2152
2
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2153
2
                                 { MVM_JIT_REG_VAL, { lock } } };
2154
2
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
2155
2
        break;
2156
0
    }
2157
2
    case MVM_OP_unlock: {
2158
2
        MVMint16 lock = ins->operands[0].reg.orig;
2159
2
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2160
2
                                 { MVM_JIT_REG_VAL, { lock } } };
2161
2
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
2162
2
        break;
2163
0
    }
2164
0
        /* repr ops */
2165
22.4k
    case MVM_OP_unshift_i:
2166
22.4k
    case MVM_OP_unshift_n:
2167
22.4k
    case MVM_OP_unshift_s:
2168
22.4k
    case MVM_OP_unshift_o:
2169
22.4k
    case MVM_OP_push_i:
2170
22.4k
    case MVM_OP_push_n:
2171
22.4k
    case MVM_OP_push_s:
2172
22.4k
    case MVM_OP_push_o:
2173
22.4k
    case MVM_OP_shift_i:
2174
22.4k
    case MVM_OP_shift_n:
2175
22.4k
    case MVM_OP_shift_s:
2176
22.4k
    case MVM_OP_shift_o:
2177
22.4k
    case MVM_OP_pop_i:
2178
22.4k
    case MVM_OP_pop_n:
2179
22.4k
    case MVM_OP_pop_s:
2180
22.4k
    case MVM_OP_pop_o:
2181
22.4k
    case MVM_OP_deletekey:
2182
22.4k
    case MVM_OP_existskey:
2183
22.4k
    case MVM_OP_existspos:
2184
22.4k
    case MVM_OP_setelemspos:
2185
22.4k
    case MVM_OP_slice:
2186
22.4k
    case MVM_OP_splice:
2187
22.4k
    case MVM_OP_atpos_i:
2188
22.4k
    case MVM_OP_atpos_n:
2189
22.4k
    case MVM_OP_atpos_s:
2190
22.4k
    case MVM_OP_atpos_o:
2191
22.4k
    case MVM_OP_atkey_i:
2192
22.4k
    case MVM_OP_atkey_n:
2193
22.4k
    case MVM_OP_atkey_s:
2194
22.4k
    case MVM_OP_atkey_o:
2195
22.4k
    case MVM_OP_bindpos_i:
2196
22.4k
    case MVM_OP_bindpos_n:
2197
22.4k
    case MVM_OP_bindpos_s:
2198
22.4k
    case MVM_OP_bindpos_o:
2199
22.4k
    case MVM_OP_bindkey_i:
2200
22.4k
    case MVM_OP_bindkey_n:
2201
22.4k
    case MVM_OP_bindkey_s:
2202
22.4k
    case MVM_OP_bindkey_o:
2203
22.4k
    case MVM_OP_getattr_i:
2204
22.4k
    case MVM_OP_getattr_n:
2205
22.4k
    case MVM_OP_getattr_s:
2206
22.4k
    case MVM_OP_getattr_o:
2207
22.4k
    case MVM_OP_getattrs_i:
2208
22.4k
    case MVM_OP_getattrs_n:
2209
22.4k
    case MVM_OP_getattrs_s:
2210
22.4k
    case MVM_OP_getattrs_o:
2211
22.4k
    case MVM_OP_attrinited:
2212
22.4k
    case MVM_OP_bindattr_i:
2213
22.4k
    case MVM_OP_bindattr_n:
2214
22.4k
    case MVM_OP_bindattr_s:
2215
22.4k
    case MVM_OP_bindattr_o:
2216
22.4k
    case MVM_OP_bindattrs_i:
2217
22.4k
    case MVM_OP_bindattrs_n:
2218
22.4k
    case MVM_OP_bindattrs_s:
2219
22.4k
    case MVM_OP_bindattrs_o:
2220
22.4k
    case MVM_OP_hintfor:
2221
22.4k
    case MVM_OP_elems:
2222
22.4k
        if (!consume_reprop(tc, jg, iter, ins)) {
2223
0
            MVM_jit_log(tc, "BAIL: op <%s> (devirt attempted)\n", ins->info->name);
2224
0
            return 0;
2225
0
        }
2226
22.4k
        break;
2227
543
    case MVM_OP_iterkey_s:
2228
543
    case MVM_OP_iterval:
2229
543
    case MVM_OP_iter: {
2230
543
        MVMint16 dst      = ins->operands[0].reg.orig;
2231
543
        MVMint32 invocant = ins->operands[1].reg.orig;
2232
543
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2233
543
                                 { MVM_JIT_REG_VAL, { invocant } } };
2234
543
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2235
543
        break;
2236
543
    }
2237
0
    case MVM_OP_continuationreset: {
2238
0
        MVMint16 reg  = ins->operands[0].reg.orig;
2239
0
        MVMint16 tag  = ins->operands[1].reg.orig;
2240
0
        MVMint16 code = ins->operands[2].reg.orig;
2241
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2242
0
                                 { MVM_JIT_REG_VAL, { tag } },
2243
0
                                 { MVM_JIT_REG_VAL, { code } },
2244
0
                                 { MVM_JIT_REG_ADDR, { reg } }};
2245
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
2246
0
        break;
2247
543
    }
2248
0
    case MVM_OP_continuationcontrol: {
2249
0
        MVMint16 reg  = ins->operands[0].reg.orig;
2250
0
        MVMint16 protect  = ins->operands[1].reg.orig;
2251
0
        MVMint16 tag  = ins->operands[2].reg.orig;
2252
0
        MVMint16 code = ins->operands[3].reg.orig;
2253
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2254
0
                                 { MVM_JIT_REG_VAL, { protect } },
2255
0
                                 { MVM_JIT_REG_VAL, { tag } },
2256
0
                                 { MVM_JIT_REG_VAL, { code } },
2257
0
                                 { MVM_JIT_REG_ADDR, { reg } }};
2258
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, MVM_JIT_RV_VOID, -1);
2259
0
        break;
2260
543
    }
2261
0
    case MVM_OP_continuationinvoke: {
2262
0
        MVMint16 reg  = ins->operands[0].reg.orig;
2263
0
        MVMint16 cont  = ins->operands[1].reg.orig;
2264
0
        MVMint16 code = ins->operands[2].reg.orig;
2265
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2266
0
                                 { MVM_JIT_REG_VAL, { cont } },
2267
0
                                 { MVM_JIT_REG_VAL, { code } },
2268
0
                                 { MVM_JIT_REG_ADDR, { reg } }};
2269
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
2270
0
        break;
2271
543
    }
2272
0
    case MVM_OP_sp_boolify_iter: {
2273
0
        MVMint16 dst = ins->operands[0].reg.orig;
2274
0
        MVMint16 obj = ins->operands[1].reg.orig;
2275
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2276
0
                                 { MVM_JIT_REG_VAL, { obj } }};
2277
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
2278
0
        break;
2279
543
    }
2280
526
    case MVM_OP_findmeth:
2281
526
    case MVM_OP_findmeth_s: {
2282
526
        MVMint16 dst = ins->operands[0].reg.orig;
2283
526
        MVMint16 obj = ins->operands[1].reg.orig;
2284
526
        MVMint32 name = (op == MVM_OP_findmeth_s ? ins->operands[2].reg.orig :
2285
0
                         ins->operands[2].lit_str_idx);
2286
526
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2287
526
                                 { MVM_JIT_REG_VAL, { obj } },
2288
526
                                 { (op == MVM_OP_findmeth_s ? MVM_JIT_REG_VAL :
2289
0
                                    MVM_JIT_STR_IDX), { name } },
2290
526
                                 { MVM_JIT_REG_ADDR, { dst } },
2291
526
                                 { MVM_JIT_LITERAL, { 1 } } };
2292
526
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, MVM_JIT_RV_VOID, -1);
2293
526
        break;
2294
526
    }
2295
593
    case MVM_OP_tryfindmeth:
2296
593
    case MVM_OP_tryfindmeth_s: {
2297
593
        MVMint16 dst = ins->operands[0].reg.orig;
2298
593
        MVMint16 obj = ins->operands[1].reg.orig;
2299
593
        MVMint32 name = (op == MVM_OP_tryfindmeth_s ? ins->operands[2].reg.orig :
2300
0
                         ins->operands[2].lit_str_idx);
2301
593
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2302
593
                                 { MVM_JIT_REG_VAL, { obj } },
2303
593
                                 { (op == MVM_OP_tryfindmeth_s ? MVM_JIT_REG_VAL :
2304
0
                                    MVM_JIT_STR_IDX), { name } },
2305
593
                                 { MVM_JIT_REG_ADDR, { dst } },
2306
593
                                 { MVM_JIT_LITERAL, { 0 } } };
2307
593
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, MVM_JIT_RV_VOID, -1);
2308
593
        break;
2309
593
    }
2310
593
2311
0
    case MVM_OP_multicachefind: {
2312
0
        MVMint16 dst = ins->operands[0].reg.orig;
2313
0
        MVMint16 cache = ins->operands[1].reg.orig;
2314
0
        MVMint16 capture = ins->operands[2].reg.orig;
2315
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2316
0
                                 { MVM_JIT_REG_VAL, { cache } },
2317
0
                                 { MVM_JIT_REG_VAL, { capture } } };
2318
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
2319
0
        break;
2320
593
    }
2321
78
    case MVM_OP_multicacheadd: {
2322
78
        MVMint16 dst = ins->operands[0].reg.orig;
2323
78
        MVMint16 cache = ins->operands[1].reg.orig;
2324
78
        MVMint16 capture = ins->operands[2].reg.orig;
2325
78
        MVMint16 result = ins->operands[3].reg.orig;
2326
78
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2327
78
                                 { MVM_JIT_REG_VAL, { cache } },
2328
78
                                 { MVM_JIT_REG_VAL, { capture } },
2329
78
                                 { MVM_JIT_REG_VAL, { result } } };
2330
78
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
2331
78
        break;
2332
593
    }
2333
593
2334
11
    case MVM_OP_can:
2335
11
    case MVM_OP_can_s: {
2336
11
        MVMint16 dst = ins->operands[0].reg.orig;
2337
11
        MVMint16 obj = ins->operands[1].reg.orig;
2338
11
        MVMint32 name = (op == MVM_OP_can_s ? ins->operands[2].reg.orig :
2339
1
                         ins->operands[2].lit_str_idx);
2340
11
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2341
11
                                 { MVM_JIT_REG_VAL, { obj } },
2342
11
                                 { (op == MVM_OP_can_s ? MVM_JIT_REG_VAL :
2343
1
                                    MVM_JIT_STR_IDX), { name } },
2344
11
                                 { MVM_JIT_REG_ADDR, { dst } } };
2345
11
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
2346
11
        break;
2347
11
    }
2348
11
2349
11
        /* coercion */
2350
986
    case MVM_OP_coerce_sn:
2351
986
    case MVM_OP_coerce_ns:
2352
986
    case MVM_OP_coerce_si:
2353
986
    case MVM_OP_coerce_is:
2354
986
    case MVM_OP_coerce_In: {
2355
986
        MVMint16 src = ins->operands[1].reg.orig;
2356
986
        MVMint16 dst = ins->operands[0].reg.orig;
2357
986
        MVMJitCallArg args[] = {{ MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2358
986
                                 { MVM_JIT_REG_VAL, { src } } };
2359
986
        MVMJitRVMode rv_mode = ((op == MVM_OP_coerce_sn || op == MVM_OP_coerce_In) ? MVM_JIT_RV_NUM :
2360
986
                                op == MVM_OP_coerce_si ? MVM_JIT_RV_INT :
2361
238
                                MVM_JIT_RV_PTR);
2362
986
        if (op == MVM_OP_coerce_ns) {
2363
53
            args[1].type = MVM_JIT_REG_VAL_F;
2364
53
        }
2365
986
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, rv_mode, dst);
2366
986
        break;
2367
986
    }
2368
0
    case MVM_OP_coerce_nI: {
2369
0
        MVMint16 src = ins->operands[1].reg.orig;
2370
0
        MVMint16 dst = ins->operands[0].reg.orig;
2371
0
        MVMint16 typ = ins->operands[2].reg.orig;
2372
0
        MVMJitCallArg args[] = {{ MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2373
0
                                { MVM_JIT_REG_VAL,   { typ } },
2374
0
                                { MVM_JIT_REG_VAL_F, { src } }};
2375
0
2376
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
2377
0
        break;
2378
986
    }
2379
0
    case MVM_OP_coerce_II: {
2380
0
        MVMint16 src = ins->operands[1].reg.orig;
2381
0
        MVMint16 dst = ins->operands[0].reg.orig;
2382
0
        MVMint16 typ = ins->operands[2].reg.orig;
2383
0
        MVMJitCallArg args[] = {{ MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2384
0
                                { MVM_JIT_REG_VAL, { typ } },
2385
0
                                { MVM_JIT_REG_VAL, { src } }};
2386
0
2387
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
2388
0
        break;
2389
986
    }
2390
1.99k
    case MVM_OP_smrt_strify:
2391
1.99k
    case MVM_OP_smrt_numify: {
2392
1.99k
        MVMint16 obj = ins->operands[1].reg.orig;
2393
1.99k
        MVMint16 dst = ins->operands[0].reg.orig;
2394
1.99k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2395
1.99k
                                 { MVM_JIT_REG_VAL, { obj } },
2396
1.99k
                                 { MVM_JIT_REG_ADDR, { dst } }};
2397
1.99k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args,
2398
1.99k
                          MVM_JIT_RV_VOID, -1);
2399
1.99k
        break;
2400
1.99k
    }
2401
0
    case MVM_OP_queuepoll: {
2402
0
        MVMint16 dst = ins->operands[0].reg.orig;
2403
0
        MVMint16 obj = ins->operands[1].reg.orig;
2404
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2405
0
                                 { MVM_JIT_REG_VAL, { obj } } };
2406
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2407
0
        break;
2408
1.99k
    }
2409
0
    case MVM_OP_close_fh: {
2410
0
        MVMint16 fho = ins->operands[0].reg.orig;
2411
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2412
0
                                 { MVM_JIT_REG_VAL, { fho } } };
2413
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
2414
0
        break;
2415
1.99k
    }
2416
0
    case MVM_OP_open_fh: {
2417
0
        MVMint16 dst  = ins->operands[0].reg.orig;
2418
0
        MVMint16 path = ins->operands[1].reg.orig;
2419
0
        MVMint16 mode = ins->operands[2].reg.orig;
2420
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2421
0
                                 { MVM_JIT_REG_VAL, { path } },
2422
0
                                 { MVM_JIT_REG_VAL, { mode } } };
2423
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
2424
0
        break;
2425
1.99k
    }
2426
0
    case MVM_OP_eof_fh: {
2427
0
        MVMint16 dst = ins->operands[0].reg.orig;
2428
0
        MVMint16 fho = ins->operands[1].reg.orig;
2429
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2430
0
                                 { MVM_JIT_REG_VAL, { fho } } };
2431
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
2432
0
        break;
2433
1.99k
    }
2434
8
    case MVM_OP_write_fhb: {
2435
8
        MVMint16 fho = ins->operands[0].reg.orig;
2436
8
        MVMint16 buf = ins->operands[1].reg.orig;
2437
8
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2438
8
                                 { MVM_JIT_REG_VAL, { fho } },
2439
8
                                 { MVM_JIT_REG_VAL, { buf } } };
2440
8
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
2441
8
        break;
2442
1.99k
    }
2443
0
    case MVM_OP_read_fhb: {
2444
0
        MVMint16 fho = ins->operands[0].reg.orig;
2445
0
        MVMint16 res = ins->operands[1].reg.orig;
2446
0
        MVMint16 len = ins->operands[2].reg.orig;
2447
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2448
0
                                 { MVM_JIT_REG_VAL, { fho } },
2449
0
                                 { MVM_JIT_REG_VAL, { res } },
2450
0
                                 { MVM_JIT_REG_VAL, { len } } };
2451
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
2452
0
        break;
2453
1.99k
    }
2454
401
    case MVM_OP_box_n: {
2455
401
        MVMint16 dst = ins->operands[0].reg.orig;
2456
401
        MVMint16 val = ins->operands[1].reg.orig;
2457
401
        MVMint16 type = ins->operands[2].reg.orig;
2458
401
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR , { MVM_JIT_INTERP_TC } },
2459
401
                                 { MVM_JIT_REG_VAL_F, { val } },
2460
401
                                 { MVM_JIT_REG_VAL, { type } },
2461
401
                                 { MVM_JIT_REG_ADDR, { dst } }};
2462
401
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
2463
401
        break;
2464
1.99k
    }
2465
1.75k
    case MVM_OP_box_s:
2466
1.75k
    case MVM_OP_box_i: {
2467
1.75k
        MVMint16 dst = ins->operands[0].reg.orig;
2468
1.75k
        MVMint16 val = ins->operands[1].reg.orig;
2469
1.75k
        MVMint16 type = ins->operands[2].reg.orig;
2470
1.75k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR , { MVM_JIT_INTERP_TC } },
2471
1.75k
                                 { MVM_JIT_REG_VAL, { val } },
2472
1.75k
                                 { MVM_JIT_REG_VAL, { type } },
2473
1.75k
                                 { MVM_JIT_REG_ADDR, { dst } }};
2474
1.75k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_VOID, -1);
2475
1.75k
        break;
2476
1.75k
    }
2477
987
    case MVM_OP_unbox_i: {
2478
987
        MVMint16 dst = ins->operands[0].reg.orig;
2479
987
        MVMint16 obj = ins->operands[1].reg.orig;
2480
987
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR , { MVM_JIT_INTERP_TC } },
2481
987
                                 { MVM_JIT_REG_VAL, { obj } } };
2482
987
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
2483
987
        break;
2484
1.75k
    }
2485
0
    case MVM_OP_unbox_n: {
2486
0
        MVMint16 dst = ins->operands[0].reg.orig;
2487
0
        MVMint16 obj = ins->operands[1].reg.orig;
2488
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR , { MVM_JIT_INTERP_TC } },
2489
0
                                 { MVM_JIT_REG_VAL, { obj } } };
2490
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_NUM, dst);
2491
0
        break;
2492
1.75k
    }
2493
277
    case MVM_OP_unbox_s: {
2494
277
        MVMint16 dst = ins->operands[0].reg.orig;
2495
277
        MVMint16 obj = ins->operands[1].reg.orig;
2496
277
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR , { MVM_JIT_INTERP_TC } },
2497
277
                                 { MVM_JIT_REG_VAL, { obj } } };
2498
277
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2499
277
        break;
2500
1.75k
    }
2501
1.75k
        /* string ops */
2502
995
    case MVM_OP_repeat_s:
2503
995
    case MVM_OP_split:
2504
995
    case MVM_OP_concat_s: {
2505
995
        MVMint16 src_a = ins->operands[1].reg.orig;
2506
995
        MVMint16 src_b = ins->operands[2].reg.orig;
2507
995
        MVMint16 dst   = ins->operands[0].reg.orig;
2508
995
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2509
995
                                 { MVM_JIT_REG_VAL, { src_a } },
2510
995
                                 { MVM_JIT_REG_VAL, { src_b } } };
2511
995
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args,
2512
995
                          MVM_JIT_RV_PTR, dst);
2513
995
        break;
2514
995
    }
2515
0
    case MVM_OP_escape:
2516
0
    case MVM_OP_uc:
2517
0
    case MVM_OP_lc:
2518
0
    case MVM_OP_tc:
2519
0
    case MVM_OP_fc:
2520
0
    case MVM_OP_indexingoptimized: {
2521
0
        MVMint16 dst    = ins->operands[0].reg.orig;
2522
0
        MVMint16 string = ins->operands[1].reg.orig;
2523
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2524
0
                                 { MVM_JIT_REG_VAL, { string } } };
2525
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2526
0
        break;
2527
0
    }
2528
203
    case MVM_OP_ne_s:
2529
203
    case MVM_OP_eq_s: {
2530
203
        MVMint16 src_a = ins->operands[1].reg.orig;
2531
203
        MVMint16 src_b = ins->operands[2].reg.orig;
2532
203
        MVMint16 dst   = ins->operands[0].reg.orig;
2533
203
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2534
203
                                 { MVM_JIT_REG_VAL, { src_a } },
2535
203
                                 { MVM_JIT_REG_VAL, { src_b } } };
2536
203
        jg_append_call_c(tc, jg, op_to_func(tc, MVM_OP_eq_s), 3, args,
2537
203
                          MVM_JIT_RV_INT, dst);
2538
203
        if (op == MVM_OP_ne_s) {
2539
6
            /* append not_i to negate ne_s */
2540
6
            MVMSpeshIns *not_i          = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMSpeshIns));
2541
6
            not_i->info                 = MVM_op_get_op(MVM_OP_not_i);
2542
6
            not_i->operands             = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMSpeshOperand) * 2);
2543
6
            not_i->operands[0].reg.orig = dst;
2544
6
            not_i->operands[1].reg.orig = dst;
2545
6
            jg_append_primitive(tc, jg, not_i);
2546
6
        }
2547
203
        break;
2548
203
    }
2549
86
    case MVM_OP_eqat_s: {
2550
86
        MVMint16 dst    = ins->operands[0].reg.orig;
2551
86
        MVMint16 src_a  = ins->operands[1].reg.orig;
2552
86
        MVMint16 src_b  = ins->operands[2].reg.orig;
2553
86
        MVMint16 offset = ins->operands[3].reg.orig;
2554
86
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2555
86
                                 { MVM_JIT_REG_VAL, { src_a } },
2556
86
                                 { MVM_JIT_REG_VAL, { src_b } },
2557
86
                                 { MVM_JIT_REG_VAL, { offset } } };
2558
86
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args,
2559
86
                          MVM_JIT_RV_INT, dst);
2560
86
        break;
2561
203
    }
2562
123
    case MVM_OP_eqatic_s: {
2563
123
        MVMint16 dst    = ins->operands[0].reg.orig;
2564
123
        MVMint16 src_a  = ins->operands[1].reg.orig;
2565
123
        MVMint16 src_b  = ins->operands[2].reg.orig;
2566
123
        MVMint16 offset = ins->operands[3].reg.orig;
2567
123
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2568
123
                                 { MVM_JIT_REG_VAL, { src_a } },
2569
123
                                 { MVM_JIT_REG_VAL, { src_b } },
2570
123
                                 { MVM_JIT_REG_VAL, { offset } } };
2571
123
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args,
2572
123
                         MVM_JIT_RV_INT, dst);
2573
123
        break;
2574
203
    }
2575
0
    case MVM_OP_eqatim_s: {
2576
0
        MVMint16 dst    = ins->operands[0].reg.orig;
2577
0
        MVMint16 src_a  = ins->operands[1].reg.orig;
2578
0
        MVMint16 src_b  = ins->operands[2].reg.orig;
2579
0
        MVMint16 offset = ins->operands[3].reg.orig;
2580
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2581
0
                                 { MVM_JIT_REG_VAL, { src_a } },
2582
0
                                 { MVM_JIT_REG_VAL, { src_b } },
2583
0
                                 { MVM_JIT_REG_VAL, { offset } } };
2584
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args,
2585
0
                         MVM_JIT_RV_INT, dst);
2586
0
        break;
2587
203
    }
2588
0
    case MVM_OP_eqaticim_s: {
2589
0
        MVMint16 dst    = ins->operands[0].reg.orig;
2590
0
        MVMint16 src_a  = ins->operands[1].reg.orig;
2591
0
        MVMint16 src_b  = ins->operands[2].reg.orig;
2592
0
        MVMint16 offset = ins->operands[3].reg.orig;
2593
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2594
0
                                 { MVM_JIT_REG_VAL, { src_a } },
2595
0
                                 { MVM_JIT_REG_VAL, { src_b } },
2596
0
                                 { MVM_JIT_REG_VAL, { offset } } };
2597
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args,
2598
0
                         MVM_JIT_RV_INT, dst);
2599
0
        break;
2600
203
    }
2601
801
    case MVM_OP_chars:
2602
801
    case MVM_OP_graphs_s:
2603
801
    case MVM_OP_codes_s:
2604
801
    case MVM_OP_flip: {
2605
801
        MVMint16 src = ins->operands[1].reg.orig;
2606
801
        MVMint16 dst = ins->operands[0].reg.orig;
2607
801
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2608
801
                                 { MVM_JIT_REG_VAL, { src } } };
2609
801
        MVMJitRVMode rv_mode = (op == MVM_OP_flip ? MVM_JIT_RV_PTR : MVM_JIT_RV_INT);
2610
801
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, rv_mode, dst);
2611
801
        break;
2612
801
    }
2613
0
    case MVM_OP_getcp_s: {
2614
0
        MVMint16 dst = ins->operands[0].reg.orig;
2615
0
        MVMint16 src = ins->operands[1].reg.orig;
2616
0
        MVMint16 idx = ins->operands[2].reg.orig;
2617
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2618
0
                                 { MVM_JIT_REG_VAL, { src } },
2619
0
                                 { MVM_JIT_REG_VAL, { idx } } };
2620
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, dst);
2621
0
        break;
2622
801
    }
2623
2
    case MVM_OP_chr: {
2624
2
        MVMint16 dst = ins->operands[0].reg.orig;
2625
2
        MVMint16 src = ins->operands[1].reg.orig;
2626
2
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2627
2
                                 { MVM_JIT_REG_VAL, { src } } };
2628
2
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2629
2
        break;
2630
801
    }
2631
1
    case MVM_OP_join: {
2632
1
        MVMint16 dst   = ins->operands[0].reg.orig;
2633
1
        MVMint16 sep   = ins->operands[1].reg.orig;
2634
1
        MVMint16 input = ins->operands[2].reg.orig;
2635
1
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2636
1
                                 { MVM_JIT_REG_VAL, { sep } },
2637
1
                                 { MVM_JIT_REG_VAL, { input } } };
2638
1
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
2639
1
        break;
2640
801
    }
2641
0
    case MVM_OP_replace: {
2642
0
        MVMint16 dst     = ins->operands[0].reg.orig;
2643
0
        MVMint16 a       = ins->operands[1].reg.orig;
2644
0
        MVMint16 start   = ins->operands[2].reg.orig;
2645
0
        MVMint16 length  = ins->operands[3].reg.orig;
2646
0
        MVMint16 replace = ins->operands[4].reg.orig;
2647
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2648
0
                                 { MVM_JIT_REG_VAL, { a } },
2649
0
                                 { MVM_JIT_REG_VAL, { start } },
2650
0
                                 { MVM_JIT_REG_VAL, { length } },
2651
0
                                 { MVM_JIT_REG_VAL, { replace } } };
2652
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, MVM_JIT_RV_PTR, dst);
2653
0
        break;
2654
801
    }
2655
306
    case MVM_OP_substr_s: {
2656
306
        MVMint16 dst = ins->operands[0].reg.orig;
2657
306
        MVMint16 string = ins->operands[1].reg.orig;
2658
306
        MVMint16 start = ins->operands[2].reg.orig;
2659
306
        MVMint16 length = ins->operands[3].reg.orig;
2660
306
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2661
306
                                 { MVM_JIT_REG_VAL, { string } },
2662
306
                                 { MVM_JIT_REG_VAL, { start } },
2663
306
                                 { MVM_JIT_REG_VAL, { length } } };
2664
306
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
2665
306
        break;
2666
801
    }
2667
10
    case MVM_OP_index_s: {
2668
10
        MVMint16 dst = ins->operands[0].reg.orig;
2669
10
        MVMint16 haystack = ins->operands[1].reg.orig;
2670
10
        MVMint16 needle = ins->operands[2].reg.orig;
2671
10
        MVMint16 start = ins->operands[3].reg.orig;
2672
10
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2673
10
                                 { MVM_JIT_REG_VAL, { haystack } },
2674
10
                                 { MVM_JIT_REG_VAL, { needle } },
2675
10
                                 { MVM_JIT_REG_VAL, { start } } };
2676
10
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
2677
10
        break;
2678
801
    }
2679
12
    case MVM_OP_iscclass: {
2680
12
        MVMint16 dst    = ins->operands[0].reg.orig;
2681
12
        MVMint16 cclass = ins->operands[1].reg.orig;
2682
12
        MVMint16 str    = ins->operands[2].reg.orig;
2683
12
        MVMint16 offset = ins->operands[3].reg.orig;
2684
12
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2685
12
                                 { MVM_JIT_REG_VAL, { cclass } },
2686
12
                                 { MVM_JIT_REG_VAL, { str } },
2687
12
                                 { MVM_JIT_REG_VAL, { offset } } };
2688
12
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_INT, dst);
2689
12
        break;
2690
801
    }
2691
34
    case MVM_OP_findcclass:
2692
34
    case MVM_OP_findnotcclass: {
2693
34
        MVMint16 dst    = ins->operands[0].reg.orig;
2694
34
        MVMint16 cclass = ins->operands[1].reg.orig;
2695
34
        MVMint16 target = ins->operands[2].reg.orig;
2696
34
        MVMint16 offset = ins->operands[3].reg.orig;
2697
34
        MVMint16 count  = ins->operands[4].reg.orig;
2698
34
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2699
34
                                 { MVM_JIT_REG_VAL, { cclass } },
2700
34
                                 { MVM_JIT_REG_VAL, { target } },
2701
34
                                 { MVM_JIT_REG_VAL, { offset } },
2702
34
                                 { MVM_JIT_REG_VAL, { count } } };
2703
34
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, MVM_JIT_RV_INT, dst);
2704
34
        break;
2705
34
    }
2706
20
    case MVM_OP_nfarunalt: {
2707
20
        MVMint16 nfa    = ins->operands[0].reg.orig;
2708
20
        MVMint16 target = ins->operands[1].reg.orig;
2709
20
        MVMint16 offset = ins->operands[2].reg.orig;
2710
20
        MVMint16 bstack = ins->operands[3].reg.orig;
2711
20
        MVMint16 cstack = ins->operands[4].reg.orig;
2712
20
        MVMint16 labels = ins->operands[5].reg.orig;
2713
20
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2714
20
                                 { MVM_JIT_REG_VAL, { nfa } },
2715
20
                                 { MVM_JIT_REG_VAL, { target } },
2716
20
                                 { MVM_JIT_REG_VAL, { offset } },
2717
20
                                 { MVM_JIT_REG_VAL, { bstack } },
2718
20
                                 { MVM_JIT_REG_VAL, { cstack } },
2719
20
                                 { MVM_JIT_REG_VAL, { labels } } };
2720
20
        jg_append_call_c(tc, jg, op_to_func(tc, op), 7, args, MVM_JIT_RV_VOID, -1);
2721
20
        break;
2722
34
    }
2723
0
    case MVM_OP_nfarunproto: {
2724
0
        MVMint16 dst     = ins->operands[0].reg.orig;
2725
0
        MVMint16 nfa     = ins->operands[1].reg.orig;
2726
0
        MVMint16 target  = ins->operands[2].reg.orig;
2727
0
        MVMint16 offset  = ins->operands[3].reg.orig;
2728
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2729
0
                                 { MVM_JIT_REG_VAL, { nfa } },
2730
0
                                 { MVM_JIT_REG_VAL, { target } },
2731
0
                                 { MVM_JIT_REG_VAL, { offset } } };
2732
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
2733
0
        break;
2734
34
    }
2735
644
    case MVM_OP_nfafromstatelist: {
2736
644
        MVMint16 dst     = ins->operands[0].reg.orig;
2737
644
        MVMint16 states  = ins->operands[1].reg.orig;
2738
644
        MVMint16 type    = ins->operands[2].reg.orig;
2739
644
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2740
644
                                 { MVM_JIT_REG_VAL, { states } },
2741
644
                                 { MVM_JIT_REG_VAL, { type } } };
2742
644
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
2743
644
        break;
2744
34
    }
2745
34
        /* encode/decode ops */
2746
8
    case MVM_OP_encode: {
2747
8
        MVMint16 dst = ins->operands[0].reg.orig;
2748
8
        MVMint16 str = ins->operands[1].reg.orig;
2749
8
        MVMint16 enc = ins->operands[2].reg.orig;
2750
8
        MVMint16 buf = ins->operands[3].reg.orig;
2751
8
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2752
8
                                 { MVM_JIT_REG_VAL, { str } },
2753
8
                                 { MVM_JIT_REG_VAL, { enc } },
2754
8
                                 { MVM_JIT_REG_VAL, { buf } },
2755
8
                                 { MVM_JIT_LITERAL_PTR, { 0 } } };
2756
8
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args, MVM_JIT_RV_PTR, dst);
2757
8
        break;
2758
34
    }
2759
0
    case MVM_OP_decoderaddbytes: {
2760
0
        MVMint16 decoder = ins->operands[0].reg.orig;
2761
0
        MVMint16 bytes   = ins->operands[1].reg.orig;
2762
0
        MVMJitCallArg argc[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2763
0
                                 { MVM_JIT_REG_VAL, { decoder } },
2764
0
                                 { MVM_JIT_LITERAL_PTR, { (MVMint64)"decoderaddbytes" } } };
2765
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2766
0
                                 { MVM_JIT_REG_VAL, { decoder } },
2767
0
                                 { MVM_JIT_REG_VAL, { bytes } } };
2768
0
        jg_append_call_c(tc, jg, &MVM_decoder_ensure_decoder, 3, argc, MVM_JIT_RV_VOID, -1);
2769
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
2770
0
        break;
2771
34
    }
2772
0
    case MVM_OP_decodertakeline: {
2773
0
        MVMint16 dst     = ins->operands[0].reg.orig;
2774
0
        MVMint16 decoder = ins->operands[1].reg.orig;
2775
0
        MVMint16 chomp   = ins->operands[2].reg.orig;
2776
0
        MVMint16 inc     = ins->operands[3].reg.orig;
2777
0
        MVMJitCallArg argc[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2778
0
                                 { MVM_JIT_REG_VAL, { decoder } },
2779
0
                                 { MVM_JIT_LITERAL_PTR, { (MVMint64)"decodertakeline" } } };
2780
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2781
0
                                 { MVM_JIT_REG_VAL, { decoder } },
2782
0
                                 { MVM_JIT_REG_VAL, { chomp } },
2783
0
                                 { MVM_JIT_REG_VAL, { inc } } };
2784
0
        jg_append_call_c(tc, jg, &MVM_decoder_ensure_decoder, 3, argc, MVM_JIT_RV_VOID, -1);
2785
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
2786
0
        break;
2787
34
    }
2788
34
        /* bigint ops */
2789
0
    case MVM_OP_isbig_I: {
2790
0
        MVMint16 dst = ins->operands[0].reg.orig;
2791
0
        MVMint16 src = ins->operands[1].reg.orig;
2792
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2793
0
                                 { MVM_JIT_REG_VAL, { src } } };
2794
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args,
2795
0
                          MVM_JIT_RV_INT, dst);
2796
0
        break;
2797
34
    }
2798
0
    case MVM_OP_cmp_I: {
2799
0
        MVMint16 src_a = ins->operands[1].reg.orig;
2800
0
        MVMint16 src_b = ins->operands[2].reg.orig;
2801
0
        MVMint16 dst   = ins->operands[0].reg.orig;
2802
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2803
0
                                 { MVM_JIT_REG_VAL, { src_a } },
2804
0
                                 { MVM_JIT_REG_VAL, { src_b } } };
2805
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args,
2806
0
                          MVM_JIT_RV_INT, dst);
2807
0
        break;
2808
34
    }
2809
0
    case MVM_OP_add_I:
2810
0
    case MVM_OP_sub_I:
2811
0
    case MVM_OP_mul_I:
2812
0
    case MVM_OP_div_I:
2813
0
    case MVM_OP_mod_I:
2814
0
    case MVM_OP_bor_I:
2815
0
    case MVM_OP_band_I:
2816
0
    case MVM_OP_bxor_I:
2817
0
    case MVM_OP_lcm_I:
2818
0
    case MVM_OP_gcd_I: {
2819
0
        MVMint16 src_a = ins->operands[1].reg.orig;
2820
0
        MVMint16 src_b = ins->operands[2].reg.orig;
2821
0
        MVMint16 type  = ins->operands[3].reg.orig;
2822
0
        MVMint16 dst   = ins->operands[0].reg.orig;
2823
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2824
0
                                 { MVM_JIT_REG_VAL, { type } },
2825
0
                                 { MVM_JIT_REG_VAL, { src_a } },
2826
0
                                 { MVM_JIT_REG_VAL, { src_b } } };
2827
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args,
2828
0
                          MVM_JIT_RV_PTR, dst);
2829
0
        break;
2830
0
    }
2831
0
    case MVM_OP_pow_I: {
2832
0
        MVMint16 src_a  = ins->operands[1].reg.orig;
2833
0
        MVMint16 src_b  = ins->operands[2].reg.orig;
2834
0
        MVMint16 type_n = ins->operands[3].reg.orig;
2835
0
        MVMint16 type_I = ins->operands[4].reg.orig;
2836
0
        MVMint16 dst    = ins->operands[0].reg.orig;
2837
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2838
0
                                 { MVM_JIT_REG_VAL, { src_a } },
2839
0
                                 { MVM_JIT_REG_VAL, { src_b } },
2840
0
                                 { MVM_JIT_REG_VAL, { type_n } },
2841
0
                                 { MVM_JIT_REG_VAL, { type_I } } };
2842
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args,
2843
0
                         MVM_JIT_RV_PTR, dst);
2844
0
        break;
2845
0
    }
2846
0
    case MVM_OP_div_In: {
2847
0
        MVMint16 dst   = ins->operands[0].reg.orig;
2848
0
        MVMint16 src_a = ins->operands[1].reg.orig;
2849
0
        MVMint16 src_b = ins->operands[2].reg.orig;
2850
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2851
0
                                 { MVM_JIT_REG_VAL, { src_a } },
2852
0
                                 { MVM_JIT_REG_VAL, { src_b } } };
2853
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_NUM, dst);
2854
0
        break;
2855
0
    }
2856
0
    case MVM_OP_brshift_I:
2857
0
    case MVM_OP_blshift_I: {
2858
0
        MVMint16 dst   = ins->operands[0].reg.orig;
2859
0
        MVMint16 src   = ins->operands[1].reg.orig;
2860
0
        MVMint16 shift = ins->operands[2].reg.orig;
2861
0
        MVMint16 type  = ins->operands[3].reg.orig;
2862
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2863
0
                                 { MVM_JIT_REG_VAL, { type } },
2864
0
                                 { MVM_JIT_REG_VAL, { src } },
2865
0
                                 { MVM_JIT_REG_VAL, { shift } } };
2866
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
2867
0
        break;
2868
0
    }
2869
0
    case MVM_OP_coerce_Is: {
2870
0
        MVMint16 src = ins->operands[1].reg.orig;
2871
0
        MVMint16 dst = ins->operands[0].reg.orig;
2872
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2873
0
                                 { MVM_JIT_REG_VAL, { src } },
2874
0
                                 { MVM_JIT_LITERAL, { 10 } } };
2875
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args,
2876
0
                          MVM_JIT_RV_PTR, dst);
2877
0
        break;
2878
0
    }
2879
6
    case MVM_OP_radix: {
2880
6
        MVMint16 dst = ins->operands[0].reg.orig;
2881
6
        MVMint16 radix = ins->operands[1].reg.orig;
2882
6
        MVMint16 string = ins->operands[2].reg.orig;
2883
6
        MVMint16 offset = ins->operands[3].reg.orig;
2884
6
        MVMint16 flag = ins->operands[4].reg.orig;
2885
6
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2886
6
                                 { MVM_JIT_REG_VAL, { radix } },
2887
6
                                 { MVM_JIT_REG_VAL, { string } },
2888
6
                                 { MVM_JIT_REG_VAL, { offset } },
2889
6
                                 { MVM_JIT_REG_VAL, { flag } } };
2890
6
        jg_append_call_c(tc, jg, op_to_func(tc, op), 5, args,
2891
6
                          MVM_JIT_RV_PTR, dst);
2892
6
        break;
2893
0
    }
2894
0
    case MVM_OP_radix_I: {
2895
0
        MVMint16 dst = ins->operands[0].reg.orig;
2896
0
        MVMint16 radix = ins->operands[1].reg.orig;
2897
0
        MVMint16 string = ins->operands[2].reg.orig;
2898
0
        MVMint16 offset = ins->operands[3].reg.orig;
2899
0
        MVMint16 flag = ins->operands[4].reg.orig;
2900
0
        MVMint16 type = ins->operands[5].reg.orig;
2901
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2902
0
                                 { MVM_JIT_REG_VAL, { radix } },
2903
0
                                 { MVM_JIT_REG_VAL, { string } },
2904
0
                                 { MVM_JIT_REG_VAL, { offset } },
2905
0
                                 { MVM_JIT_REG_VAL, { flag } },
2906
0
                                 { MVM_JIT_REG_VAL, { type } } };
2907
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 6, args,
2908
0
                          MVM_JIT_RV_PTR, dst);
2909
0
        break;
2910
0
    }
2911
0
    case MVM_OP_base_I: {
2912
0
        MVMint16 src  = ins->operands[1].reg.orig;
2913
0
        MVMint16 base = ins->operands[2].reg.orig;
2914
0
        MVMint16 dst  = ins->operands[0].reg.orig;
2915
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2916
0
                                 { MVM_JIT_REG_VAL, { src } },
2917
0
                                 { MVM_JIT_REG_VAL, { base } } };
2918
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args,
2919
0
                          MVM_JIT_RV_PTR, dst);
2920
0
        break;
2921
0
    }
2922
0
    case MVM_OP_isprime_I: {
2923
0
        MVMint16 dst = ins->operands[0].reg.orig;
2924
0
        MVMint32 invocant = ins->operands[1].reg.orig;
2925
0
        MVMint32 rounds   = ins->operands[2].reg.orig;
2926
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
2927
0
                                 { MVM_JIT_REG_VAL, invocant },
2928
0
                                 { MVM_JIT_REG_VAL, rounds } };
2929
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_INT, dst);
2930
0
        break;
2931
0
    }
2932
0
    case MVM_OP_bool_I: {
2933
0
        MVMint16 dst = ins->operands[0].reg.orig;
2934
0
        MVMint32 invocant = ins->operands[1].reg.orig;
2935
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
2936
0
                                 { MVM_JIT_REG_VAL, invocant } };
2937
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
2938
0
        break;
2939
0
    }
2940
0
    case MVM_OP_rand_I:
2941
0
    case MVM_OP_bnot_I: {
2942
0
        MVMint16 dst      = ins->operands[0].reg.orig;
2943
0
        MVMint32 invocant = ins->operands[1].reg.orig;
2944
0
        MVMint32 type     = ins->operands[2].reg.orig;
2945
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
2946
0
                                 { MVM_JIT_REG_VAL, type },
2947
0
                                 { MVM_JIT_REG_VAL, invocant } };
2948
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
2949
0
        break;
2950
0
    }
2951
1
    case MVM_OP_getcodeobj: {
2952
1
        MVMint16 dst = ins->operands[0].reg.orig;
2953
1
        MVMint32 invocant = ins->operands[1].reg.orig;
2954
1
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
2955
1
                                 { MVM_JIT_REG_VAL, invocant } };
2956
1
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
2957
1
        break;
2958
0
    }
2959
0
    case MVM_OP_floor_n:
2960
0
    case MVM_OP_sqrt_n:
2961
0
    case MVM_OP_sin_n:
2962
0
    case MVM_OP_cos_n:
2963
0
    case MVM_OP_tan_n:
2964
0
    case MVM_OP_asin_n:
2965
0
    case MVM_OP_acos_n:
2966
0
    case MVM_OP_atan_n: {
2967
0
        MVMint16 dst   = ins->operands[0].reg.orig;
2968
0
        MVMint16 src   = ins->operands[1].reg.orig;
2969
0
        MVMJitCallArg args[] = { { MVM_JIT_REG_VAL_F, { src } } };
2970
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 1, args,
2971
0
                          MVM_JIT_RV_NUM, dst);
2972
0
        break;
2973
0
    }
2974
0
    case MVM_OP_pow_n:
2975
0
    case MVM_OP_atan2_n: {
2976
0
        MVMint16 dst   = ins->operands[0].reg.orig;
2977
0
        MVMint16 a     = ins->operands[1].reg.orig;
2978
0
        MVMint16 b     = ins->operands[2].reg.orig;
2979
0
        MVMJitCallArg args[] = { { MVM_JIT_REG_VAL_F, { a } },
2980
0
                                 { MVM_JIT_REG_VAL_F, { b } } };
2981
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args,
2982
0
                          MVM_JIT_RV_NUM, dst);
2983
0
        break;
2984
0
    }
2985
6
    case MVM_OP_time_n: {
2986
6
        MVMint16 dst   = ins->operands[0].reg.orig;
2987
6
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } } };
2988
6
        jg_append_call_c(tc, jg, op_to_func(tc, op), 1, args,
2989
6
                          MVM_JIT_RV_NUM, dst);
2990
6
        break;
2991
0
    }
2992
2
    case MVM_OP_randscale_n: {
2993
2
        MVMint16 dst   = ins->operands[0].reg.orig;
2994
2
        MVMint16 scale = ins->operands[1].reg.orig;
2995
2
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
2996
2
                                 { MVM_JIT_REG_VAL_F, { scale } } };
2997
2
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_NUM, dst);
2998
2
        break;
2999
0
    }
3000
0
    case MVM_OP_isnanorinf: {
3001
0
        MVMint16 dst   = ins->operands[0].reg.orig;
3002
0
        MVMint16 src = ins->operands[1].reg.orig;
3003
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3004
0
                                 { MVM_JIT_REG_VAL_F, { src } } };
3005
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
3006
0
        break;
3007
0
    }
3008
0
    case MVM_OP_nativecallcast: {
3009
0
        MVMint16 dst     = ins->operands[0].reg.orig;
3010
0
        MVMint16 restype = ins->operands[1].reg.orig;
3011
0
        MVMint16 site    = ins->operands[2].reg.orig;
3012
0
        MVMint16 cargs   = ins->operands[3].reg.orig;
3013
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3014
0
                                 { MVM_JIT_REG_VAL, { restype } },
3015
0
                                 { MVM_JIT_REG_VAL, { site } },
3016
0
                                 { MVM_JIT_REG_VAL, { cargs } } };
3017
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args,
3018
0
                          MVM_JIT_RV_PTR, dst);
3019
0
        break;
3020
0
    }
3021
0
    case MVM_OP_nativecallinvoke: {
3022
0
        MVMint16 dst     = ins->operands[0].reg.orig;
3023
0
        MVMint16 restype = ins->operands[1].reg.orig;
3024
0
        MVMint16 site    = ins->operands[2].reg.orig;
3025
0
        MVMint16 cargs   = ins->operands[3].reg.orig;
3026
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3027
0
                                 { MVM_JIT_REG_VAL, { restype } },
3028
0
                                 { MVM_JIT_REG_VAL, { site } },
3029
0
                                 { MVM_JIT_REG_VAL, { cargs } } };
3030
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args,
3031
0
                          MVM_JIT_RV_PTR, dst);
3032
0
        break;
3033
0
    }
3034
0
    case MVM_OP_typeparameters:
3035
0
    case MVM_OP_typeparameterized: {
3036
0
        MVMint16 dst = ins->operands[0].reg.orig;
3037
0
        MVMint16 obj = ins->operands[1].reg.orig;
3038
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3039
0
                                 { MVM_JIT_REG_VAL, { obj } } };
3040
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
3041
0
        break;
3042
0
    }
3043
0
    case MVM_OP_typeparameterat: {
3044
0
        MVMint16 dst = ins->operands[0].reg.orig;
3045
0
        MVMint16 obj = ins->operands[1].reg.orig;
3046
0
        MVMint16 idx = ins->operands[2].reg.orig;
3047
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3048
0
                                 { MVM_JIT_REG_VAL, { obj } },
3049
0
                                 { MVM_JIT_REG_VAL, { idx } } };
3050
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
3051
0
        break;
3052
0
    }
3053
2
    case MVM_OP_objectid: {
3054
2
        MVMint16 dst = ins->operands[0].reg.orig;
3055
2
        MVMint16 obj = ins->operands[1].reg.orig;
3056
2
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3057
2
                                 { MVM_JIT_REG_VAL, { obj } } };
3058
2
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
3059
2
        break;
3060
0
    }
3061
0
        /* native references (as simple function calls for now) */
3062
0
    case MVM_OP_iscont_i:
3063
0
    case MVM_OP_iscont_n:
3064
0
    case MVM_OP_iscont_s:
3065
0
    case MVM_OP_isrwcont: {
3066
0
        MVMint16 dst = ins->operands[0].reg.orig;
3067
0
        MVMint16 obj = ins->operands[1].reg.orig;
3068
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3069
0
                                 { MVM_JIT_REG_VAL, { obj } } };
3070
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_INT, dst);
3071
0
        break;
3072
0
    }
3073
0
    case MVM_OP_assign_i:
3074
0
    case MVM_OP_assign_n:
3075
0
    case MVM_OP_assign_s: {
3076
0
        MVMint16 target = ins->operands[0].reg.orig;
3077
0
        MVMint16 value  = ins->operands[1].reg.orig;
3078
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3079
0
                                 { MVM_JIT_REG_VAL, { target } },
3080
0
                                 { MVM_JIT_REG_VAL, { value } } };
3081
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
3082
0
        break;
3083
0
    }
3084
0
    case MVM_OP_decont_i:
3085
0
    case MVM_OP_decont_n:
3086
0
    case MVM_OP_decont_s: {
3087
0
        MVMint16 dst = ins->operands[0].reg.orig;
3088
0
        MVMint16 obj = ins->operands[1].reg.orig;
3089
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3090
0
                                 { MVM_JIT_REG_VAL, { obj } },
3091
0
                                 { MVM_JIT_REG_ADDR, { dst } } };
3092
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
3093
0
        break;
3094
0
    }
3095
0
    case MVM_OP_getrusage: {
3096
0
        MVMint16 obj = ins->operands[0].reg.orig;
3097
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3098
0
                                 { MVM_JIT_REG_VAL, { obj } } };
3099
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
3100
0
        break;
3101
0
    }
3102
0
    case MVM_OP_threadlockcount: {
3103
0
        MVMint16 dst = ins->operands[0].reg.orig;
3104
0
        MVMint16 obj = ins->operands[1].reg.orig;
3105
0
        MVMJitCallArg args[] =  { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3106
0
                                  { MVM_JIT_REG_VAL, { obj } } };
3107
0
        jg_append_call_c(tc, jg, MVM_thread_lock_count, 2, args, MVM_JIT_RV_INT, dst);
3108
0
        break;
3109
0
    }
3110
0
    case MVM_OP_cpucores: {
3111
0
        MVMint16 dst = ins->operands[0].reg.orig;
3112
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 0, NULL, MVM_JIT_RV_INT, dst);
3113
0
        break;
3114
0
    }
3115
0
    case MVM_OP_getsignals: {
3116
0
        MVMint16 dst = ins->operands[0].reg.orig;
3117
0
        MVMJitCallArg args[] =  { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } } };
3118
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 1, args, MVM_JIT_RV_PTR, dst);
3119
0
        break;
3120
0
    }
3121
0
    case MVM_OP_sleep: {
3122
0
        MVMint16 time = ins->operands[0].reg.orig;
3123
0
        MVMJitCallArg block_args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } } };
3124
0
        MVMJitCallArg sleep_args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3125
0
                                       { MVM_JIT_REG_VAL, { time } } };
3126
0
        jg_append_call_c(tc, jg, MVM_gc_mark_thread_blocked, 1, block_args, MVM_JIT_RV_VOID, -1);
3127
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, sleep_args, MVM_JIT_RV_VOID, -1);
3128
0
        jg_append_call_c(tc, jg, MVM_gc_mark_thread_unblocked, 1, block_args, MVM_JIT_RV_VOID, -1);
3129
0
        break;
3130
0
    }
3131
0
    case MVM_OP_currentthread: {
3132
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } } };
3133
0
        jg_append_call_c(tc, jg, MVM_thread_current, 1, args, MVM_JIT_RV_PTR, ins->operands[0].reg.orig);
3134
0
        break;
3135
0
    }
3136
0
    case MVM_OP_getlexref_i:
3137
0
    case MVM_OP_getlexref_i32:
3138
0
    case MVM_OP_getlexref_i16:
3139
0
    case MVM_OP_getlexref_i8:
3140
0
    case MVM_OP_getlexref_n:
3141
0
    case MVM_OP_getlexref_n32:
3142
0
    case MVM_OP_getlexref_s: {
3143
0
        MVMint16 dst     = ins->operands[0].reg.orig;
3144
0
        MVMuint16 outers = ins->operands[1].lex.outers;
3145
0
        MVMuint16 idx    = ins->operands[1].lex.idx;
3146
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3147
0
                                 { MVM_JIT_LITERAL, { outers } },
3148
0
                                 { MVM_JIT_LITERAL, { idx } } };
3149
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
3150
0
        break;
3151
0
    }
3152
0
    case MVM_OP_getattrref_i:
3153
0
    case MVM_OP_getattrref_n:
3154
0
    case MVM_OP_getattrref_s: {
3155
0
        MVMint16 dst     = ins->operands[0].reg.orig;
3156
0
        MVMint16 obj     = ins->operands[1].reg.orig;
3157
0
        MVMint16 class   = ins->operands[2].reg.orig;
3158
0
        MVMint16 name    = ins->operands[3].lit_str_idx;
3159
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3160
0
                                 { MVM_JIT_REG_VAL, { obj } },
3161
0
                                 { MVM_JIT_REG_VAL, { class } },
3162
0
                                 { MVM_JIT_STR_IDX, { name } } };
3163
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
3164
0
        break;
3165
0
    }
3166
0
    case MVM_OP_getattrsref_i:
3167
0
    case MVM_OP_getattrsref_n:
3168
0
    case MVM_OP_getattrsref_s: {
3169
0
        MVMint16 dst     = ins->operands[0].reg.orig;
3170
0
        MVMint16 obj     = ins->operands[1].reg.orig;
3171
0
        MVMint16 class   = ins->operands[2].reg.orig;
3172
0
        MVMint16 name    = ins->operands[3].reg.orig;
3173
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3174
0
                                 { MVM_JIT_REG_VAL, { obj } },
3175
0
                                 { MVM_JIT_REG_VAL, { class } },
3176
0
                                 { MVM_JIT_REG_VAL, { name } } };
3177
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 4, args, MVM_JIT_RV_PTR, dst);
3178
0
        break;
3179
0
    }
3180
0
    case MVM_OP_atposref_i:
3181
0
    case MVM_OP_atposref_n:
3182
0
    case MVM_OP_atposref_s: {
3183
0
        MVMint16 dst     = ins->operands[0].reg.orig;
3184
0
        MVMint16 obj     = ins->operands[1].reg.orig;
3185
0
        MVMint16 index   = ins->operands[2].reg.orig;
3186
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3187
0
                                 { MVM_JIT_REG_VAL, { obj } },
3188
0
                                 { MVM_JIT_REG_VAL, { index } } };
3189
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_PTR, dst);
3190
0
        break;
3191
0
    }
3192
0
        /* profiling */
3193
0
    case MVM_OP_prof_allocated: {
3194
0
        MVMint16 reg = ins->operands[0].reg.orig;
3195
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3196
0
                                 { MVM_JIT_REG_VAL, { reg } } };
3197
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
3198
0
        break;
3199
0
    }
3200
0
    case MVM_OP_prof_exit: {
3201
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } } };
3202
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 1, args, MVM_JIT_RV_VOID, -1);
3203
0
        break;
3204
0
    }
3205
0
        /* special jumplist branch */
3206
713
    case MVM_OP_jumplist: {
3207
713
        return consume_jumplist(tc, jg, iter, ins);
3208
0
    }
3209
0
        /* returning */
3210
6
    case MVM_OP_return: {
3211
6
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  { MVM_JIT_INTERP_TC } },
3212
6
                                 { MVM_JIT_LITERAL, { 0 } }};
3213
6
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
3214
6
        jg_append_call_c(tc, jg, &MVM_frame_try_return, 1, args, MVM_JIT_RV_VOID, -1);
3215
6
        break;
3216
0
    }
3217
4.37k
    case MVM_OP_return_o:
3218
4.37k
    case MVM_OP_return_s:
3219
4.37k
    case MVM_OP_return_n:
3220
4.37k
    case MVM_OP_return_i: {
3221
4.37k
        MVMint16 reg = ins->operands[0].reg.orig;
3222
4.37k
        MVMJitCallArg args[] = {{ MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3223
4.37k
                                 { MVM_JIT_REG_VAL, { reg } },
3224
4.37k
                                 { MVM_JIT_LITERAL, { 0 } } };
3225
4.37k
        if (op == MVM_OP_return_n) {
3226
2
            args[1].type = MVM_JIT_REG_VAL_F;
3227
2
        }
3228
4.37k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
3229
4.37k
        /* reuse args for tc arg */
3230
4.37k
        jg_append_call_c(tc, jg, &MVM_frame_try_return, 1, args, MVM_JIT_RV_VOID, -1);
3231
4.37k
        break;
3232
4.37k
    }
3233
37.5k
    case MVM_OP_sp_guard:
3234
37.5k
    case MVM_OP_sp_guardconc:
3235
37.5k
    case MVM_OP_sp_guardtype:
3236
37.5k
    case MVM_OP_sp_guardsf:
3237
37.5k
    case MVM_OP_sp_guardobj:
3238
37.5k
    case MVM_OP_sp_guardnotobj:
3239
37.5k
        jg_append_guard(tc, jg, ins, 2);
3240
37.5k
        break;
3241
6
    case MVM_OP_sp_guardjustconc:
3242
6
    case MVM_OP_sp_guardjusttype:
3243
6
        jg_append_guard(tc, jg, ins, 1);
3244
6
        break;
3245
4.02k
    case MVM_OP_sp_resolvecode: {
3246
4.02k
        MVMint16 dst     = ins->operands[0].reg.orig;
3247
4.02k
        MVMint16 obj     = ins->operands[1].reg.orig;
3248
4.02k
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3249
4.02k
                                 { MVM_JIT_REG_VAL, { obj } } };
3250
4.02k
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
3251
4.02k
        break;
3252
6
    }
3253
27.0k
    case MVM_OP_prepargs: {
3254
27.0k
        return consume_invoke(tc, jg, iter, ins);
3255
6
    }
3256
0
    case MVM_OP_getexcategory: {
3257
0
        MVMint16 dst     = ins->operands[0].reg.orig;
3258
0
        MVMint16 obj     = ins->operands[1].reg.orig;
3259
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3260
0
                                 { MVM_JIT_REG_VAL, { obj } } };
3261
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_PTR, dst);
3262
0
        break;
3263
6
    }
3264
0
    case MVM_OP_bindexcategory: {
3265
0
        MVMint16 obj      = ins->operands[0].reg.orig;
3266
0
        MVMint16 category = ins->operands[1].reg.orig;
3267
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3268
0
                                 { MVM_JIT_REG_VAL, { obj } },
3269
0
                                 { MVM_JIT_REG_VAL, { category } } };
3270
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
3271
0
        break;
3272
6
    }
3273
0
    case MVM_OP_exreturnafterunwind: {
3274
0
        MVMint16 obj      = ins->operands[0].reg.orig;
3275
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3276
0
                                 { MVM_JIT_REG_VAL, { obj } } };
3277
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 2, args, MVM_JIT_RV_VOID, -1);
3278
0
        break;
3279
6
    }
3280
154
    case MVM_OP_sp_getstringfrom: {
3281
154
        MVMint16 spesh_idx = ins->operands[1].lit_i16;
3282
154
        MVMuint32 cu_idx = ins->operands[2].lit_str_idx;
3283
154
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3284
154
                                 { MVM_JIT_SPESH_SLOT_VALUE, { spesh_idx } },
3285
154
                                 { MVM_JIT_LITERAL, cu_idx } };
3286
154
        jg_append_call_c(tc, jg, MVM_cu_string, 3, args, MVM_JIT_RV_PTR, ins->operands[0].reg.orig);
3287
154
        break;
3288
6
    }
3289
0
    case MVM_OP_encoderepconf: {
3290
0
        MVMint16 dst = ins->operands[0].reg.orig;
3291
0
        MVMint16 str = ins->operands[1].reg.orig;
3292
0
        MVMint16 encoding = ins->operands[2].reg.orig;
3293
0
        MVMint16 replacement = ins->operands[3].reg.orig;
3294
0
        MVMint16 blob = ins->operands[4].reg.orig;
3295
0
        MVMint16 config = ins->operands[5].reg.orig;
3296
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, { MVM_JIT_INTERP_TC } },
3297
0
                                 { MVM_JIT_REG_VAL, { str } },
3298
0
                                 { MVM_JIT_REG_VAL, { encoding } },
3299
0
                                 { MVM_JIT_REG_VAL, { blob } },
3300
0
                                 { MVM_JIT_REG_VAL, { replacement } },
3301
0
                                 { MVM_JIT_REG_VAL, { config } } };
3302
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 6, args, MVM_JIT_RV_PTR, dst);
3303
0
        break;
3304
6
    }
3305
0
    case MVM_OP_breakpoint: {
3306
0
        MVMint32 file_idx = ins->operands[0].lit_i16;
3307
0
        MVMint32 line_no  = ins->operands[1].lit_i16;
3308
0
        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR, MVM_JIT_INTERP_TC },
3309
0
                                 { MVM_JIT_LITERAL, file_idx },
3310
0
                                 { MVM_JIT_LITERAL, line_no } };
3311
0
        jg_append_call_c(tc, jg, op_to_func(tc, op), 3, args, MVM_JIT_RV_VOID, -1);
3312
0
        break;
3313
6
    }
3314
324
    default: {
3315
324
        /* Check if it's an extop. */
3316
324
        MVMint32 emitted_extop = 0;
3317
324
        if (ins->info->opcode == (MVMuint16)-1) {
3318
0
            MVMExtOpRecord *extops     = jg->sg->sf->body.cu->body.extops;
3319
0
            MVMuint16       num_extops = jg->sg->sf->body.cu->body.num_extops;
3320
0
            MVMuint16       i;
3321
0
            for (i = 0; i < num_extops; i++) {
3322
0
                if (extops[i].info == ins->info && !extops[i].no_jit) {
3323
0
                    size_t fake_regs_size;
3324
0
                    MVMuint16 *fake_regs = try_fake_extop_regs(tc, jg->sg, ins, &fake_regs_size);
3325
0
                    if (fake_regs_size && fake_regs != NULL) {
3326
0
                        MVMint32  data_label = jg_add_data_node(tc, jg, fake_regs, fake_regs_size);
3327
0
                        MVMJitCallArg args[] = { { MVM_JIT_INTERP_VAR,  { MVM_JIT_INTERP_TC } },
3328
0
                                                 { MVM_JIT_DATA_LABEL,  { data_label } }};
3329
0
                        jg_append_call_c(tc, jg, extops[i].func, 2, args, MVM_JIT_RV_VOID, -1);
3330
0
                        MVM_jit_log(tc, "append extop: <%s>\n", ins->info->name);
3331
0
                        emitted_extop = 1;
3332
0
                    }
3333
0
                    break;
3334
0
                }
3335
0
            }
3336
0
        }
3337
324
        if (!emitted_extop) {
3338
324
            MVM_jit_log(tc, "BAIL: op <%s>\n", ins->info->name);
3339
324
            return 0;
3340
324
        }
3341
324
    }
3342
285k
    }
3343
257k
    return 1;
3344
285k
}
3345
3346
static MVMint32 consume_bb(MVMThreadContext *tc, MVMJitGraph *jg,
3347
296k
                           MVMSpeshIterator *iter, MVMSpeshBB *bb) {
3348
296k
    MVMJitExprTree *tree = NULL;
3349
296k
    MVMint32 i;
3350
296k
    MVMint32 label = MVM_jit_label_before_bb(tc, jg, bb);
3351
296k
    jg_append_label(tc, jg, label);
3352
296k
3353
296k
    /* add a jit breakpoint if required */
3354
296k
    for (i = 0; i < tc->instance->jit_breakpoints_num; i++) {
3355
0
        if (tc->instance->jit_breakpoints[i].frame_nr == tc->instance->jit_seq_nr &&
3356
0
            tc->instance->jit_breakpoints[i].block_nr == iter->bb->idx) {
3357
0
            jg_append_control(tc, jg, bb->first_ins, MVM_JIT_CONTROL_BREAKPOINT);
3358
0
            break; /* one is enough though */
3359
0
        }
3360
0
    }
3361
296k
3362
296k
    /* Try to create an expression tree */
3363
296k
    if (tc->instance->jit_expr_enabled &&
3364
296k
        (tc->instance->jit_expr_last_frame < 0 ||
3365
0
         tc->instance->jit_seq_nr < tc->instance->jit_expr_last_frame ||
3366
0
         (tc->instance->jit_seq_nr == tc->instance->jit_expr_last_frame &&
3367
0
          (tc->instance->jit_expr_last_bb < 0 ||
3368
296k
           iter->bb->idx <= tc->instance->jit_expr_last_bb)))) {
3369
296k
3370
522k
        while (iter->ins) {
3371
296k
            /* consumes iterator */
3372
296k
            tree = MVM_jit_expr_tree_build(tc, jg, iter);
3373
296k
            if (tree != NULL) {
3374
262k
                MVMJitNode *node = MVM_spesh_alloc(tc, jg->sg, sizeof(MVMJitNode));
3375
262k
                node->type       = MVM_JIT_NODE_EXPR_TREE;
3376
262k
                node->u.tree     = tree;
3377
262k
                tree->seq_nr     = jg->expr_seq_nr++;
3378
262k
                jg_append_node(jg, node);
3379
262k
                MVM_jit_log_expr_tree(tc, tree);
3380
262k
            }
3381
296k
            if (iter->ins) {
3382
71.5k
                /* something we can't compile yet, or simply an empty tree */
3383
71.5k
                break;
3384
71.5k
            }
3385
296k
        }
3386
296k
    }
3387
296k
3388
296k
    /* Try to consume the (rest of the) basic block per instruction */
3389
581k
    while (iter->ins) {
3390
285k
        before_ins(tc, jg, iter, iter->ins);
3391
285k
        if(!consume_ins(tc, jg, iter, iter->ins))
3392
324
            return 0;
3393
284k
        after_ins(tc, jg, iter, iter->ins);
3394
284k
        MVM_spesh_iterator_next_ins(tc, iter);
3395
284k
    }
3396
296k
3397
296k
    return 1;
3398
296k
}
3399
3400
3401
11.1k
MVMJitGraph * MVM_jit_try_make_graph(MVMThreadContext *tc, MVMSpeshGraph *sg) {
3402
11.1k
    MVMSpeshIterator iter;
3403
11.1k
    MVMJitGraph *graph;
3404
11.1k
3405
11.1k
    if (!MVM_jit_support()) {
3406
0
        return NULL;
3407
0
    }
3408
11.1k
3409
11.1k
    if (tc->instance->jit_log_fh) {
3410
0
        char *cuuid = MVM_string_utf8_encode_C_string(tc, sg->sf->body.cuuid);
3411
0
        char *name  = MVM_string_utf8_encode_C_string(tc, sg->sf->body.name);
3412
0
        MVM_jit_log(tc, "Constructing JIT graph (cuuid: %s, name: '%s')\n",
3413
0
                    cuuid, name);
3414
0
        MVM_free(cuuid);
3415
0
        MVM_free(name);
3416
0
    }
3417
11.1k
3418
11.1k
    MVM_spesh_iterator_init(tc, &iter, sg);
3419
11.1k
    /* ignore first BB, which always contains a NOP */
3420
11.1k
    MVM_spesh_iterator_next_bb(tc, &iter);
3421
11.1k
3422
11.1k
    graph             = MVM_spesh_alloc(tc, sg, sizeof(MVMJitGraph));
3423
11.1k
    graph->sg         = sg;
3424
11.1k
    graph->first_node = NULL;
3425
11.1k
    graph->last_node  = NULL;
3426
11.1k
3427
11.1k
    /* Set initial instruction label offset */
3428
11.1k
    graph->obj_label_ofs = sg->num_bbs + 1;
3429
11.1k
3430
11.1k
    /* Labels for individual instructions (not basic blocks), for instance at
3431
11.1k
     * boundaries of exception handling frames */
3432
11.1k
    MVM_VECTOR_INIT(graph->obj_labels, 16);
3433
11.1k
3434
11.1k
    /* Deoptimization labels */
3435
11.1k
    MVM_VECTOR_INIT(graph->deopts, 8);
3436
11.1k
    /* Nodes for each label, used to ensure labels aren't added twice */
3437
11.1k
    MVM_VECTOR_INIT(graph->label_nodes, 16 + sg->num_bbs);
3438
11.1k
3439
11.1k
    graph->expr_seq_nr = 0;
3440
11.1k
3441
11.1k
    /* JIT handlers are indexed by spesh graph handler index */
3442
11.1k
    if (sg->num_handlers > 0) {
3443
4.13k
        MVM_VECTOR_INIT(graph->handlers, sg->num_handlers);
3444
4.13k
        graph->handlers_num = sg->num_handlers;
3445
6.96k
    } else {
3446
6.96k
        graph->handlers     = NULL;
3447
6.96k
        graph->handlers_num = 0;
3448
6.96k
    }
3449
11.1k
3450
11.1k
    /* JIT inlines are indexed by spesh graph inline index */
3451
11.1k
    if (sg->num_inlines > 0) {
3452
3.27k
        MVM_VECTOR_INIT(graph->inlines, sg->num_inlines);
3453
3.27k
        graph->inlines_num = sg->num_inlines;
3454
7.83k
    } else {
3455
7.83k
        graph->inlines     = NULL;
3456
7.83k
        graph->inlines_num = 0;
3457
7.83k
    }
3458
11.1k
3459
11.1k
    /* Add start-of-graph label */
3460
11.1k
    jg_append_label(tc, graph, MVM_jit_label_before_graph(tc, graph, sg));
3461
11.1k
    /* Loop over basic blocks */
3462
307k
    while (iter.bb) {
3463
296k
        if (!consume_bb(tc, graph, &iter, iter.bb))
3464
324
            goto bail;
3465
296k
        MVM_spesh_iterator_next_bb(tc, &iter);
3466
296k
    }
3467
11.1k
    /* Check if we've added a instruction at all */
3468
10.7k
    if (!graph->first_node)
3469
0
        goto bail;
3470
10.7k
3471
10.7k
    /* append the end-of-graph label */
3472
10.7k
    jg_append_label(tc, graph, MVM_jit_label_after_graph(tc, graph, sg));
3473
10.7k
3474
10.7k
    /* Calculate number of basic block + graph labels */
3475
10.7k
    graph->num_labels    = graph->obj_label_ofs + graph->obj_labels_num;
3476
10.7k
3477
10.7k
    return graph;
3478
10.7k
3479
324
 bail:
3480
324
    MVM_jit_graph_destroy(tc, graph);
3481
324
    return NULL;
3482
10.7k
}
3483
3484
11.0k
void MVM_jit_graph_destroy(MVMThreadContext *tc, MVMJitGraph *graph) {
3485
11.0k
    MVMJitNode *node;
3486
11.0k
    /* destroy all trees */
3487
870k
    for (node = graph->first_node; node != NULL; node = node->next) {
3488
859k
        if (node->type == MVM_JIT_NODE_EXPR_TREE) {
3489
250k
            MVM_jit_expr_tree_destroy(tc, node->u.tree);
3490
250k
        }
3491
859k
    }
3492
11.0k
    MVM_free(graph->label_nodes);
3493
11.0k
    MVM_free(graph->obj_labels);
3494
11.0k
    MVM_free(graph->deopts);
3495
11.0k
    MVM_free(graph->handlers);
3496
11.0k
    MVM_free(graph->inlines);
3497
11.0k
}