24 #include "insns_info.inc"
32 #undef RUBY_UNTYPED_DATA_WARNING
33 #define RUBY_UNTYPED_DATA_WARNING 0
35 #define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
36 #define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
130 #define compile_debug CPDEBUG
132 #define compile_debug ISEQ_COMPILE_DATA(iseq)->option->debug_level
137 #define compile_debug_print_indent(level) \
138 ruby_debug_print_indent((level), compile_debug, gl_node_level * 2)
140 #define debugp(header, value) (void) \
141 (compile_debug_print_indent(1) && \
142 ruby_debug_print_value(1, compile_debug, (header), (value)))
144 #define debugi(header, id) (void) \
145 (compile_debug_print_indent(1) && \
146 ruby_debug_print_id(1, compile_debug, (header), (id)))
148 #define debugp_param(header, value) (void) \
149 (compile_debug_print_indent(1) && \
150 ruby_debug_print_value(1, compile_debug, (header), (value)))
152 #define debugp_verbose(header, value) (void) \
153 (compile_debug_print_indent(2) && \
154 ruby_debug_print_value(2, compile_debug, (header), (value)))
156 #define debugp_verbose_node(header, value) (void) \
157 (compile_debug_print_indent(10) && \
158 ruby_debug_print_value(10, compile_debug, (header), (value)))
160 #define debug_node_start(node) ((void) \
161 (compile_debug_print_indent(1) && \
162 (ruby_debug_print_node(1, CPDEBUG, "", (const NODE *)(node)), gl_node_level)), \
165 #define debug_node_end() gl_node_level --
169 #define debugi(header, id) ((void)0)
170 #define debugp(header, value) ((void)0)
171 #define debugp_verbose(header, value) ((void)0)
172 #define debugp_verbose_node(header, value) ((void)0)
173 #define debugp_param(header, value) ((void)0)
174 #define debug_node_start(node) ((void)0)
175 #define debug_node_end() ((void)0)
178 #if CPDEBUG > 1 || CPDEBUG < 0
179 #define printf ruby_debug_printf
180 #define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
181 #define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v))
183 #define debugs if(0)printf
184 #define debug_compile(msg, v) (v)
187 #define LVAR_ERRINFO (1)
190 #define NEW_LABEL(l) new_label_body(iseq, (l))
191 #define LABEL_FORMAT "<L%03d>"
193 #define NEW_ISEQ(node, name, type, line_no) \
194 new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no))
196 #define NEW_CHILD_ISEQ(node, name, type, line_no) \
197 new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no))
200 #define ADD_SEQ(seq1, seq2) \
201 APPEND_LIST((seq1), (seq2))
204 #define ADD_INSN(seq, line, insn) \
205 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
208 #define INSERT_BEFORE_INSN(next, line, insn) \
209 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
212 #define INSERT_AFTER_INSN(prev, line, insn) \
213 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
216 #define ADD_INSN1(seq, line, insn, op1) \
217 ADD_ELEM((seq), (LINK_ELEMENT *) \
218 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
221 #define INSERT_BEFORE_INSN1(next, line, insn, op1) \
222 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) \
223 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
226 #define INSERT_AFTER_INSN1(prev, line, insn, op1) \
227 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) \
228 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
230 #define LABEL_REF(label) ((label)->refcnt++)
233 #define ADD_INSNL(seq, line, insn, label) (ADD_INSN1(seq, line, insn, label), LABEL_REF(label))
235 #define ADD_INSN2(seq, line, insn, op1, op2) \
236 ADD_ELEM((seq), (LINK_ELEMENT *) \
237 new_insn_body(iseq, (line), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
239 #define ADD_INSN3(seq, line, insn, op1, op2, op3) \
240 ADD_ELEM((seq), (LINK_ELEMENT *) \
241 new_insn_body(iseq, (line), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
244 #define ADD_SEND(seq, line, id, argc) \
245 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL)
247 #define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag) \
248 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)(flag), NULL)
250 #define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block) \
251 ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(0), NULL)
253 #define ADD_CALL_RECEIVER(seq, line) \
254 ADD_INSN((seq), (line), putself)
256 #define ADD_CALL(seq, line, id, argc) \
257 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
259 #define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \
260 ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
262 #define ADD_SEND_R(seq, line, id, argc, block, flag, keywords) \
263 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
265 #define ADD_TRACE(seq, event) \
266 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), 0))
267 #define ADD_TRACE_WITH_DATA(seq, event, data) \
268 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), (data)))
271 #define DECL_BRANCH_BASE(branches, first_line, first_column, last_line, last_column, type) \
273 if (ISEQ_COVERAGE(iseq) && \
274 ISEQ_BRANCH_COVERAGE(iseq) && \
275 (first_line) > 0) { \
276 VALUE structure = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 0); \
277 branches = rb_ary_tmp_new(5); \
278 rb_ary_push(structure, branches); \
279 rb_ary_push(branches, ID2SYM(rb_intern(type))); \
280 rb_ary_push(branches, INT2FIX(first_line)); \
281 rb_ary_push(branches, INT2FIX(first_column)); \
282 rb_ary_push(branches, INT2FIX(last_line)); \
283 rb_ary_push(branches, INT2FIX(last_column)); \
286 #define ADD_TRACE_BRANCH_COVERAGE(seq, first_line, first_column, last_line, last_column, type, branches) \
288 if (ISEQ_COVERAGE(iseq) && \
289 ISEQ_BRANCH_COVERAGE(iseq) && \
290 (first_line) > 0) { \
291 VALUE counters = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 1); \
292 long counter_idx = RARRAY_LEN(counters); \
293 rb_ary_push(counters, INT2FIX(0)); \
294 rb_ary_push(branches, ID2SYM(rb_intern(type))); \
295 rb_ary_push(branches, INT2FIX(first_line)); \
296 rb_ary_push(branches, INT2FIX(first_column)); \
297 rb_ary_push(branches, INT2FIX(last_line)); \
298 rb_ary_push(branches, INT2FIX(last_column)); \
299 rb_ary_push(branches, INT2FIX(counter_idx)); \
300 ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx); \
301 ADD_INSN(seq, last_line, nop); \
308 #define ADD_GETLOCAL(seq, line, idx, level) iseq_add_getlocal(iseq, (seq), (line), (idx), (level))
309 #define ADD_SETLOCAL(seq, line, idx, level) iseq_add_setlocal(iseq, (seq), (line), (idx), (level))
312 #define ADD_LABEL(seq, label) \
313 ADD_ELEM((seq), (LINK_ELEMENT *) (label))
315 #define APPEND_LABEL(seq, before, label) \
316 APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label))
318 #define ADD_ADJUST(seq, line, label) \
319 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), (line)))
321 #define ADD_ADJUST_RESTORE(seq, label) \
322 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1))
324 #define LABEL_UNREMOVABLE(label) \
325 ((label) ? (LABEL_REF(label), (label)->unremovable=1) : 0)
326 #define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \
327 VALUE _e = rb_ary_new3(5, (type), \
328 (VALUE)(ls) | 1, (VALUE)(le) | 1, \
329 (VALUE)(iseqv), (VALUE)(lc) | 1); \
330 LABEL_UNREMOVABLE(ls); \
333 if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) \
334 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, rb_ary_tmp_new(3)); \
335 rb_ary_push(ISEQ_COMPILE_DATA(iseq)->catch_table_ary, freeze_hide_obj(_e)); \
339 #define COMPILE(anchor, desc, node) \
340 (debug_compile("== " desc "\n", \
341 iseq_compile_each(iseq, (anchor), (node), 0)))
344 #define COMPILE_POPPED(anchor, desc, node) \
345 (debug_compile("== " desc "\n", \
346 iseq_compile_each(iseq, (anchor), (node), 1)))
349 #define COMPILE_(anchor, desc, node, popped) \
350 (debug_compile("== " desc "\n", \
351 iseq_compile_each(iseq, (anchor), (node), (popped))))
353 #define COMPILE_RECV(anchor, desc, node) \
354 (private_recv_p(node) ? \
355 (ADD_INSN(anchor, nd_line(node), putself), VM_CALL_FCALL) : \
356 COMPILE(anchor, desc, node->nd_recv) ? 0 : -1)
358 #define OPERAND_AT(insn, idx) \
359 (((INSN*)(insn))->operands[(idx)])
361 #define INSN_OF(insn) \
362 (((INSN*)(insn))->insn_id)
364 #define IS_INSN(link) ((link)->type == ISEQ_ELEMENT_INSN)
365 #define IS_LABEL(link) ((link)->type == ISEQ_ELEMENT_LABEL)
366 #define IS_ADJUST(link) ((link)->type == ISEQ_ELEMENT_ADJUST)
367 #define IS_TRACE(link) ((link)->type == ISEQ_ELEMENT_TRACE)
368 #define IS_INSN_ID(iobj, insn) (INSN_OF(iobj) == BIN(insn))
369 #define IS_NEXT_INSN_ID(link, insn) \
370 ((link)->next && IS_INSN((link)->next) && IS_INSN_ID((link)->next, insn))
380 VALUE err_info = ISEQ_COMPILE_DATA(
iseq)->err_info;
388 if (
NIL_P(err_info)) {
392 else if (!err_info) {
413 #define COMPILE_ERROR append_compile_error
415 #define ERROR_ARGS_AT(n) iseq, nd_line(n),
416 #define ERROR_ARGS ERROR_ARGS_AT(node)
418 #define EXPECT_NODE(prefix, node, ndtype, errval) \
420 const NODE *error_node = (node); \
421 enum node_type error_type = nd_type(error_node); \
422 if (error_type != (ndtype)) { \
423 COMPILE_ERROR(ERROR_ARGS_AT(error_node) \
424 prefix ": " #ndtype " is expected, but %s", \
425 ruby_node_name(error_type)); \
430 #define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval) \
432 COMPILE_ERROR(ERROR_ARGS_AT(parent) \
433 prefix ": must be " #ndtype ", but 0"); \
437 #define UNKNOWN_NODE(prefix, node, errval) \
439 const NODE *error_node = (node); \
440 COMPILE_ERROR(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \
441 ruby_node_name(nd_type(error_node))); \
448 #define CHECK(sub) if (!(sub)) {BEFORE_RETURN;return COMPILE_NG;}
449 #define NO_CHECK(sub) (void)(sub)
450 #define BEFORE_RETURN
454 #define DECL_ANCHOR(name) \
455 LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},}}
456 #define INIT_ANCHOR(name) \
457 (name->last = &name->anchor)
467 #include "optinsn.inc"
468 #if OPT_INSTRUCTIONS_UNIFICATION
469 #include "optunifs.inc"
474 #define ISEQ_ARG iseq,
475 #define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
478 #define ISEQ_ARG_DECLARE
482 #define gl_node_level ISEQ_COMPILE_DATA(iseq)->node_level
488 static int insn_data_length(
INSN *iobj);
489 static int calc_sp_depth(
int depth,
INSN *iobj);
530 if (plist !=
list->prev) {
537 if (anchor->
last != plist && anchor->
last != 0) {
542 rb_bug(
"list verify error: %08x (%s)", flag, info);
547 #define verify_list(info, anchor) verify_list(iseq, (info), (anchor))
556 while (i < iseq->body->iseq_size) {
558 const char *
types = insn_op_types(insn);
560 for (
int j=0;
types[j]; j++) {
561 if (
types[j] == TS_CALLDATA) {
566 rb_bug(
"call cache not zero for fresh iseq");
581 elem->
prev = anchor->last;
582 anchor->last->
next = elem;
584 verify_list(
"add", anchor);
597 if (before == anchor->last) anchor->last = elem;
598 verify_list(
"add", anchor);
601 #define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem))
602 #define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem))
605 #define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line)
637 ADD_INSN(ret, ISEQ_COMPILE_DATA(
iseq)->last_line, leave);
640 return iseq_setup(
iseq, ret);
655 iseq_set_local_table(
iseq, 0);
660 iseq_set_local_table(
iseq, node->nd_tbl);
661 iseq_set_arguments(
iseq, ret, node->nd_args);
664 case ISEQ_TYPE_BLOCK:
685 case ISEQ_TYPE_CLASS:
690 ISEQ_COMPILE_DATA(
iseq)->last_line =
nd_line(node);
693 case ISEQ_TYPE_METHOD:
698 ISEQ_COMPILE_DATA(
iseq)->last_line =
nd_line(node);
709 #define INVALID_ISEQ_TYPE(type) \
710 ISEQ_TYPE_##type: m = #type; goto invalid_iseq_type
718 #undef INVALID_ISEQ_TYPE
719 case ISEQ_TYPE_RESCUE:
720 iseq_set_exception_local_table(
iseq);
723 case ISEQ_TYPE_ENSURE:
724 iseq_set_exception_local_table(
iseq);
727 case ISEQ_TYPE_PLAIN:
744 ADD_INSN(ret, ISEQ_COMPILE_DATA(
iseq)->last_line, leave);
748 if (ISEQ_COMPILE_DATA(
iseq)->labels_table) {
749 st_table *labels_table = ISEQ_COMPILE_DATA(
iseq)->labels_table;
750 ISEQ_COMPILE_DATA(
iseq)->labels_table = 0;
751 validate_labels(
iseq, labels_table);
755 return iseq_setup(
iseq, ret);
761 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
768 int len = insn_len(insn);
769 encoded[
i] = (
VALUE)table[insn];
780 VALUE *original_code;
782 if (ISEQ_ORIGINAL_ISEQ(
iseq))
return ISEQ_ORIGINAL_ISEQ(
iseq);
786 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
791 const void *addr = (
const void *)original_code[
i];
794 original_code[
i] = insn;
799 return original_code;
812 #if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__)
813 #define STRICT_ALIGNMENT
816 #ifdef STRICT_ALIGNMENT
817 #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE
818 #define ALIGNMENT_SIZE SIZEOF_LONG_LONG
820 #define ALIGNMENT_SIZE SIZEOF_VALUE
822 #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1))
823 #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX
826 #define PADDING_SIZE_MAX 0
829 #ifdef STRICT_ALIGNMENT
832 calc_padding(
void *
ptr,
size_t size)
839 padding = ALIGNMENT_SIZE - mis;
845 #if ALIGNMENT_SIZE > SIZEOF_VALUE
860 #ifdef STRICT_ALIGNMENT
861 size_t padding = calc_padding((
void *)&storage->
buff[storage->
pos],
size);
863 const size_t padding = 0;
867 if (storage->
pos +
size + padding > storage->
size) {
868 unsigned int alloc_size = storage->
size;
876 storage = *arena = storage->
next;
879 storage->
size = alloc_size;
880 #ifdef STRICT_ALIGNMENT
881 padding = calc_padding((
void *)&storage->
buff[storage->
pos],
size);
885 #ifdef STRICT_ALIGNMENT
886 storage->
pos += (
int)padding;
898 return compile_data_alloc_with_arena(arena,
size);
905 return compile_data_alloc(
iseq,
size);
912 return (
INSN *)compile_data_alloc_with_arena(arena,
sizeof(
INSN));
1002 anchor->last = anchor->last->
prev;
1003 anchor->last->
next = 0;
1004 verify_list(
"pop", anchor);
1008 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor))
1015 switch (elem->
type) {
1016 case ISEQ_ELEMENT_INSN:
1017 case ISEQ_ELEMENT_ADJUST:
1027 LIST_INSN_SIZE_ONE(
const LINK_ANCHOR *
const anchor)
1029 LINK_ELEMENT *first_insn = ELEM_FIRST_INSN(FIRST_ELEMENT(anchor));
1030 if (first_insn !=
NULL &&
1031 ELEM_FIRST_INSN(first_insn->
next) ==
NULL) {
1040 LIST_INSN_SIZE_ZERO(
const LINK_ANCHOR *
const anchor)
1042 if (ELEM_FIRST_INSN(FIRST_ELEMENT(anchor)) ==
NULL) {
1063 anc1->last = anc2->
last;
1065 verify_list(
"append", anc1);
1068 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
1077 printf(
"anch: %p, frst: %p, last: %p\n", &anchor->anchor,
1078 anchor->anchor.next, anchor->last);
1080 printf(
"curr: %p, next: %p, prev: %p, type: %d\n",
list,
list->next,
1086 dump_disasm_list(anchor->anchor.next);
1087 verify_list(
"debug list", anchor);
1090 #define debug_list(anc) debug_list(iseq, (anc))
1093 #define debug_list(anc) ((void)0)
1099 TRACE *trace = compile_data_alloc_trace(
iseq);
1101 trace->
link.
type = ISEQ_ELEMENT_TRACE;
1103 trace->
event = event;
1112 LABEL *labelobj = compile_data_alloc_label(
iseq);
1114 labelobj->
link.
type = ISEQ_ELEMENT_LABEL;
1117 labelobj->
label_no = ISEQ_COMPILE_DATA(
iseq)->label_no++;
1130 ADJUST *adjust = compile_data_alloc_adjust(
iseq);
1131 adjust->
link.
type = ISEQ_ELEMENT_ADJUST;
1133 adjust->
label = label;
1143 INSN *iobj = compile_data_alloc_insn(
iseq);
1147 iobj->
link.
type = ISEQ_ELEMENT_INSN;
1161 VALUE *operands = 0;
1173 return new_insn_core(
iseq, line_no, insn_id,
argc, operands);
1180 struct
rb_call_info *
ci = (struct rb_call_info *)compile_data_alloc(iseq, size);
1198 kw_arg ==
NULL && !has_blockiseq) {
1209 operands[1] = (
VALUE)blockiseq;
1210 return new_insn_core(
iseq, line_no,
BIN(send), 2, operands);
1224 debugs(
"[new_child_iseq]> ---------------------------------------\n");
1228 debugs(
"[new_child_iseq]< ---------------------------------------\n");
1238 debugs(
"[new_child_iseq_with_callback]> ---------------------------------------\n");
1242 debugs(
"[new_child_iseq_with_callback]< ---------------------------------------\n");
1273 while (pos < body->iseq_size) {
1274 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
1279 if (insn ==
BIN(
throw)) {
1280 set_catch_except_p(body);
1283 pos += insn_len(insn);
1289 for (
i = 0;
i < ct->
size;
i++) {
1304 VALUE catch_table_ary = ISEQ_COMPILE_DATA(
iseq)->catch_table_ary;
1305 if (
NIL_P(catch_table_ary))
return;
1306 unsigned int i, tlen = (
unsigned int)
RARRAY_LEN(catch_table_ary);
1308 for (
i = 0;
i < tlen;
i++) {
1315 INSN *nop = new_insn_core(
iseq, 0,
BIN(nop), 0, 0);
1316 ELEM_INSERT_NEXT(
end, &nop->
link);
1326 if (
RTEST(ISEQ_COMPILE_DATA(
iseq)->err_info))
1332 dump_disasm_list(FIRST_ELEMENT(anchor));
1334 debugs(
"[compile step 3.1 (iseq_optimize)]\n");
1335 iseq_optimize(
iseq, anchor);
1338 dump_disasm_list(FIRST_ELEMENT(anchor));
1340 if (ISEQ_COMPILE_DATA(
iseq)->option->instructions_unification) {
1341 debugs(
"[compile step 3.2 (iseq_insns_unification)]\n");
1342 iseq_insns_unification(
iseq, anchor);
1344 dump_disasm_list(FIRST_ELEMENT(anchor));
1347 if (ISEQ_COMPILE_DATA(
iseq)->option->stack_caching) {
1348 debugs(
"[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
1349 iseq_set_sequence_stackcaching(
iseq, anchor);
1351 dump_disasm_list(FIRST_ELEMENT(anchor));
1354 debugs(
"[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n");
1355 iseq_insert_nop_between_end_and_cont(
iseq);
1363 if (
RTEST(ISEQ_COMPILE_DATA(
iseq)->err_info))
1366 debugs(
"[compile step 4.1 (iseq_set_sequence)]\n");
1369 dump_disasm_list(FIRST_ELEMENT(anchor));
1371 debugs(
"[compile step 4.2 (iseq_set_exception_table)]\n");
1374 debugs(
"[compile step 4.3 (set_optargs_table)] \n");
1377 debugs(
"[compile step 5 (iseq_translate_threaded_code)] \n");
1380 update_catch_except_flags(
iseq->
body);
1386 verify_call_cache(
iseq);
1387 debugs(
"[compile step: finish]\n");
1431 "get_local_var_idx: %d", idx);
1440 int lv = 0, idx = -1;
1444 idx = get_dyna_var_idx_at_raw(
iseq,
id);
1454 "get_dyna_var_idx: -1");
1463 iseq_local_block_param_p(
const rb_iseq_t *
iseq,
unsigned int idx,
unsigned int level)
1482 iseq_block_param_id_p(
const rb_iseq_t *
iseq,
ID id,
int *pidx,
int *plevel)
1485 int idx = get_dyna_var_idx(
iseq,
id, &level, &ls);
1486 if (iseq_local_block_param_p(
iseq, ls - idx, level)) {
1499 if (iseq_local_block_param_p(
iseq, idx, level)) {
1510 if (iseq_local_block_param_p(
iseq, idx, level)) {
1564 struct rb_iseq_param_keyword *keyword;
1567 int kw = 0, rkw = 0, di = 0,
i;
1574 node = node->nd_next;
1577 keyword->bits_start = arg_size++;
1581 const NODE *val_node = node->nd_body->nd_value;
1590 dv = val_node->nd_lit;
1606 keyword->num = ++di;
1610 node = node->nd_next;
1616 keyword->rest_start = arg_size++;
1619 keyword->required_num = rkw;
1620 keyword->table = &body->
local_table[keyword->bits_start - keyword->num];
1627 if (dv == complex_mark) dv =
Qundef;
1634 keyword->default_values = dvs;
1642 debugs(
"iseq_set_arguments: %s\n", node_args ?
"" :
"0");
1678 node = node->nd_next;
1690 for (j = 0; j <
i+1; j++) {
1719 arg_size = iseq_set_arguments_keywords(
iseq, optargs, args, arg_size);
1722 struct rb_iseq_param_keyword *keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
1723 keyword->rest_start = arg_size++;
1736 iseq_calc_param_size(
iseq);
1746 if (body->
type == ISEQ_TYPE_BLOCK) {
1802 else if (tlit != tval) {
1828 cdhash_hash(
VALUE a)
1878 ISEQ_COMPILE_DATA(
iseq)->ivar_cache_table = tbl;
1885 #define BADINSN_DUMP(anchor, list, dest) \
1886 dump_disasm_list_with_cursor(FIRST_ELEMENT(anchor), list, dest)
1888 #define BADINSN_ERROR \
1889 (xfree(generated_iseq), \
1890 xfree(insns_info), \
1891 BADINSN_DUMP(anchor, list, NULL), \
1897 int stack_max = 0, sp = 0, line = 0;
1901 if (
list->type == ISEQ_ELEMENT_LABEL) {
1908 switch (
list->type) {
1909 case ISEQ_ELEMENT_INSN:
1917 sp = calc_sp_depth(sp, iobj);
1921 "argument stack underflow (%d)", sp);
1924 if (sp > stack_max) {
1932 types = insn_op_types(insn);
1933 len = insn_len(insn);
1940 "operand size miss! (%d for %d)",
1945 for (j = 0;
types[j]; j++) {
1946 if (
types[j] == TS_OFFSET) {
1955 if (lobj->
sp == -1) {
1962 case ISEQ_ELEMENT_LABEL:
1965 if (lobj->
sp == -1) {
1973 case ISEQ_ELEMENT_TRACE:
1978 case ISEQ_ELEMENT_ADJUST:
1984 if (adjust->
line_no != -1 && orig_sp - sp < 0) {
1987 "iseq_set_sequence: adjust bug %d < %d",
2004 int insns_info_index,
int code_index,
const INSN *iobj)
2006 if (insns_info_index == 0 ||
2011 positions[insns_info_index] = code_index;
2019 int insns_info_index,
int code_index,
const ADJUST *adjust)
2021 if (insns_info_index > 0 ||
2022 insns_info[insns_info_index-1].line_no != adjust->
line_no) {
2024 insns_info[insns_info_index].
events = 0;
2025 positions[insns_info_index] = code_index;
2039 unsigned int *positions;
2041 VALUE *generated_iseq;
2045 int insn_num, code_index, insns_info_index, sp = 0;
2051 insn_num = code_index = 0;
2053 switch (
list->type) {
2054 case ISEQ_ELEMENT_INSN:
2058 sp = calc_sp_depth(sp, iobj);
2076 code_index += insn_data_length(iobj);
2081 case ISEQ_ELEMENT_LABEL:
2088 case ISEQ_ELEMENT_TRACE:
2091 events |= trace->
event;
2095 case ISEQ_ELEMENT_ADJUST:
2101 if (orig_sp - sp > 0) {
2102 if (orig_sp - sp > 1) code_index++;
2116 positions =
ALLOC_N(
unsigned int, insn_num);
2122 ISEQ_COMPILE_DATA(
iseq)->ci_index = ISEQ_COMPILE_DATA(
iseq)->ci_kw_index = 0;
2124 list = FIRST_ELEMENT(anchor);
2125 insns_info_index = code_index = sp = 0;
2128 switch (
list->type) {
2129 case ISEQ_ELEMENT_INSN:
2137 sp = calc_sp_depth(sp, iobj);
2141 generated_iseq[code_index] = insn;
2142 types = insn_op_types(insn);
2143 len = insn_len(insn);
2145 for (j = 0;
types[j]; j++) {
2153 generated_iseq[code_index + 1 + j] = lobj->
position - (code_index +
len);
2158 VALUE map = operands[j];
2161 data.pos = code_index;
2166 freeze_hide_obj(map);
2167 generated_iseq[code_index + 1 + j] = map;
2174 generated_iseq[code_index + 1 + j] =
FIX2INT(operands[j]);
2180 generated_iseq[code_index + 1 + j] =
v;
2195 unsigned int ic_index =
FIX2UINT(operands[j]);
2200 "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
2203 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
2216 assert(ISEQ_COMPILE_DATA(
iseq)->ci_kw_index <= body->ci_kw_size);
2220 cd->
ci = *source_ci;
2221 assert(ISEQ_COMPILE_DATA(
iseq)->ci_index <= body->ci_size);
2224 generated_iseq[code_index + 1 + j] = (
VALUE)cd;
2228 generated_iseq[code_index + 1 + j] =
SYM2ID(operands[j]);
2234 generated_iseq[code_index + 1 + j] = (
VALUE)entry;
2238 generated_iseq[code_index + 1 + j] = operands[j];
2241 generated_iseq[code_index + 1 + j] = operands[j];
2245 "unknown operand type: %c",
type);
2249 if (add_insn_info(insns_info, positions, insns_info_index, code_index, iobj)) insns_info_index++;
2253 case ISEQ_ELEMENT_LABEL:
2259 case ISEQ_ELEMENT_ADJUST:
2264 if (adjust->
label) {
2272 const int diff = orig_sp - sp;
2274 if (add_adjust_info(insns_info, positions, insns_info_index, code_index, adjust)) insns_info_index++;
2277 generated_iseq[code_index++] =
BIN(adjuststack);
2278 generated_iseq[code_index++] = orig_sp - sp;
2280 else if (diff == 1) {
2281 generated_iseq[code_index++] =
BIN(pop);
2283 else if (diff < 0) {
2285 xfree(generated_iseq);
2290 "iseq_set_sequence: adjust bug to %d %d < %d",
2291 label_no, orig_sp, sp);
2314 REALLOC_N(positions,
unsigned int, insns_info_index);
2322 label_get_position(
LABEL *lobj)
2328 label_get_sp(
LABEL *lobj)
2337 unsigned int tlen,
i;
2340 if (
NIL_P(ISEQ_COMPILE_DATA(
iseq)->catch_table_ary))
goto no_catch_table;
2348 for (
i = 0;
i < table->
size;
i++) {
2351 entry->
type = (
enum catch_type)(
ptr[0] & 0xffff);
2353 entry->
end = label_get_position((
LABEL *)(
ptr[2] & ~1));
2360 entry->
cont = label_get_position(lobj);
2361 entry->
sp = label_get_sp(lobj);
2364 if (entry->
type == CATCH_TYPE_RESCUE ||
2365 entry->
type == CATCH_TYPE_BREAK ||
2366 entry->
type == CATCH_TYPE_NEXT) {
2402 opt_table[
i] = label_get_position((
LABEL *)opt_table[
i]);
2409 get_destination_insn(
INSN *iobj)
2417 switch (
list->type) {
2418 case ISEQ_ELEMENT_INSN:
2419 case ISEQ_ELEMENT_ADJUST:
2421 case ISEQ_ELEMENT_LABEL:
2424 case ISEQ_ELEMENT_TRACE:
2427 events |= trace->
event;
2443 get_next_insn(
INSN *iobj)
2457 get_prev_insn(
INSN *iobj)
2471 unref_destination(
INSN *iobj,
int pos)
2479 replace_destination(
INSN *dobj,
INSN *nobj)
2491 find_destination(
INSN *
i)
2493 int pos,
len = insn_len(
i->insn_id);
2494 for (pos = 0; pos <
len; ++pos) {
2495 if (insn_op_types(
i->insn_id)[pos] == TS_OFFSET) {
2506 int *unref_counts = 0, nlabels = ISEQ_COMPILE_DATA(
iseq)->label_no;
2509 unref_counts =
ALLOCA_N(
int, nlabels);
2510 MEMZERO(unref_counts,
int, nlabels);
2519 else if ((lab = find_destination((
INSN *)
i)) != 0) {
2528 if (
i == first)
return 0;
2541 }
while ((
i =
i->next) != 0);
2547 int pos,
len = insn_len(insn);
2548 for (pos = 0; pos <
len; ++pos) {
2549 switch (insn_op_types(insn)[pos]) {
2551 unref_destination((
INSN *)
i, pos);
2563 }
while ((
i != end) && (
i =
i->next) != 0);
2572 ELEM_REMOVE(&iobj->
link);
2575 ELEM_REMOVE(&iobj->
link);
2588 if (debug1 == debug2)
return TRUE;
2599 is_frozen_putstring(
INSN *insn,
VALUE *op)
2637 INSN *niobj, *ciobj, *
dup = 0;
2642 case BIN(putstring):
2648 case BIN(putobject):
2651 default:
return FALSE;
2654 ciobj = (
INSN *)get_next_insn(iobj);
2659 ciobj = (
INSN *)get_next_insn(
dup = ciobj);
2662 niobj = (
INSN *)get_next_insn(ciobj);
2674 case BIN(branchunless):
2689 ELEM_INSERT_NEXT(&niobj->
link, &dest->
link);
2704 optimize_checktype(
iseq, iobj);
2707 INSN *niobj, *diobj, *piobj;
2708 diobj = (
INSN *)get_destination_insn(iobj);
2709 niobj = (
INSN *)get_next_insn(iobj);
2711 if (diobj == niobj) {
2718 unref_destination(iobj, 0);
2719 ELEM_REMOVE(&iobj->
link);
2722 else if (iobj != diobj &&
IS_INSN(&diobj->
link) &&
2735 replace_destination(iobj, diobj);
2754 unref_destination(iobj, 0);
2760 ELEM_INSERT_NEXT(&iobj->
link, &pop->
link);
2767 INSN *pdiobj = (
INSN *)get_destination_insn(piobj);
2768 if (niobj == pdiobj) {
2786 ?
BIN(branchunless) :
BIN(branchif);
2787 replace_destination(piobj, iobj);
2789 ELEM_REMOVE(&iobj->
link);
2796 else if (diobj == pdiobj) {
2812 ELEM_REPLACE(&piobj->
link, &popiobj->
link);
2832 VALUE str_beg, str_end;
2835 (end = (
INSN *)get_prev_insn(
range)) != 0 &&
2836 is_frozen_putstring(end, &str_end) &&
2837 (beg = (
INSN *)get_prev_insn(end)) != 0 &&
2838 is_frozen_putstring(beg, &str_beg)) {
2842 ELEM_REMOVE(&beg->
link);
2843 ELEM_REMOVE(&end->
link);
2865 INSN *nobj = (
INSN *)get_destination_insn(iobj);
2887 int stop_optimization =
2890 if (!stop_optimization) {
2902 replace_destination(iobj, nobj);
2923 replace_destination(iobj, nobj);
2970 if (prev_dup || !
IS_INSN_ID(pobj, newarray)) {
2973 else if (!iseq_pop_newarray(
iseq, pobj)) {
2975 ELEM_INSERT_PREV(&iobj->
link, &pobj->
link);
2980 ELEM_INSERT_NEXT(&iobj->
link, &pobj->
link);
2986 unref_destination(iobj, 0);
2987 ELEM_REMOVE(&iobj->
link);
2992 nobj = (
INSN *)get_destination_insn(nobj);
3007 if (previ ==
BIN(putobject) || previ ==
BIN(putnil) ||
3008 previ ==
BIN(putself) || previ ==
BIN(putstring) ||
3010 previ ==
BIN(getlocal) ||
3011 previ ==
BIN(getblockparam) ||
3012 previ ==
BIN(getblockparamproxy) ||
3014 previ ==
BIN(duparray)) {
3018 ELEM_REMOVE(&iobj->
link);
3020 else if (previ ==
BIN(newarray) && iseq_pop_newarray(
iseq, (
INSN*)prev)) {
3021 ELEM_REMOVE(&iobj->
link);
3023 else if (previ ==
BIN(concatarray)) {
3028 else if (previ ==
BIN(concatstrings)) {
3033 ELEM_REMOVE(&iobj->
link);
3086 ELEM_REMOVE(&next->
link);
3088 ELEM_REMOVE(&iobj->
link);
3102 next = (freeze = next)->next;
3104 next = get_destination_insn(jump = (
INSN *)next);
3111 ELEM_REMOVE(&label->
link);
3119 if (same_debug_pos_p(freeze, next->
next)) {
3120 ELEM_REMOVE(freeze);
3126 ELEM_INSERT_NEXT(next, &label->
link);
3127 CHECK(iseq_peephole_optimize(
iseq, get_next_insn(jump), do_tailcallopt));
3130 if (freeze) ELEM_REMOVE(freeze);
3149 ci->orig_argc == 0) {
3155 if (do_tailcallopt &&
3184 next = get_destination_insn((
INSN *)next);
3217 ELEM_REMOVE(&iobj->
link);
3225 ELEM_REMOVE(set1->
next);
3235 niobj = niobj->
next;
3247 if (
IS_INSN_ID(iobj, opt_invokebuiltin_delegate)) {
3250 iobj->
insn_id =
BIN(opt_invokebuiltin_delegate_leave);
3264 if (insn_id ==
BIN(opt_neq)) {
3269 iobj->
operands[1] = old_operands[0];
3290 ELEM_REMOVE(&niobj->
link);
3294 ELEM_REMOVE(&niobj->
link);
3305 #define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
3307 switch (
ci->orig_argc) {
3361 case ISEQ_TYPE_EVAL:
3362 case ISEQ_TYPE_MAIN:
3364 case ISEQ_TYPE_RESCUE:
3365 case ISEQ_TYPE_ENSURE:
3377 const int do_peepholeopt = ISEQ_COMPILE_DATA(
iseq)->option->peephole_optimization;
3378 const int do_tailcallopt = tailcallable_p(
iseq) &&
3379 ISEQ_COMPILE_DATA(
iseq)->option->tailcall_optimization;
3380 const int do_si = ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction;
3381 const int do_ou = ISEQ_COMPILE_DATA(
iseq)->option->operands_unification;
3382 int rescue_level = 0;
3383 int tailcallopt = do_tailcallopt;
3385 list = FIRST_ELEMENT(anchor);
3389 if (do_peepholeopt) {
3390 iseq_peephole_optimize(
iseq,
list, tailcallopt);
3396 insn_operands_unification((
INSN *)
list);
3403 tailcallopt =
FALSE;
3406 if (!--rescue_level) tailcallopt = do_tailcallopt;
3415 #if OPT_INSTRUCTIONS_UNIFICATION
3459 #if OPT_INSTRUCTIONS_UNIFICATION
3465 list = FIRST_ELEMENT(anchor);
3470 if (unified_insns_data[
id] != 0) {
3471 const int *
const *entry = unified_insns_data[
id];
3472 for (j = 1; j < (
intptr_t)entry[0]; j++) {
3473 const int *unified = entry[j];
3475 for (k = 2; k < unified[1]; k++) {
3477 ((
INSN *)li)->insn_id != unified[k]) {
3484 new_unified_insn(
iseq, unified[0], unified[1] - 1,
3507 #if OPT_STACK_CACHING
3509 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
3510 #define SC_NEXT(insn) sc_insn_next[(insn)]
3512 #include "opt_sc.inc"
3521 iobj->
insn_id = SC_INSN(insn_id, state);
3522 nstate = SC_NEXT(iobj->
insn_id);
3524 if (insn_id ==
BIN(jump) ||
3525 insn_id ==
BIN(branchif) || insn_id ==
BIN(branchunless)) {
3541 if (insn_id ==
BIN(jump)) {
3545 else if (insn_id ==
BIN(leave)) {
3553 label_set_sc_state(
LABEL *lobj,
int state)
3573 #if OPT_STACK_CACHING
3579 list = FIRST_ELEMENT(anchor);
3585 switch (
list->type) {
3586 case ISEQ_ELEMENT_INSN:
3597 if (state != SCS_AX) {
3599 new_insn_body(
iseq, 0,
BIN(reput), 0);
3610 if (state == SCS_AB || state == SCS_BA) {
3611 state = (state == SCS_AB ? SCS_BA : SCS_AB);
3648 state = insn_set_sc_state(
iseq, anchor, iobj, state);
3651 case ISEQ_ELEMENT_LABEL:
3656 state = label_set_sc_state(lobj, state);
3668 all_string_result_p(
const NODE *node)
3670 if (!node)
return FALSE;
3675 if (!node->nd_body || !node->nd_else)
return FALSE;
3676 if (all_string_result_p(node->nd_body))
3677 return all_string_result_p(node->nd_else);
3681 return all_string_result_p(node->nd_1st);
3682 if (!all_string_result_p(node->nd_1st))
3684 return all_string_result_p(node->nd_2nd);
3694 VALUE lit = node->nd_lit;
3709 if (
RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
3713 const NODE *
const head =
list->nd_head;
3726 if (
NIL_P(lit) && first_lit) {
3727 ELEM_REMOVE(first_lit);
3757 const int line =
nd_line(node);
3768 ADD_INSNL(ret, line, branchunless, else_label);
3778 ADD_INSNL(ret, line, branchunless, then_label);
3795 CHECK(compile_branch_condition(
iseq, ret, cond->nd_1st, label,
3797 if (!label->
refcnt)
break;
3799 cond = cond->nd_2nd;
3805 CHECK(compile_branch_condition(
iseq, ret, cond->nd_1st, then_label,
3807 if (!label->
refcnt)
break;
3809 cond = cond->nd_2nd;
3833 CHECK(compile_flip_flop(
iseq, ret, cond,
TRUE, then_label, else_label));
3836 CHECK(compile_flip_flop(
iseq, ret, cond,
FALSE, then_label, else_label));
3852 keyword_node_p(
const NODE *
const node)
3859 const NODE *
const root_node,
3865 if (keyword_node_p(root_node) && root_node->nd_head &&
nd_type(root_node->nd_head) ==
NODE_LIST) {
3866 const NODE *node = root_node->nd_head;
3869 const NODE *key_node = node->nd_head;
3883 node = node->nd_next;
3884 node = node->nd_next;
3888 node = root_node->nd_head;
3890 int len = (
int)node->nd_alen / 2;
3897 *kw_arg_ptr = kw_arg;
3899 for (
i=0; node !=
NULL;
i++, node = node->nd_next->nd_next) {
3900 const NODE *key_node = node->nd_head;
3901 const NODE *val_node = node->nd_next->nd_head;
3918 for (; node;
len++, node = node->nd_next) {
3923 if (node->nd_next ==
NULL &&
3924 compile_keyword_arg(
iseq, ret, node->nd_head, keywords_ptr, flag)) {
3938 node = node->nd_head;
3946 return ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal;
3955 node = node->nd_head;
3975 return node->nd_lit;
3994 for (; node; node = node->nd_next) {
4037 const int max_stack_len = 0x100;
4038 const int min_tmp_ary_len = 0x40;
4040 int first_chunk = 1;
4043 #define FLUSH_CHUNK(newarrayinsn) \
4045 ADD_INSN1(ret, line, newarrayinsn, INT2FIX(stack_len)); \
4046 if (!first_chunk) ADD_INSN(ret, line, concatarray); \
4047 first_chunk = stack_len = 0; \
4054 if (static_literal_node_p(node,
iseq)) {
4056 const NODE *node_tmp = node->nd_next;
4057 for (; node_tmp && static_literal_node_p(node_tmp,
iseq); node_tmp = node_tmp->nd_next)
4060 if ((first_chunk && stack_len == 0 && !node_tmp) ||
count >= min_tmp_ary_len) {
4084 for (;
count;
count--, node = node->nd_next) {
4092 if (!node->nd_next && keyword_node_p(node->nd_head)) {
4099 if (stack_len >= max_stack_len)
FLUSH_CHUNK(newarray);
4111 return node->nd_head && static_literal_node_p(node,
iseq) && static_literal_node_p(node->nd_next,
iseq);
4119 node = node->nd_head;
4131 for (; node; node = node->nd_next) {
4155 const int max_stack_len = 0x100;
4156 const int min_tmp_hash_len = 0x800;
4158 int first_chunk = 1;
4163 #define FLUSH_CHUNK() \
4165 if (first_chunk) { \
4166 APPEND_LIST(ret, anchor); \
4167 ADD_INSN1(ret, line, newhash, INT2FIX(stack_len)); \
4170 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \
4171 ADD_INSN(ret, line, swap); \
4172 APPEND_LIST(ret, anchor); \
4173 ADD_SEND(ret, line, id_core_hash_merge_ptr, INT2FIX(stack_len + 1)); \
4175 INIT_ANCHOR(anchor); \
4176 first_chunk = stack_len = 0; \
4183 if (static_literal_node_pair_p(node,
iseq)) {
4185 const NODE *node_tmp = node->nd_next->nd_next;
4186 for (; node_tmp && static_literal_node_pair_p(node_tmp,
iseq); node_tmp = node_tmp->nd_next->nd_next)
4189 if ((first_chunk && stack_len == 0 && !node_tmp) ||
count >= min_tmp_hash_len) {
4194 for (;
count;
count--, node = node->nd_next->nd_next) {
4196 elem[0] = static_literal_value(node,
iseq);
4197 elem[1] = static_literal_value(node->nd_next,
iseq);
4224 for (;
count;
count--, node = node->nd_next->nd_next) {
4230 if (node->nd_head) {
4233 NO_CHECK(
COMPILE_(anchor,
"hash value element", node->nd_next->nd_head, 0));
4243 const NODE *kw = node->nd_next->nd_head;
4245 int first_kw = first_chunk && stack_len == 0;
4246 int last_kw = !node->nd_next->nd_next;
4247 int only_kw = last_kw && first_kw;
4257 else if (first_kw) {
4318 LABEL *l1,
int only_special_literals,
VALUE literals)
4321 const NODE *val = vals->nd_head;
4325 only_special_literals = 0;
4340 if (!
COMPILE(cond_seq,
"when cond", val))
return -1;
4345 vals = vals->nd_next;
4347 return only_special_literals;
4352 LABEL *l1,
int only_special_literals,
VALUE literals)
4354 const int line =
nd_line(vals);
4358 if (when_vals(
iseq, cond_seq, vals, l1, only_special_literals, literals) < 0)
4366 ADD_INSNL(cond_seq, line, branchif, l1);
4369 CHECK(when_splat_vals(
iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
4370 CHECK(when_splat_vals(
iseq, cond_seq, vals->nd_body, l1, only_special_literals, literals));
4373 CHECK(when_splat_vals(
iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
4375 CHECK(
COMPILE(cond_seq,
"when argspush body", vals->nd_body));
4377 ADD_INSNL(cond_seq, line, branchif, l1);
4384 ADD_INSNL(cond_seq, line, branchif, l1);
4403 iobj = (
INSN *)get_prev_insn((
INSN *)LAST_ELEMENT(ret));
4421 ELEM_REMOVE(FIRST_ELEMENT(anchor));
4429 ELEM_REMOVE(FIRST_ELEMENT(anchor));
4441 CHECK(compile_massign_opt_lhs(
iseq, ret, lhsn->nd_next));
4442 CHECK(compile_massign_lhs(
iseq, ret, lhsn->nd_head));
4449 const NODE *rhsn,
const NODE *orig_lhsn)
4454 int llen = 0, rlen = 0;
4456 const NODE *lhsn = orig_lhsn;
4458 #define MEMORY(v) { \
4460 if (memindex == memsize) return 0; \
4461 for (i=0; i<memindex; i++) { \
4462 if (mem[i] == (v)) return 0; \
4464 mem[memindex++] = (v); \
4472 const NODE *ln = lhsn->nd_head;
4486 lhsn = lhsn->nd_next;
4497 rhsn = rhsn->nd_next;
4502 for (
i=0;
i<llen-rlen;
i++) {
4507 compile_massign_opt_lhs(
iseq, ret, orig_lhsn);
4515 do {
ADD_INSN(ret, line, putnil);}
while (++rlen < llen);
4517 else if (rlen > llen) {
4518 do {
ADD_INSN(ret, line, pop);}
while (--rlen > llen);
4525 const NODE *rhsn = node->nd_value;
4526 const NODE *splatn = node->nd_args;
4527 const NODE *lhsn = node->nd_head;
4530 if (!popped || splatn || !compile_massign_opt(
iseq, ret, rhsn, lhsn)) {
4538 CHECK(compile_massign_lhs(
iseq, lhsseq, lhsn->nd_head));
4540 lhsn = lhsn->nd_next;
4548 else if (!lhs_splat) {
4552 last->operand_size == 1) {
4557 adjust_stack(
iseq, ret,
nd_line(node), rlen, llen);
4561 else if (llen > 2 && llen != rlen) {
4563 adjust_stack(
iseq, ret,
nd_line(node), rlen, llen);
4567 else if (llen > 2) {
4582 const NODE *postn = splatn->nd_2nd;
4583 const NODE *restn = splatn->nd_1st;
4584 int num = (
int)postn->nd_alen;
4591 CHECK(compile_massign_lhs(
iseq, ret, restn));
4594 CHECK(compile_massign_lhs(
iseq, ret, postn->nd_head));
4595 postn = postn->nd_next;
4600 CHECK(compile_massign_lhs(
iseq, ret, splatn));
4613 debugi(
"compile_const_prefix - colon", node->nd_vid);
4618 debugi(
"compile_const_prefix - colon3", node->nd_mid);
4625 CHECK(compile_const_prefix(
iseq, node->nd_head, pref, body));
4626 debugi(
"compile_const_prefix - colon2", node->nd_mid);
4645 else if (cpath->nd_head) {
4659 private_recv_p(
const NODE *node)
4662 NODE *
self = node->nd_recv;
4663 return self->nd_state != 0;
4678 const int line =
nd_line(node);
4697 const NODE *vals = node;
4700 defined_expr0(
iseq, ret, vals->nd_head, lfinish,
Qfalse);
4705 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4706 }
while ((vals = vals->nd_next) !=
NULL);
4727 ID2SYM(node->nd_vid), needstr);
4733 ID2SYM(node->nd_entry->
id), needstr);
4739 ID2SYM(node->nd_vid), needstr);
4745 ID2SYM(node->nd_vid), needstr);
4751 defined_expr0(
iseq, ret, node->nd_head, lfinish,
Qfalse);
4752 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4758 ID2SYM(node->nd_mid), needstr);
4772 const int explicit_receiver =
4776 if (!lfinish[1] && (node->nd_args || explicit_receiver)) {
4779 if (node->nd_args) {
4780 defined_expr0(
iseq, ret, node->nd_args, lfinish,
Qfalse);
4781 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4783 if (explicit_receiver) {
4784 defined_expr0(
iseq, ret, node->nd_recv, lfinish,
Qfalse);
4785 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4788 ID2SYM(node->nd_mid), needstr);
4793 ID2SYM(node->nd_mid), needstr);
4850 iseq_set_exception_local_table(
iseq);
4858 defined_expr0(
iseq, ret, node, lfinish, needstr);
4865 rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq,
NULL);
4866 rescue = new_child_iseq_with_callback(
iseq, ifunc,
4869 iseq, ISEQ_TYPE_RESCUE, 0);
4881 const int line =
nd_line(node);
4882 if (!node->nd_head) {
4891 defined_expr(
iseq, ret, node->nd_head, lfinish, needstr);
4893 ELEM_INSERT_NEXT(
last, &new_insn_body(
iseq, line,
BIN(putnil), 0)->
link);
4904 make_name_for_block(
const rb_iseq_t *orig_iseq)
4932 enl->
prev = ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack;
4934 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = enl;
4944 while (erange->
next != 0) {
4945 erange = erange->
next;
4949 ne->end = erange->
end;
4950 erange->
end = lstart;
4959 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack;
4971 add_ensure_range(
iseq, enlp->
erange, lstart, lend);
4973 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = enlp->
prev;
4986 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = prev_enlp;
4991 check_keyword(
const NODE *node)
4996 while (node->nd_next) {
4997 node = node->nd_next;
4999 node = node->nd_head;
5002 return keyword_node_p(node);
5023 int rest_len = compile_args(
iseq, args, argn->nd_body,
NULL,
NULL);
5033 if (check_keyword(argn->nd_body))
5054 int len = compile_args(
iseq, args, argn, keywords, flag);
5076 ret = setup_args_core(
iseq, args, argn->nd_head, 0, flag, keywords);
5078 if (LIST_INSN_SIZE_ONE(arg_block)) {
5080 if (elem->
type == ISEQ_ELEMENT_INSN) {
5090 ret = setup_args_core(
iseq, args, argn, 0, flag, keywords);
5106 iseq_set_local_table(
iseq, 0);
5117 #if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0)
5123 ADD_INSNL(ret, line, branchunless, fail_label);
5127 if (
vars->nd_next) {
5136 #if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
5137 if (!
vars->nd_next &&
vars == node) {
5169 number_literal_p(
const NODE *
n)
5178 const NODE *
const node_body =
type ==
NODE_IF ? node->nd_body : node->nd_else;
5179 const NODE *
const node_else =
type ==
NODE_IF ? node->nd_else : node->nd_body;
5181 const int line =
nd_line(node);
5189 LABEL *then_label, *else_label, *end_label;
5202 compile_branch_condition(
iseq, cond_seq, node->nd_cond,
5203 then_label, else_label);
5209 if (!then_label->
refcnt) {
5222 if (!else_label->
refcnt) {
5237 if (then_label->
refcnt) {
5239 if (else_label->
refcnt) {
5249 ADD_INSNL(then_seq, line, jump, end_label);
5254 if (else_label->
refcnt) {
5256 if (then_label->
refcnt) {
5280 const NODE *node = orig_node;
5281 LABEL *endlabel, *elselabel;
5285 int only_special_literals = 1;
5287 int line, lineno, column, last_lineno, last_column;
5301 node = node->nd_body;
5329 CHECK(
COMPILE_(body_seq,
"when body", node->nd_body, popped));
5330 ADD_INSNL(body_seq, line, jump, endlabel);
5332 vals = node->nd_head;
5336 only_special_literals = when_vals(
iseq, cond_seq, vals, l1, only_special_literals, literals);
5337 if (only_special_literals < 0)
return COMPILE_NG;
5342 only_special_literals = 0;
5343 CHECK(when_splat_vals(
iseq, cond_seq, vals, l1, only_special_literals, literals));
5353 node = node->nd_next;
5370 ADD_INSNL(cond_seq, line, jump, endlabel);
5373 debugs(
"== else (implicit)\n");
5383 if (only_special_literals && ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction) {
5385 ADD_INSN2(ret,
nd_line(orig_node), opt_case_dispatch, literals, elselabel);
5401 const NODE *node = orig_node->nd_body;
5412 const int line =
nd_line(node);
5428 ADD_INSNL(body_seq, line, jump, endlabel);
5430 vals = node->nd_head;
5438 val = vals->nd_head;
5441 CHECK(compile_branch_condition(
iseq, ret, val, l1, lnext));
5443 vals = vals->nd_next;
5457 node = node->nd_next;
5479 const int line =
nd_line(node);
5542 const int min_argc = pre_args_num + post_args_num;
5546 LABEL *match_failed, *type_error, *fin;
5557 if (node->nd_pconst) {
5561 ADD_INSNL(ret, line, branchunless, match_failed);
5567 ADD_INSNL(ret, line, branchunless, match_failed);
5573 ADD_INSNL(ret, line, branchunless, type_error);
5579 ADD_INSNL(ret, line, branchunless, match_failed);
5581 for (
i = 0;
i < pre_args_num;
i++) {
5585 iseq_compile_pattern_each(
iseq, ret, args->nd_head, in_alt_pattern);
5586 args = args->nd_next;
5587 ADD_INSNL(ret, line, branchunless, match_failed);
5601 iseq_compile_pattern_each(
iseq, ret, apinfo->
rest_arg, in_alt_pattern);
5602 ADD_INSNL(ret, line, branchunless, match_failed);
5605 if (post_args_num > 0) {
5617 for (
i = 0;
i < post_args_num;
i++) {
5625 iseq_compile_pattern_each(
iseq, ret, args->nd_head, in_alt_pattern);
5626 args = args->nd_next;
5627 ADD_INSNL(ret, line, branchunless, match_failed);
5715 LABEL *match_failed, *type_error, *fin;
5722 if (node->nd_pkwargs && !node->nd_pkwrestarg) {
5723 const NODE *kw_args = node->nd_pkwargs->nd_head;
5727 kw_args = kw_args->nd_next->nd_next;
5731 if (node->nd_pconst) {
5735 ADD_INSNL(ret, line, branchunless, match_failed);
5741 ADD_INSNL(ret, line, branchunless, match_failed);
5754 ADD_INSNL(ret, line, branchunless, type_error);
5756 if (node->nd_pkwrestarg) {
5760 if (node->nd_pkwargs) {
5764 args = node->nd_pkwargs->nd_head;
5769 for (
i = 0;
i < keys_num;
i++) {
5770 NODE *key_node = args->nd_head;
5771 NODE *value_node = args->nd_next->nd_head;
5777 key = key_node->nd_lit;
5782 ADD_INSNL(ret, line, branchunless, match_failed);
5787 iseq_compile_pattern_each(
iseq, match_values, value_node, in_alt_pattern);
5788 ADD_INSNL(match_values, line, branchunless, match_failed);
5789 args = args->nd_next->nd_next;
5797 ADD_INSNL(ret, line, branchunless, match_failed);
5800 if (node->nd_pkwrestarg) {
5804 ADD_INSNL(ret, line, branchunless, match_failed);
5808 iseq_compile_pattern_each(
iseq, ret, node->nd_pkwrestarg, in_alt_pattern);
5809 ADD_INSNL(ret, line, branchunless, match_failed);
5855 ID id = node->nd_vid;
5858 if (in_alt_pattern) {
5874 ID id = node->nd_vid;
5876 idx = get_dyna_var_idx(
iseq,
id, &lv, &ls);
5878 if (in_alt_pattern) {
5898 LABEL *match_failed, *fin;
5901 iseq_compile_pattern_each(
iseq, ret, node->nd_body, in_alt_pattern);
5902 ADD_INSNL(ret, line, branchunless, match_failed);
5905 ADD_INSNL(ret, line, branchunless, match_failed);
5908 ADD_INSNL(ret, line, branchif, match_failed);
5921 LABEL *match_failed, *fin;
5932 iseq_compile_pattern_each(
iseq, ret,
n->nd_head, in_alt_pattern);
5933 ADD_INSNL(ret, line, branchunless, match_failed);
5934 iseq_compile_pattern_each(
iseq, ret,
n->nd_next->nd_head, in_alt_pattern);
5945 LABEL *match_succeeded, *fin;
5950 iseq_compile_pattern_each(
iseq, ret, node->nd_1st,
TRUE);
5951 ADD_INSNL(ret, line, branchif, match_succeeded);
5952 iseq_compile_pattern_each(
iseq, ret, node->nd_2nd,
TRUE);
5971 const NODE *pattern;
5972 const NODE *node = orig_node;
5973 LABEL *endlabel, *elselabel;
5977 int line, lineno, column, last_lineno, last_column;
5989 node = node->nd_body;
6017 CHECK(
COMPILE_(body_seq,
"in body", node->nd_body, popped));
6018 ADD_INSNL(body_seq, line, jump, endlabel);
6020 pattern = node->nd_head;
6023 iseq_compile_pattern_each(
iseq, cond_seq, pattern,
FALSE);
6031 node = node->nd_next;
6048 ADD_INSNL(cond_seq, line, jump, endlabel);
6051 debugs(
"== else (implicit)\n");
6080 LABEL *prev_start_label = ISEQ_COMPILE_DATA(
iseq)->start_label;
6081 LABEL *prev_end_label = ISEQ_COMPILE_DATA(
iseq)->end_label;
6082 LABEL *prev_redo_label = ISEQ_COMPILE_DATA(
iseq)->redo_label;
6083 int prev_loopval_popped = ISEQ_COMPILE_DATA(
iseq)->loopval_popped;
6097 ISEQ_COMPILE_DATA(
iseq)->loopval_popped = 0;
6100 if (node->nd_state == 1) {
6112 if (tmp_label)
ADD_LABEL(ret, tmp_label);
6128 compile_branch_condition(
iseq, ret, node->nd_cond,
6129 redo_label, end_label);
6133 compile_branch_condition(
iseq, ret, node->nd_cond,
6134 end_label, redo_label);
6140 if (node->nd_state ==
Qundef) {
6160 ISEQ_COMPILE_DATA(
iseq)->redo_label);
6162 ISEQ_COMPILE_DATA(
iseq)->start_label = prev_start_label;
6163 ISEQ_COMPILE_DATA(
iseq)->end_label = prev_end_label;
6164 ISEQ_COMPILE_DATA(
iseq)->redo_label = prev_redo_label;
6165 ISEQ_COMPILE_DATA(
iseq)->loopval_popped = prev_loopval_popped;
6166 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack->prev;
6173 const int line =
nd_line(node);
6174 const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(
iseq)->current_block;
6181 CHECK(
COMPILE(ret,
"iter caller (for)", node->nd_iter));
6183 ISEQ_COMPILE_DATA(
iseq)->current_block = child_iseq =
6185 ISEQ_TYPE_BLOCK, line);
6189 ISEQ_COMPILE_DATA(
iseq)->current_block = child_iseq =
6191 ISEQ_TYPE_BLOCK, line);
6200 ISEQ_COMPILE_DATA(
iseq)->current_block = prevblock;
6202 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l);
6212 const int line =
nd_line(node);
6213 const NODE *var = node->nd_var;
6221 ADD_INSNL(ret, line, branchunless, not_single);
6229 ADD_INSNL(ret, line, branchunless, not_ary);
6240 const int line =
nd_line(node);
6241 unsigned long throw_flag = 0;
6243 if (ISEQ_COMPILE_DATA(
iseq)->redo_label != 0) {
6248 CHECK(
COMPILE_(ret,
"break val (while/until)", node->nd_stts,
6249 ISEQ_COMPILE_DATA(
iseq)->loopval_popped));
6250 add_ensure_iseq(ret,
iseq, 0);
6251 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->end_label);
6261 CHECK(
COMPILE(ret,
"break val (block)", node->nd_stts));
6276 if (!ISEQ_COMPILE_DATA(ip)) {
6281 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6285 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6288 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6303 const int line =
nd_line(node);
6304 unsigned long throw_flag = 0;
6306 if (ISEQ_COMPILE_DATA(
iseq)->redo_label != 0) {
6308 debugs(
"next in while loop\n");
6310 CHECK(
COMPILE(ret,
"next val/valid syntax?", node->nd_stts));
6311 add_ensure_iseq(ret,
iseq, 0);
6313 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->start_label);
6319 else if (ISEQ_COMPILE_DATA(
iseq)->end_label) {
6321 debugs(
"next in block\n");
6325 add_ensure_iseq(ret,
iseq, 0);
6326 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->end_label);
6343 if (!ISEQ_COMPILE_DATA(ip)) {
6349 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6353 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6356 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6381 const int line =
nd_line(node);
6383 if (ISEQ_COMPILE_DATA(
iseq)->redo_label) {
6388 add_ensure_iseq(ret,
iseq, 0);
6389 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->redo_label);
6400 else if (ISEQ_COMPILE_DATA(
iseq)->start_label) {
6405 add_ensure_iseq(ret,
iseq, 0);
6407 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->start_label);
6418 if (!ISEQ_COMPILE_DATA(ip)) {
6423 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6426 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6429 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6454 const int line =
nd_line(node);
6474 const int line =
nd_line(node);
6480 ISEQ_TYPE_RESCUE, line);
6487 if (node->nd_else) {
6507 const int line =
nd_line(node);
6508 const NODE *resq = node;
6510 LABEL *label_miss, *label_hit;
6516 narg = resq->nd_args;
6524 ADD_INSNL(ret, line, branchif, label_hit);
6525 narg = narg->nd_next;
6534 ADD_INSNL(ret, line, branchif, label_hit);
6544 ADD_INSNL(ret, line, branchif, label_hit);
6549 if (ISEQ_COMPILE_DATA(
iseq)->option->tailcall_optimization) {
6554 resq = resq->nd_head;
6562 const int line =
nd_line(node);
6566 ISEQ_TYPE_ENSURE, line);
6584 push_ensure_entry(
iseq, &enl, &er, node->nd_ensr);
6587 CHECK(
COMPILE_(ret,
"ensure head", node->nd_head, (popped | last_leave)));
6590 if (!popped && last_leave)
ADD_INSN(ret, line, putnil);
6592 if (last_leave)
ADD_INSN(ret, line, pop);
6594 erange = ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack->erange;
6599 erange = erange->
next;
6603 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = enl.prev;
6610 const int line =
nd_line(node);
6615 enum iseq_type t =
type;
6616 const NODE *retval = node->nd_stts;
6619 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) {
6625 case ISEQ_TYPE_MAIN:
6627 rb_warn(
"argument of top-level return is ignored");
6631 type = ISEQ_TYPE_METHOD;
6638 if (
type == ISEQ_TYPE_METHOD) {
6644 CHECK(
COMPILE(ret,
"return nd_stts (return val)", retval));
6646 if (
type == ISEQ_TYPE_METHOD) {
6647 add_ensure_iseq(ret,
iseq, 1);
6671 if (!popped && !all_string_result_p(node)) {
6672 const int line =
nd_line(node);
6694 DECL_BRANCH_BASE(br, first_lineno, first_column, last_lineno, last_column,
"&.");
6697 ADD_INSNL(recv, line, branchnil, else_label);
6706 if (!else_label)
return;
6723 node->nd_args ==
NULL &&
6724 ISEQ_COMPILE_DATA(
iseq)->current_block ==
NULL &&
6725 ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction) {
6744 if (node->nd_mid ==
idAREF && !private_recv_p(node) && node->nd_args &&
6747 ISEQ_COMPILE_DATA(
iseq)->current_block ==
NULL &&
6748 !ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal &&
6749 ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction) {
6766 return ISEQ_COMPILE_DATA(
iseq)->builtin_function_table !=
NULL;
6774 for (
i=0; table[
i].
index != -1;
i++) {
6783 iseq_builtin_function_name(
ID mid)
6786 static const char prefix[] =
"__builtin_";
6787 const size_t prefix_len =
sizeof(prefix) - 1;
6790 return &
name[prefix_len];
6806 unsigned int start=0;
6815 for (
unsigned int i=start;
i-start<
argc;
i++) {
6816 if (elem->
type == ISEQ_ELEMENT_INSN &&
6821 if (local_level == 0) {
6824 fprintf(
stderr,
"lvar:%s (%d), id:%s (%d) local_index:%d, local_size:%d\n",
6851 *pstart_index = start;
6868 ID mid = node->nd_mid;
6870 unsigned int flag = 0;
6872 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(
iseq)->current_block;
6876 ISEQ_COMPILE_DATA(
iseq)->current_block =
NULL;
6880 #if OPT_SUPPORT_JOKE
6886 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
6888 if (mid == id_bitblt) {
6892 else if (mid == id_answer) {
6906 (mid == goto_id || mid == label_id)) {
6909 st_table *labels_table = ISEQ_COMPILE_DATA(
iseq)->labels_table;
6912 if (!labels_table) {
6914 ISEQ_COMPILE_DATA(
iseq)->labels_table = labels_table;
6917 SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
6919 label_name = node->nd_args->nd_head->nd_lit;
6926 label = (
LABEL *)data;
6934 if (mid == goto_id) {
6944 const char *builtin_func;
6945 NODE *args_node = node->nd_args;
6948 (builtin_func = iseq_builtin_function_name(mid)) !=
NULL) {
6950 if (parent_block !=
NULL) {
6955 char inline_func[0x20];
6956 bool cconst =
false;
6961 if (
strcmp(
"cstmt!", builtin_func) == 0 ||
6962 strcmp(
"cexpr!", builtin_func) == 0) {
6964 int inline_index =
GET_VM()->builtin_inline_index++;
6965 snprintf(inline_func, 0x20,
"_bi%d", inline_index);
6966 builtin_func = inline_func;
6970 else if (
strcmp(
"cconst!", builtin_func) == 0) {
6974 else if (
strcmp(
"cinit!", builtin_func) == 0) {
6976 GET_VM()->builtin_inline_index++;
6981 rb_bug(
"can't find builtin function:%s", builtin_func);
6990 typedef VALUE(*builtin_func0)(
void *,
VALUE);
6992 ADD_INSN1(ret, line, putobject, const_val);
6998 argc = setup_args(
iseq, args, args_node, &flag, &keywords);
7006 unsigned int start_index;
7008 ADD_INSN2(ret, line, opt_invokebuiltin_delegate, bf,
INT2FIX(start_index));
7015 if (popped)
ADD_INSN(ret, line, pop);
7027 iseq_block_param_id_p(
iseq, node->nd_recv->nd_vid, &idx, &level)) {
7030 else if (private_recv_p(node)) {
7039 else_label = qcall_branch_start(
iseq, recv, &branches, node, line);
7048 argc = setup_args(
iseq, args, node->nd_args, &flag, &keywords);
7061 switch ((
int)
type) {
7071 qcall_branch_end(
iseq, ret, else_label, branches, node, line);
7092 int lineno = ISEQ_COMPILE_DATA(
iseq)->last_line;
7094 debugs(
"node: NODE_NIL(implicit)\n");
7099 return iseq_compile_each0(
iseq, ret, node, popped);
7108 case ISEQ_TYPE_MAIN:
7110 case ISEQ_TYPE_CLASS:
7114 "`yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]");
7129 if (ISEQ_COMPILE_DATA(
iseq)->last_line == line) {
7135 ISEQ_COMPILE_DATA(
iseq)->last_line = line;
7144 #undef BEFORE_RETURN
7145 #define BEFORE_RETURN debug_node_end()
7151 (node->nd_next ? 1 : popped)));
7152 node = node->nd_next;
7164 CHECK(compile_case(
iseq, ret, node, popped));
7167 CHECK(compile_case2(
iseq, ret, node, popped));
7170 CHECK(compile_case3(
iseq, ret, node, popped));
7178 CHECK(compile_iter(
iseq, ret, node, popped));
7181 CHECK(compile_for_masgn(
iseq, ret, node, popped));
7184 CHECK(compile_break(
iseq, ret, node, popped));
7187 CHECK(compile_next(
iseq, ret, node, popped));
7190 CHECK(compile_redo(
iseq, ret, node, popped));
7193 CHECK(compile_retry(
iseq, ret, node, popped));
7200 CHECK(compile_rescue(
iseq, ret, node, popped));
7203 CHECK(compile_resbody(
iseq, ret, node, popped));
7206 CHECK(compile_ensure(
iseq, ret, node, popped));
7217 ADD_INSNL(ret, line, branchunless, end_label);
7220 ADD_INSNL(ret, line, branchif, end_label);
7231 compile_massign(
iseq, ret, node, popped);
7236 ID id = node->nd_vid;
7251 ID id = node->nd_vid;
7259 idx = get_dyna_var_idx(
iseq,
id, &lv, &ls);
7276 ((
VALUE)node->nd_entry | 1));
7284 ADD_INSN2(ret, line, setinstancevariable,
7286 get_ivar_ic_value(
iseq,node->nd_vid));
7302 compile_cpath(ret,
iseq, node->nd_else);
7318 unsigned int flag = 0;
7320 ID id = node->nd_mid;
7349 asgnflag =
COMPILE_RECV(ret,
"NODE_OP_ASGN1 recv", node);
7350 CHECK(asgnflag != -1);
7351 switch (
nd_type(node->nd_args->nd_head)) {
7359 argc = setup_args(
iseq, ret, node->nd_args->nd_head, &flag,
NULL);
7383 ADD_INSNL(ret, line, branchunless, label);
7387 CHECK(
COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
7421 CHECK(
COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
7452 ID atype = node->nd_next->nd_mid;
7500 asgnflag =
COMPILE_RECV(ret,
"NODE_OP_ASGN2#recv", node);
7501 CHECK(asgnflag != -1);
7502 if (node->nd_next->nd_aid) {
7516 ADD_INSNL(ret, line, branchunless, lcfin);
7519 CHECK(
COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
7539 CHECK(
COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
7546 if (lskip && popped) {
7550 if (lskip && !popped) {
7561 switch (
nd_type(node->nd_head)) {
7566 CHECK(
COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
7573 mid = node->nd_head->nd_mid;
7575 if (node->nd_aid ==
idOROP) {
7580 ADD_INSNL(ret, line, branchunless, lassign);
7589 if (node->nd_aid ==
idOROP)
7592 ADD_INSNL(ret, line, branchunless, lfin);
7594 if (!popped)
ADD_INSN(ret, line, pop);
7596 CHECK(
COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
7606 if (!popped)
ADD_INSN(ret, line, swap);
7610 CHECK(
COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
7632 defined_expr(
iseq, ret, node->nd_head, lfinish,
Qfalse);
7633 lassign = lfinish[1];
7637 ADD_INSNL(ret, line, branchunless, lassign);
7643 CHECK(
COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
7647 ADD_INSNL(ret, line, branchunless, lfin);
7655 CHECK(
COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_value", node->nd_value));
7666 if (compile_call_precheck_freeze(
iseq, ret, node, line, popped) ==
TRUE) {
7680 unsigned int flag = 0;
7682 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(
iseq)->current_block;
7685 ISEQ_COMPILE_DATA(
iseq)->current_block =
NULL;
7696 const struct rb_iseq_param_keyword *
const local_kwd = local_body->
param.
keyword;
7697 int lvar_level = get_lvar_level(
iseq);
7734 for (j=0; j<post_len; j++) {
7739 ADD_INSN (args, line, concatarray);
7744 for (j=0; j<post_len; j++) {
7748 argc = post_len + post_start;
7766 for (
i = 0;
i < local_kwd->num; ++
i) {
7767 ID id = local_kwd->table[
i];
7768 int idx =
local_size - get_local_var_idx(liseq,
id);
7775 ADD_INSN (args, line, concatarray);
7780 else if (local_body->
param.
flags.has_kwrest) {
7787 ADD_INSN (args, line, concatarray);
7808 CHECK(compile_array(
iseq, ret, node, popped) >= 0);
7818 const NODE *
n = node;
7830 CHECK(compile_hash(
iseq, ret, node, popped) >= 0);
7833 CHECK(compile_return(
iseq, ret, node, popped));
7838 unsigned int flag = 0;
7843 if (check_yield_place(
iseq, line) ==
FALSE) {
7848 if (node->nd_head) {
7866 ID id = node->nd_vid;
7876 debugi(
"nd_vid", node->nd_vid);
7878 idx = get_dyna_var_idx(
iseq, node->nd_vid, &lv, &ls);
7890 ((
VALUE)node->nd_entry | 1));
7897 debugi(
"nd_vid", node->nd_vid);
7899 ADD_INSN2(ret, line, getinstancevariable,
7901 get_ivar_ic_value(
iseq,node->nd_vid));
7906 debugi(
"nd_vid", node->nd_vid);
7908 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
7910 int ic_index = body->
is_size++;
7938 if (!node->nd_nth) {
7950 INT2FIX(0x01 | (node->nd_nth << 1)));
7964 ADD_INSN1(recv, line, putobject, node->nd_lit);
7982 if (node->nd_args) {
7983 compile_named_capture_assign(
iseq, ret, node->nd_args);
7994 ADD_INSN1(ret, line, putobject, node->nd_lit);
8001 VALUE lit = node->nd_lit;
8002 if (!ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal) {
8024 compile_dstr(
iseq, ret, node);
8030 if (ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal) {
8035 ADD_INSN1(ret, line, freezestring, debug_info);
8036 if (!
NIL_P(debug_info)) {
8057 compile_dstr(
iseq, ret, node);
8066 CHECK(compile_evstr(
iseq, ret, node->nd_body, popped));
8069 compile_dregx(
iseq, ret, node);
8077 int ic_index = body->
is_size++;
8079 block_iseq =
NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(
iseq), ISEQ_TYPE_PLAIN, line);
8110 CHECK(
COMPILE_(ret,
"argspush body", node->nd_body, popped));
8114 CHECK(
COMPILE_(ret,
"argspush body", node->nd_body, popped));
8130 ID mid = node->nd_mid;
8133 ISEQ_TYPE_METHOD, line);
8146 ID mid = node->nd_mid;
8149 ISEQ_TYPE_METHOD, line);
8153 ADD_INSN2(ret, line, definesmethod,
ID2SYM(mid), singleton_method_iseq);
8198 ISEQ_TYPE_CLASS, line);
8201 compile_cpath(ret,
iseq, node->nd_cpath);
8215 ISEQ_TYPE_CLASS, line);
8217 compile_cpath(ret,
iseq, node->nd_cpath);
8231 ISEQ_TYPE_CLASS, line);
8235 CONST_ID(singletonclass,
"singletonclass");
8237 ID2SYM(singletonclass), singleton_class,
8250 int ic_index = body->
is_size++;
8257 CHECK(compile_const_prefix(
iseq, node, pref, body));
8258 if (LIST_INSN_SIZE_ZERO(pref)) {
8259 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
8268 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
8291 int ic_index = body->
is_size++;
8293 debugi(
"colon3#nd_mid", node->nd_mid);
8296 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
8305 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
8319 const NODE *b = node->nd_beg;
8320 const NODE *e = node->nd_end;
8321 if (number_literal_p(b) && number_literal_p(e)) {
8378 if (body->
type == ISEQ_TYPE_RESCUE) {
8385 if (ip->
body->
type == ISEQ_TYPE_RESCUE) {
8410 int is_index = body->
is_size++;
8412 rb_iseq_new_with_callback_new_callback(build_postexe_iseq, node->nd_body);
8414 new_child_iseq_with_callback(
iseq, ifunc,
8428 const NODE *default_value = node->nd_body->nd_value;
8451 ADD_INSNL(ret, line, branchif, end_label);
8459 compile_dstr(
iseq, ret, node);
8471 unsigned int flag = 0;
8472 ID mid = node->nd_mid;
8480 if (mid ==
idASET && !private_recv_p(node) && node->nd_args &&
8483 ISEQ_COMPILE_DATA(
iseq)->current_block ==
NULL &&
8484 !ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal &&
8485 ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction)
8489 CHECK(
COMPILE(ret,
"value", node->nd_args->nd_next->nd_head));
8503 argc = setup_args(
iseq, args, node->nd_args, &flag,
NULL);
8507 CHECK(asgnflag != -1);
8508 flag |= (
unsigned int)asgnflag;
8516 else_label = qcall_branch_start(
iseq, recv, &branches, node, line);
8548 qcall_branch_end(
iseq, ret, else_label, branches, node, line);
8583 insn_data_length(
INSN *iobj)
8585 return insn_len(iobj->
insn_id);
8589 calc_sp_depth(
int depth,
INSN *insn)
8591 return comptime_insn_stack_increase(depth, insn->
insn_id, insn->
operands);
8597 struct RBasic *r = (
struct RBasic *)
obj;
8614 insn_data_to_s_detail(
INSN *iobj)
8622 for (j = 0;
types[j]; j++) {
8682 if (dladdr(func, &info) && info.dli_sname) {
8691 rb_bug(
"unsupported: TS_BUILTIN");
8719 printf(
"-- raw disasm--------\n");
8723 switch (
link->type) {
8724 case ISEQ_ELEMENT_INSN:
8727 str = insn_data_to_s_detail(iobj);
8729 pos += insn_data_length(iobj);
8732 case ISEQ_ELEMENT_LABEL:
8736 dest == lobj ?
" <---" :
"");
8739 case ISEQ_ELEMENT_TRACE:
8745 case ISEQ_ELEMENT_ADJUST:
8757 printf(
"---------------------\n");
8764 return insn_name(
i);
8790 label = (
LABEL *)tmp;
8800 #define rb_intern(str) rb_intern_const(str)
8801 static VALUE symRescue, symEnsure, symRetry;
8802 static VALUE symBreak, symRedo, symNext;
8804 if (symRescue == 0) {
8813 if (
sym == symRescue)
return CATCH_TYPE_RESCUE;
8814 if (
sym == symEnsure)
return CATCH_TYPE_ENSURE;
8815 if (
sym == symRetry)
return CATCH_TYPE_RETRY;
8816 if (
sym == symBreak)
return CATCH_TYPE_BREAK;
8817 if (
sym == symRedo)
return CATCH_TYPE_REDO;
8818 if (
sym == symNext)
return CATCH_TYPE_NEXT;
8832 LABEL *lstart, *lend, *lcont;
8853 if (
type == CATCH_TYPE_RESCUE ||
8854 type == CATCH_TYPE_BREAK ||
8855 type == CATCH_TYPE_NEXT) {
8869 insn_make_insn_table(
void)
8907 unsigned int flag = 0;
8918 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
8920 if (!
NIL_P(vkw_arg)) {
8923 size_t n = rb_call_info_kw_arg_bytes(
len);
8927 for (
i = 0;
i <
len;
i++) {
8941 #define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern(#ev))) return ev;
8967 static struct st_table *insn_table;
8969 if (insn_table == 0) {
8970 insn_table = insn_make_insn_table();
8982 LABEL *label = register_label(
iseq, labels_table,
obj);
8999 "unknown instruction: %+"PRIsVALUE, insn);
9004 if (
argc != insn_len((
VALUE)insn_id)-1) {
9006 "operand size mismatch");
9013 for (j=0; j<
argc; j++) {
9015 switch (insn_op_type((
VALUE)insn_id, j)) {
9017 LABEL *label = register_label(
iseq, labels_table, op);
9057 argv[j] = iseq_build_callinfo_from_hash(
iseq, op);
9073 register_label(
iseq, labels_table,
sym);
9083 #if SIZEOF_VALUE <= SIZEOF_LONG
9105 validate_labels(
iseq, labels_table);
9106 if (!ret)
return ret;
9107 return iseq_setup(
iseq, anchor);
9110 #define CHECK_ARRAY(v) rb_to_array_type(v)
9111 #define CHECK_SYMBOL(v) rb_to_symbol_type(v)
9121 else if (!
NIL_P(val)) {
9128 static const struct rb_iseq_param_keyword *
9137 struct rb_iseq_param_keyword *keyword =
ZALLOC(
struct rb_iseq_param_keyword);
9142 #define SYM(s) ID2SYM(rb_intern(#s))
9143 (
void)int_param(&keyword->bits_start, params,
SYM(kwbits));
9144 i = keyword->bits_start - keyword->num;
9149 for (
i = 0;
i <
len;
i++) {
9153 goto default_values;
9156 keyword->required_num++;
9160 default_len =
len -
i;
9161 if (default_len == 0) {
9162 keyword->table = ids;
9165 else if (default_len < 0) {
9171 for (j = 0;
i <
len;
i++, j++) {
9188 dvs[j] = default_val;
9191 keyword->table = ids;
9192 keyword->default_values = dvs;
9202 unsigned int pos = 0;
9205 #ifdef STRICT_ALIGNMENT
9206 size_t padding = calc_padding((
void *)&storage->
buff[pos],
size);
9208 const size_t padding = 0;
9210 size_t offset = pos +
size + padding;
9211 if (offset > storage->
size || offset > storage->
pos) {
9213 storage = storage->
next;
9216 #ifdef STRICT_ALIGNMENT
9217 pos += (
int)padding;
9220 iobj = (
INSN *)&storage->
buff[pos];
9226 for (j = 0;
types[j]; j++) {
9253 #define SYM(s) ID2SYM(rb_intern(#s))
9255 unsigned int arg_size,
local_size, stack_max;
9269 for (
i = 0;
i <
len;
i++) {
9272 if (sym_arg_rest == lv) {
9280 #define INT_PARAM(F) int_param(&iseq->body->param.F, params, SYM(F))
9290 #define INT_PARAM(F) F = (int_param(&x, misc, SYM(F)) ? (unsigned int)x : 0)
9305 for (
i = 0;
i <
len;
i++) {
9307 LABEL *label = register_label(
iseq, labels_table, ent);
9308 opt_table[
i] = (
VALUE)label;
9315 else if (!
NIL_P(arg_opt_labels)) {
9323 else if (!
NIL_P(keywords)) {
9332 if (int_param(&
i, params,
SYM(kwrest))) {
9333 struct rb_iseq_param_keyword *keyword = (
struct rb_iseq_param_keyword *)
iseq->
body->
param.
keyword;
9337 keyword->rest_start =
i;
9341 iseq_calc_param_size(
iseq);
9344 iseq_build_from_ary_exception(
iseq, labels_table, exception);
9347 iseq_build_from_ary_body(
iseq, anchor, body, labels_wrapper);
9434 rb_iseq_new_with_callback_new_callback(build, &acc);
9444 const int line = args->
line;
9447 iseq_set_local_table(
iseq, 0);
9459 const int line = args->
line;
9479 return method_for_self(
name,
arg, func, for_self_aref);
9488 return method_for_self(
name,
arg, func, for_self_aset);
9493 #ifndef IBF_ISEQ_DEBUG
9494 #define IBF_ISEQ_DEBUG 0
9497 #ifndef IBF_ISEQ_ENABLE_LOCAL_BUFFER
9498 #define IBF_ISEQ_ENABLE_LOCAL_BUFFER 0
9502 #define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
9504 #define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
9506 #define IBF_DEVEL_VERSION 2
9507 #define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
9509 #define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
9559 ibf_dump_pos(
struct ibf_dump *dump)
9562 #if SIZEOF_LONG > SIZEOF_INT
9567 return (
unsigned int)pos;
9571 ibf_dump_align(
struct ibf_dump *dump,
size_t align)
9575 static const char padding[
sizeof(
VALUE)];
9577 #if SIZEOF_LONG > SIZEOF_INT
9582 for (;
size >
sizeof(padding);
size -=
sizeof(padding)) {
9590 ibf_dump_write(
struct ibf_dump *dump,
const void *
buff,
unsigned long size)
9599 ibf_dump_write_byte(
struct ibf_dump *dump,
unsigned char byte)
9601 return ibf_dump_write(dump, &
byte,
sizeof(
unsigned char));
9605 ibf_dump_overwrite(
struct ibf_dump *dump,
void *
buff,
unsigned int size,
long offset)
9610 rb_bug(
"ibf_dump_overwrite: overflow");
9626 size_t size = x * y;
9631 #define IBF_W_ALIGN(type) (RUBY_ALIGNOF(type) > 1 ? ibf_dump_align(dump, RUBY_ALIGNOF(type)) : (void)0)
9633 #define IBF_W(b, type, n) (IBF_W_ALIGN(type), (type *)(VALUE)IBF_WP(b, type, n))
9634 #define IBF_WV(variable) ibf_dump_write(dump, &(variable), sizeof(variable))
9635 #define IBF_WP(b, type, n) ibf_dump_write(dump, (b), sizeof(type) * (n))
9636 #define IBF_R(val, type, n) (type *)ibf_load_alloc(load, IBF_OFFSET(val), sizeof(type), (n))
9637 #define IBF_ZERO(variable) memset(&(variable), 0, sizeof(variable))
9655 int index = ibf_table_lookup(table,
key);
9673 ibf_dump_object_list_new(
void)
9700 return ibf_dump_object(dump,
rb_id2sym(
id));
9704 ibf_load_id(
const struct ibf_load *load,
const ID id_index)
9706 if (id_index == 0) {
9709 VALUE sym = ibf_load_object(load, id_index);
9731 if (iseq_index < 0) {
9742 return (
VALUE)ibf_dump_id(dump, entry->
id);
9748 ID gid = ibf_load_id(load, (
ID)(
VALUE)entry);
9752 static unsigned char
9773 ibf_dump_write(dump, &x,
sizeof(
VALUE));
9776 enum { max_byte_length =
sizeof(
VALUE) + 1 };
9778 unsigned char bytes[max_byte_length];
9781 for (
n = 0;
n <
sizeof(
VALUE) && (x >> (7 -
n));
n++, x >>= 8) {
9782 bytes[max_byte_length - 1 -
n] = (
unsigned char)x;
9788 bytes[max_byte_length - 1 -
n] = (
unsigned char)x;
9791 ibf_dump_write(dump, bytes + max_byte_length -
n,
n);
9801 *offset +=
sizeof(
VALUE);
9806 enum { max_byte_length =
sizeof(
VALUE) + 1 };
9809 const unsigned char c = buffer[*offset];
9813 c == 0 ? 9 : ntz_int32(c) + 1;
9821 for (
i = 1;
i <
n;
i++) {
9823 x |= (
VALUE)buffer[*offset +
i];
9837 ibf_dump_write_small_value(dump, (
VALUE)bf->
index);
9840 ibf_dump_write_small_value(dump, (
VALUE)
len);
9841 ibf_dump_write(dump, bf->
name,
len);
9847 int i = (
int)ibf_load_small_value(load, offset);
9848 int len = (
int)ibf_load_small_value(load, offset);
9849 const char *
name = (
char *)ibf_load_ptr(load, offset,
len);
9876 for (code_index=0; code_index<
iseq_size;) {
9877 const VALUE insn = orig_code[code_index++];
9878 const char *
types = insn_op_types(insn);
9883 ibf_dump_write_small_value(dump, insn);
9886 for (op_index=0;
types[op_index]; op_index++, code_index++) {
9887 VALUE op = orig_code[code_index];
9890 switch (
types[op_index]) {
9893 wv = ibf_dump_object(dump, op);
9915 ibf_dump_write_byte(dump, c);
9919 wv = ibf_dump_id(dump, (
ID)op);
9934 ibf_dump_write_small_value(dump, wv);
9937 assert(insn_len(insn) == op_index+1);
9946 unsigned int code_index;
9955 for (code_index=0; code_index<iseq_size;) {
9957 const VALUE insn = code[code_index++] = ibf_load_small_value(load, &reading_pos);
9958 const char *
types = insn_op_types(insn);
9962 for (op_index=0;
types[op_index]; op_index++, code_index++) {
9963 switch (
types[op_index]) {
9967 VALUE op = ibf_load_small_value(load, &reading_pos);
9968 VALUE v = ibf_load_object(load, op);
9969 code[code_index] =
v;
9978 VALUE op = (
VALUE)ibf_load_small_value(load, &reading_pos);
9980 code[code_index] =
v;
9993 VALUE op = ibf_load_small_value(load, &reading_pos);
9994 code[code_index] = (
VALUE)&is_entries[op];
9999 unsigned char op = ibf_load_byte(load, &reading_pos);
10000 code[code_index] = op ? (
VALUE)cd_kw_entries++ : (
VALUE)cd_entries++;
10005 VALUE op = ibf_load_small_value(load, &reading_pos);
10006 code[code_index] = ibf_load_id(load, (
ID)(
VALUE)op);
10011 VALUE op = ibf_load_small_value(load, &reading_pos);
10019 code[code_index] = (
VALUE)ibf_load_builtin(load, &reading_pos);
10022 code[code_index] = ibf_load_small_value(load, &reading_pos);
10026 if (insn_len(insn) != op_index+1) {
10033 assert(code_index == iseq_size);
10034 assert(reading_pos == bytecode_offset + bytecode_size);
10048 return ibf_dump_pos(dump);
10053 ibf_load_param_opt_table(
const struct ibf_load *load,
ibf_offset_t opt_table_offset,
int opt_num)
10071 struct rb_iseq_param_keyword dump_kw = *kw;
10072 int dv_num = kw->num - kw->required_num;
10077 for (
i=0;
i<kw->num;
i++) ids[
i] = (
ID)ibf_dump_id(dump, kw->table[
i]);
10078 for (
i=0;
i<dv_num;
i++) dvs[
i] = (
VALUE)ibf_dump_object(dump, kw->default_values[
i]);
10080 dump_kw.table =
IBF_W(ids,
ID, kw->num);
10081 dump_kw.default_values =
IBF_W(dvs,
VALUE, dv_num);
10083 return ibf_dump_write(dump, &dump_kw,
sizeof(
struct rb_iseq_param_keyword) * 1);
10090 static const struct rb_iseq_param_keyword *
10093 if (param_keyword_offset) {
10094 struct rb_iseq_param_keyword *kw =
IBF_R(param_keyword_offset,
struct rb_iseq_param_keyword, 1);
10095 ID *ids =
IBF_R(kw->table,
ID, kw->num);
10096 int dv_num = kw->num - kw->required_num;
10100 for (
i=0;
i<kw->num;
i++) {
10101 ids[
i] = ibf_load_id(load, ids[
i]);
10103 for (
i=0;
i<dv_num;
i++) {
10104 dvs[
i] = ibf_load_object(load, dvs[
i]);
10108 kw->default_values = dvs;
10139 entries[
i].line_no = (
int)ibf_load_small_value(load, &reading_pos);
10147 ibf_dump_insns_info_positions(
struct ibf_dump *dump,
const unsigned int *positions,
unsigned int size)
10151 unsigned int last = 0;
10154 ibf_dump_write_small_value(dump, positions[
i] -
last);
10155 last = positions[
i];
10161 static unsigned int *
10165 unsigned int *positions =
ALLOC_N(
unsigned int,
size);
10167 unsigned int last = 0;
10170 positions[
i] =
last + (
unsigned int)ibf_load_small_value(load, &reading_pos);
10171 last = positions[
i];
10190 return ibf_dump_write(dump,
table,
sizeof(
ID) *
size);
10219 for (
i=0;
i<table->
size;
i++) {
10220 iseq_indices[
i] = ibf_dump_iseq(dump, table->
entries[
i].
iseq);
10225 for (
i=0;
i<table->
size;
i++) {
10226 ibf_dump_write_small_value(dump, iseq_indices[
i]);
10227 ibf_dump_write_small_value(dump, table->
entries[
i].
type);
10229 ibf_dump_write_small_value(dump, table->
entries[
i].
end);
10230 ibf_dump_write_small_value(dump, table->
entries[
i].
cont);
10231 ibf_dump_write_small_value(dump, table->
entries[
i].
sp);
10236 return ibf_dump_pos(dump);
10250 for (
i=0;
i<table->
size;
i++) {
10251 int iseq_index = (
int)ibf_load_small_value(load, &reading_pos);
10252 table->
entries[
i].
type = (
enum catch_type)ibf_load_small_value(load, &reading_pos);
10253 table->
entries[
i].
start = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10254 table->
entries[
i].
end = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10255 table->
entries[
i].
cont = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10256 table->
entries[
i].
sp = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10280 for (
i = 0;
i < ci_size;
i++) {
10281 VALUE mid = ibf_dump_id(dump, calls[
i].
ci.mid);
10283 ibf_dump_write_small_value(dump, mid);
10284 ibf_dump_write_small_value(dump, calls[
i].
ci.flag);
10285 ibf_dump_write_small_value(dump, calls[
i].
ci.orig_argc);
10288 for (
i = 0;
i < ci_kw_size;
i++) {
10291 VALUE mid = ibf_dump_id(dump, kw_calls[
i].ci_kw.ci.mid);
10293 ibf_dump_write_small_value(dump, mid);
10294 ibf_dump_write_small_value(dump, kw_calls[
i].ci_kw.ci.flag);
10295 ibf_dump_write_small_value(dump, kw_calls[
i].ci_kw.ci.orig_argc);
10297 ibf_dump_write_small_value(dump, kw_arg->
keyword_len);
10301 VALUE keyword = ibf_dump_object(dump, kw_arg->
keywords[j]);
10303 ibf_dump_write_small_value(dump, keyword);
10312 ibf_load_ci_entries(
const struct ibf_load *load,
10314 unsigned int ci_size,
10315 unsigned int ci_kw_size)
10327 for (
i = 0;
i < ci_size;
i++) {
10328 VALUE mid_index = ibf_load_small_value(load, &reading_pos);
10330 calls[
i].
ci.
mid = ibf_load_id(load, mid_index);
10331 calls[
i].
ci.
flag = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10332 calls[
i].
ci.
orig_argc = (
int)ibf_load_small_value(load, &reading_pos);
10335 for (
i = 0;
i < ci_kw_size;
i++) {
10336 VALUE mid_index = ibf_load_small_value(load, &reading_pos);
10338 kw_calls[
i].
ci_kw.
ci.
mid = ibf_load_id(load, mid_index);
10339 kw_calls[
i].
ci_kw.
ci.
flag = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10342 int keyword_len = (
int)ibf_load_small_value(load, &reading_pos);
10351 VALUE keyword = ibf_load_small_value(load, &reading_pos);
10365 unsigned int *positions;
10373 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10379 buffer.obj_list = ibf_dump_object_list_new();
10384 const ibf_offset_t bytecode_size = ibf_dump_pos(dump) - bytecode_offset;
10385 const ibf_offset_t param_opt_table_offset = ibf_dump_param_opt_table(dump,
iseq);
10386 const ibf_offset_t param_keyword_offset = ibf_dump_param_keyword(dump,
iseq);
10387 const ibf_offset_t insns_info_body_offset = ibf_dump_insns_info_body(dump,
iseq);
10400 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10402 unsigned int local_obj_list_size;
10404 ibf_dump_object_list(dump, &local_obj_list_offset, &local_obj_list_size);
10410 unsigned int param_flags =
10422 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10423 # define IBF_BODY_OFFSET(x) (x)
10425 # define IBF_BODY_OFFSET(x) (body_offset - (x))
10428 ibf_dump_write_small_value(dump, body->
type);
10429 ibf_dump_write_small_value(dump, body->
iseq_size);
10431 ibf_dump_write_small_value(dump, bytecode_size);
10432 ibf_dump_write_small_value(dump, param_flags);
10433 ibf_dump_write_small_value(dump, body->
param.
size);
10435 ibf_dump_write_small_value(dump, body->
param.
opt_num);
10440 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(param_opt_table_offset));
10441 ibf_dump_write_small_value(dump, param_keyword_offset);
10442 ibf_dump_write_small_value(dump, location_pathobj_index);
10443 ibf_dump_write_small_value(dump, location_base_label_index);
10444 ibf_dump_write_small_value(dump, location_label_index);
10451 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(insns_info_body_offset));
10452 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(insns_info_positions_offset));
10454 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(local_table_offset));
10455 ibf_dump_write_small_value(dump, catch_table_size);
10456 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(catch_table_offset));
10457 ibf_dump_write_small_value(dump, parent_iseq_index);
10458 ibf_dump_write_small_value(dump, local_iseq_index);
10459 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(ci_entries_offset));
10462 ibf_dump_write_small_value(dump, body->
is_size);
10463 ibf_dump_write_small_value(dump, body->
ci_size);
10464 ibf_dump_write_small_value(dump, body->
ci_kw_size);
10465 ibf_dump_write_small_value(dump, body->
stack_max);
10468 #undef IBF_BODY_OFFSET
10470 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10474 ibf_dump_write(dump,
RSTRING_PTR(buffer.str), iseq_length_bytes);
10477 ibf_dump_write_small_value(dump, iseq_start);
10478 ibf_dump_write_small_value(dump, iseq_length_bytes);
10479 ibf_dump_write_small_value(dump, body_offset);
10481 ibf_dump_write_small_value(dump, local_obj_list_offset);
10482 ibf_dump_write_small_value(dump, local_obj_list_size);
10486 return body_offset;
10491 ibf_load_location_str(
const struct ibf_load *load,
VALUE str_index)
10493 VALUE str = ibf_load_object(load, str_index);
10507 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10511 const ibf_offset_t iseq_start = ibf_load_small_value(load, &reading_pos);
10512 const ibf_offset_t iseq_length_bytes = ibf_load_small_value(load, &reading_pos);
10513 const ibf_offset_t body_offset = ibf_load_small_value(load, &reading_pos);
10517 buffer.size = iseq_length_bytes;
10518 buffer.obj_list_offset = ibf_load_small_value(load, &reading_pos);
10519 buffer.obj_list_size = ibf_load_small_value(load, &reading_pos);
10524 reading_pos = body_offset;
10527 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10528 # define IBF_BODY_OFFSET(x) (x)
10530 # define IBF_BODY_OFFSET(x) (offset - (x))
10533 const unsigned int type = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10534 const unsigned int iseq_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10537 const unsigned int param_flags = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10538 const unsigned int param_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10539 const int param_lead_num = (
int)ibf_load_small_value(load, &reading_pos);
10540 const int param_opt_num = (
int)ibf_load_small_value(load, &reading_pos);
10541 const int param_rest_start = (
int)ibf_load_small_value(load, &reading_pos);
10542 const int param_post_start = (
int)ibf_load_small_value(load, &reading_pos);
10543 const int param_post_num = (
int)ibf_load_small_value(load, &reading_pos);
10544 const int param_block_start = (
int)ibf_load_small_value(load, &reading_pos);
10547 const VALUE location_pathobj_index = ibf_load_small_value(load, &reading_pos);
10548 const VALUE location_base_label_index = ibf_load_small_value(load, &reading_pos);
10549 const VALUE location_label_index = ibf_load_small_value(load, &reading_pos);
10550 const VALUE location_first_lineno = ibf_load_small_value(load, &reading_pos);
10551 const int location_node_id = (
int)ibf_load_small_value(load, &reading_pos);
10552 const int location_code_location_beg_pos_lineno = (
int)ibf_load_small_value(load, &reading_pos);
10553 const int location_code_location_beg_pos_column = (
int)ibf_load_small_value(load, &reading_pos);
10554 const int location_code_location_end_pos_lineno = (
int)ibf_load_small_value(load, &reading_pos);
10555 const int location_code_location_end_pos_column = (
int)ibf_load_small_value(load, &reading_pos);
10558 const unsigned int insns_info_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10560 const unsigned int catch_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10562 const int parent_iseq_index = (
int)ibf_load_small_value(load, &reading_pos);
10563 const int local_iseq_index = (
int)ibf_load_small_value(load, &reading_pos);
10565 const rb_snum_t variable_flip_count = (
rb_snum_t)ibf_load_small_value(load, &reading_pos);
10566 const unsigned int local_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10567 const unsigned int is_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10568 const unsigned int ci_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10569 const unsigned int ci_kw_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10570 const unsigned int stack_max = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10571 const char catch_except_p = (
char)ibf_load_small_value(load, &reading_pos);
10573 #undef IBF_BODY_OFFSET
10577 load_body->
param.
flags.has_lead = (param_flags >> 0) & 1;
10578 load_body->
param.
flags.has_opt = (param_flags >> 1) & 1;
10579 load_body->
param.
flags.has_rest = (param_flags >> 2) & 1;
10580 load_body->
param.
flags.has_post = (param_flags >> 3) & 1;
10582 load_body->
param.
flags.has_kwrest = (param_flags >> 5) & 1;
10583 load_body->
param.
flags.has_block = (param_flags >> 6) & 1;
10584 load_body->
param.
flags.ambiguous_param0 = (param_flags >> 7) & 1;
10585 load_body->
param.
flags.accepts_no_kwarg = (param_flags >> 8) & 1;
10586 load_body->
param.
flags.ruby2_keywords = (param_flags >> 9) & 1;
10595 load_body->
is_size = is_size;
10596 load_body->
ci_size = ci_size;
10601 ISEQ_ORIGINAL_ISEQ_CLEAR(
iseq);
10613 load_body->
call_data = ibf_load_ci_entries(load, ci_entries_offset, ci_size, ci_kw_size);
10614 load_body->
param.
opt_table = ibf_load_param_opt_table(load, param_opt_table_offset, param_opt_num);
10615 load_body->
param.
keyword = ibf_load_param_keyword(load, param_keyword_offset);
10616 load_body->
param.
flags.has_kw = (param_flags >> 4) & 1;
10617 load_body->
insns_info.
body = ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size);
10618 load_body->
insns_info.
positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size);
10619 load_body->
local_table = ibf_load_local_table(load, local_table_offset, local_table_size);
10620 load_body->
catch_table = ibf_load_catch_table(load, catch_table_offset, catch_table_size);
10624 ibf_load_code(load,
iseq, bytecode_offset, bytecode_size, iseq_size);
10625 #if VM_INSN_INFO_TABLE_IMPL == 2
10629 rb_iseq_translate_threaded_code(
iseq);
10631 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10665 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10668 verify_call_cache(
iseq);
10694 #define IBF_OBJECT_INTERNAL FL_PROMOTED0
10706 unsigned int internal: 1;
10752 #define IBF_ALIGNED_OFFSET(align, offset) \
10753 ((((offset) - 1) / (align) + 1) * (align))
10754 #define IBF_OBJBODY(type, offset) (const type *)\
10755 ibf_load_check_offset(load, IBF_ALIGNED_OFFSET(RUBY_ALIGNOF(type), offset))
10757 static const void *
10758 ibf_load_check_offset(
const struct ibf_load *load,
size_t offset)
10805 rb_bug(
"unsupported class");
10807 ibf_dump_write_small_value(dump, (
VALUE)cindex);
10842 const double *dblp =
IBF_OBJBODY(
double, offset);
10859 ibf_dump_write_small_value(dump, encindex);
10860 ibf_dump_write_small_value(dump,
len);
10869 int encindex = (
int)ibf_load_small_value(load, &reading_pos);
10870 const long len = (
long)ibf_load_small_value(load, &reading_pos);
10893 regexp.srcstr = (
long)ibf_dump_object(dump,
srcstr);
10895 ibf_dump_write_byte(dump, (
unsigned char)regexp.option);
10896 ibf_dump_write_small_value(dump, regexp.srcstr);
10903 regexp.
option = ibf_load_byte(load, &offset);
10904 regexp.srcstr = ibf_load_small_value(load, &offset);
10906 VALUE srcstr = ibf_load_object(load, regexp.srcstr);
10919 ibf_dump_write_small_value(dump,
len);
10922 ibf_dump_write_small_value(dump,
index);
10931 const long len = (
long)ibf_load_small_value(load, &reading_pos);
10937 const VALUE index = ibf_load_small_value(load, &reading_pos);
10953 VALUE val_index = ibf_dump_object(dump, (
VALUE)val);
10955 ibf_dump_write_small_value(dump, key_index);
10956 ibf_dump_write_small_value(dump, val_index);
10964 ibf_dump_write_small_value(dump, (
VALUE)
len);
10972 long len = (
long)ibf_load_small_value(load, &offset);
10976 for (
i = 0;
i <
len;
i++) {
10977 VALUE key_index = ibf_load_small_value(load, &offset);
10978 VALUE val_index = ibf_load_small_value(load, &offset);
10980 VALUE key = ibf_load_object(load, key_index);
10981 VALUE val = ibf_load_object(load, val_index);
11000 range.class_index = 0;
11042 int sign = bignum->
slen > 0;
11065 ibf_dump_object_unsupported(dump,
obj);
11075 const char *data = (
const char *)&body[2];
11085 return ibf_load_object_unsupported(load, header, offset);
11102 VALUE a = ibf_load_object(load, nums->
a);
11103 VALUE b = ibf_load_object(load, nums->
b);
11116 VALUE str_index = ibf_dump_object(dump,
str);
11118 ibf_dump_write_small_value(dump, str_index);
11124 VALUE str_index = ibf_load_small_value(load, &offset);
11125 VALUE str = ibf_load_object(load, str_index);
11132 ibf_dump_object_unsupported,
11133 ibf_dump_object_unsupported,
11134 ibf_dump_object_class,
11135 ibf_dump_object_unsupported,
11136 ibf_dump_object_float,
11137 ibf_dump_object_string,
11138 ibf_dump_object_regexp,
11139 ibf_dump_object_array,
11140 ibf_dump_object_hash,
11141 ibf_dump_object_struct,
11142 ibf_dump_object_bignum,
11143 ibf_dump_object_unsupported,
11144 ibf_dump_object_data,
11145 ibf_dump_object_unsupported,
11146 ibf_dump_object_complex_rational,
11147 ibf_dump_object_complex_rational,
11148 ibf_dump_object_unsupported,
11149 ibf_dump_object_unsupported,
11150 ibf_dump_object_unsupported,
11151 ibf_dump_object_unsupported,
11152 ibf_dump_object_symbol,
11153 ibf_dump_object_unsupported,
11154 ibf_dump_object_unsupported,
11155 ibf_dump_object_unsupported,
11156 ibf_dump_object_unsupported,
11157 ibf_dump_object_unsupported,
11158 ibf_dump_object_unsupported,
11159 ibf_dump_object_unsupported,
11160 ibf_dump_object_unsupported,
11161 ibf_dump_object_unsupported,
11162 ibf_dump_object_unsupported,
11163 ibf_dump_object_unsupported,
11169 unsigned char byte =
11170 (header.
type << 0) |
11181 unsigned char byte = ibf_load_byte(load, offset);
11184 header.
type = (
byte >> 0) & 0x1f;
11186 header.
frozen = (
byte >> 6) & 0x01;
11187 header.
internal = (
byte >> 7) & 0x01;
11201 current_offset = ibf_dump_pos(dump);
11206 obj_header.internal =
FALSE;
11209 obj_header.special_const =
TRUE;
11210 obj_header.frozen =
TRUE;
11211 obj_header.internal =
TRUE;
11212 ibf_dump_object_object_header(dump, obj_header);
11213 ibf_dump_write_small_value(dump,
obj);
11218 obj_header.special_const =
FALSE;
11220 ibf_dump_object_object_header(dump, obj_header);
11221 (*dump_object_functions[obj_header.type])(dump,
obj);
11224 return current_offset;
11229 ibf_load_object_unsupported,
11230 ibf_load_object_unsupported,
11231 ibf_load_object_class,
11232 ibf_load_object_unsupported,
11233 ibf_load_object_float,
11234 ibf_load_object_string,
11235 ibf_load_object_regexp,
11236 ibf_load_object_array,
11237 ibf_load_object_hash,
11238 ibf_load_object_struct,
11239 ibf_load_object_bignum,
11240 ibf_load_object_unsupported,
11241 ibf_load_object_data,
11242 ibf_load_object_unsupported,
11243 ibf_load_object_complex_rational,
11244 ibf_load_object_complex_rational,
11245 ibf_load_object_unsupported,
11246 ibf_load_object_unsupported,
11247 ibf_load_object_unsupported,
11248 ibf_load_object_unsupported,
11249 ibf_load_object_symbol,
11250 ibf_load_object_unsupported,
11251 ibf_load_object_unsupported,
11252 ibf_load_object_unsupported,
11253 ibf_load_object_unsupported,
11254 ibf_load_object_unsupported,
11255 ibf_load_object_unsupported,
11256 ibf_load_object_unsupported,
11257 ibf_load_object_unsupported,
11258 ibf_load_object_unsupported,
11259 ibf_load_object_unsupported,
11260 ibf_load_object_unsupported,
11264 ibf_load_object(
const struct ibf_load *load,
VALUE object_index)
11266 if (object_index == 0) {
11277 const struct ibf_object_header header = ibf_load_object_object_header(load, &offset);
11280 fprintf(
stderr,
"ibf_load_object: list=%#x offsets=%p offset=%#x\n",
11282 fprintf(
stderr,
"ibf_load_object: type=%#x special=%d frozen=%d internal=%d\n",
11292 obj = ibf_load_small_value(load, &reading_pos);
11295 obj = (*load_object_functions[header.
type])(load, &header, offset);
11302 object_index,
obj);
11309 ibf_dump_object_list(
struct ibf_dump *dump,
ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size)
11322 *obj_list_offset = ibf_dump_pos(dump);
11329 *obj_list_size =
size;
11333 ibf_dump_mark(
void *
ptr)
11342 ibf_dump_free(
void *
ptr)
11353 ibf_dump_memsize(
const void *
ptr)
11356 size_t size =
sizeof(*dump);
11363 {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
11395 ibf_dump_setup(dump, dump_obj);
11397 ibf_dump_write(dump, &header,
sizeof(header));
11399 ibf_dump_iseq(dump,
iseq);
11401 header.
magic[0] =
'Y';
11402 header.
magic[1] =
'A';
11403 header.
magic[2] =
'R';
11404 header.
magic[3] =
'B';
11407 ibf_dump_iseq_list(dump, &header);
11409 header.
size = ibf_dump_pos(dump);
11412 VALUE opt_str = opt;
11421 ibf_dump_overwrite(dump, &header,
sizeof(header), 0);
11424 ibf_dump_free(dump);
11431 ibf_iseq_list(
const struct ibf_load *load)
11444 fprintf(
stderr,
"rb_ibf_load_iseq_complete: index=%#x offset=%#x size=%#x\n",
11448 ibf_load_iseq_each(load,
iseq, offset);
11449 ISEQ_COMPILE_DATA_CLEAR(
iseq);
11452 load->
iseq = prev_src_iseq;
11467 int iseq_index = (
int)(
VALUE)index_iseq;
11470 fprintf(
stderr,
"ibf_load_iseq: index_iseq=%p iseq_list=%p\n",
11471 (
void *)index_iseq, (
void *)load->
iseq_list);
11473 if (iseq_index == -1) {
11480 fprintf(
stderr,
"ibf_load_iseq: iseqv=%p\n", (
void *)iseqv);
11482 if (iseqv !=
Qnil) {
11494 fprintf(
stderr,
"ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n",
11505 if (
GET_VM()->builtin_function_table) {
11512 (
void *)
iseq, (
void *)load->
iseq);
11535 if (size < load->header->size) {
11575 ibf_loader_mark(
void *
ptr)
11584 ibf_loader_free(
void *
ptr)
11591 ibf_loader_memsize(
const void *
ptr)
11598 {ibf_loader_mark, ibf_loader_free, ibf_loader_memsize,},
11610 iseq = ibf_load_iseq(load, 0);
11624 iseq = ibf_load_iseq(load, 0);