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_ID(diobj, jump) &&
2734 replace_destination(iobj, diobj);
2753 unref_destination(iobj, 0);
2759 ELEM_INSERT_NEXT(&iobj->
link, &pop->
link);
2766 INSN *pdiobj = (
INSN *)get_destination_insn(piobj);
2767 if (niobj == pdiobj) {
2785 ?
BIN(branchunless) :
BIN(branchif);
2786 replace_destination(piobj, iobj);
2788 ELEM_REMOVE(&iobj->
link);
2795 else if (diobj == pdiobj) {
2811 ELEM_REPLACE(&piobj->
link, &popiobj->
link);
2831 VALUE str_beg, str_end;
2834 (end = (
INSN *)get_prev_insn(
range)) != 0 &&
2835 is_frozen_putstring(end, &str_end) &&
2836 (beg = (
INSN *)get_prev_insn(end)) != 0 &&
2837 is_frozen_putstring(beg, &str_beg)) {
2841 ELEM_REMOVE(&beg->
link);
2842 ELEM_REMOVE(&end->
link);
2864 INSN *nobj = (
INSN *)get_destination_insn(iobj);
2886 int stop_optimization =
2889 if (!stop_optimization) {
2901 replace_destination(iobj, nobj);
2922 replace_destination(iobj, nobj);
2969 if (prev_dup || !
IS_INSN_ID(pobj, newarray)) {
2972 else if (!iseq_pop_newarray(
iseq, pobj)) {
2974 ELEM_INSERT_PREV(&iobj->
link, &pobj->
link);
2979 ELEM_INSERT_NEXT(&iobj->
link, &pobj->
link);
2985 unref_destination(iobj, 0);
2986 ELEM_REMOVE(&iobj->
link);
2991 nobj = (
INSN *)get_destination_insn(nobj);
3006 if (previ ==
BIN(putobject) || previ ==
BIN(putnil) ||
3007 previ ==
BIN(putself) || previ ==
BIN(putstring) ||
3009 previ ==
BIN(getlocal) ||
3010 previ ==
BIN(getblockparam) ||
3011 previ ==
BIN(getblockparamproxy) ||
3013 previ ==
BIN(duparray)) {
3017 ELEM_REMOVE(&iobj->
link);
3019 else if (previ ==
BIN(newarray) && iseq_pop_newarray(
iseq, (
INSN*)prev)) {
3020 ELEM_REMOVE(&iobj->
link);
3022 else if (previ ==
BIN(concatarray)) {
3027 else if (previ ==
BIN(concatstrings)) {
3032 ELEM_REMOVE(&iobj->
link);
3085 ELEM_REMOVE(&next->
link);
3087 ELEM_REMOVE(&iobj->
link);
3101 next = (freeze = next)->next;
3103 next = get_destination_insn(jump = (
INSN *)next);
3110 ELEM_REMOVE(&label->
link);
3118 if (same_debug_pos_p(freeze, next->
next)) {
3119 ELEM_REMOVE(freeze);
3125 ELEM_INSERT_NEXT(next, &label->
link);
3126 CHECK(iseq_peephole_optimize(
iseq, get_next_insn(jump), do_tailcallopt));
3129 if (freeze) ELEM_REMOVE(freeze);
3148 ci->orig_argc == 0) {
3154 if (do_tailcallopt &&
3183 next = get_destination_insn((
INSN *)next);
3216 ELEM_REMOVE(&iobj->
link);
3224 ELEM_REMOVE(set1->
next);
3234 niobj = niobj->
next;
3246 if (
IS_INSN_ID(iobj, opt_invokebuiltin_delegate)) {
3249 iobj->
insn_id =
BIN(opt_invokebuiltin_delegate_leave);
3263 if (insn_id ==
BIN(opt_neq)) {
3268 iobj->
operands[1] = old_operands[0];
3289 ELEM_REMOVE(&niobj->
link);
3293 ELEM_REMOVE(&niobj->
link);
3304 #define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
3306 switch (
ci->orig_argc) {
3360 case ISEQ_TYPE_EVAL:
3361 case ISEQ_TYPE_MAIN:
3363 case ISEQ_TYPE_RESCUE:
3364 case ISEQ_TYPE_ENSURE:
3376 const int do_peepholeopt = ISEQ_COMPILE_DATA(
iseq)->option->peephole_optimization;
3377 const int do_tailcallopt = tailcallable_p(
iseq) &&
3378 ISEQ_COMPILE_DATA(
iseq)->option->tailcall_optimization;
3379 const int do_si = ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction;
3380 const int do_ou = ISEQ_COMPILE_DATA(
iseq)->option->operands_unification;
3381 int rescue_level = 0;
3382 int tailcallopt = do_tailcallopt;
3384 list = FIRST_ELEMENT(anchor);
3388 if (do_peepholeopt) {
3389 iseq_peephole_optimize(
iseq,
list, tailcallopt);
3395 insn_operands_unification((
INSN *)
list);
3402 tailcallopt =
FALSE;
3405 if (!--rescue_level) tailcallopt = do_tailcallopt;
3414 #if OPT_INSTRUCTIONS_UNIFICATION
3458 #if OPT_INSTRUCTIONS_UNIFICATION
3464 list = FIRST_ELEMENT(anchor);
3469 if (unified_insns_data[
id] != 0) {
3470 const int *
const *entry = unified_insns_data[
id];
3471 for (j = 1; j < (
intptr_t)entry[0]; j++) {
3472 const int *unified = entry[j];
3474 for (k = 2; k < unified[1]; k++) {
3476 ((
INSN *)li)->insn_id != unified[k]) {
3483 new_unified_insn(
iseq, unified[0], unified[1] - 1,
3506 #if OPT_STACK_CACHING
3508 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
3509 #define SC_NEXT(insn) sc_insn_next[(insn)]
3511 #include "opt_sc.inc"
3520 iobj->
insn_id = SC_INSN(insn_id, state);
3521 nstate = SC_NEXT(iobj->
insn_id);
3523 if (insn_id ==
BIN(jump) ||
3524 insn_id ==
BIN(branchif) || insn_id ==
BIN(branchunless)) {
3540 if (insn_id ==
BIN(jump)) {
3544 else if (insn_id ==
BIN(leave)) {
3552 label_set_sc_state(
LABEL *lobj,
int state)
3572 #if OPT_STACK_CACHING
3578 list = FIRST_ELEMENT(anchor);
3584 switch (
list->type) {
3585 case ISEQ_ELEMENT_INSN:
3596 if (state != SCS_AX) {
3598 new_insn_body(
iseq, 0,
BIN(reput), 0);
3609 if (state == SCS_AB || state == SCS_BA) {
3610 state = (state == SCS_AB ? SCS_BA : SCS_AB);
3647 state = insn_set_sc_state(
iseq, anchor, iobj, state);
3650 case ISEQ_ELEMENT_LABEL:
3655 state = label_set_sc_state(lobj, state);
3667 all_string_result_p(
const NODE *node)
3669 if (!node)
return FALSE;
3674 if (!node->nd_body || !node->nd_else)
return FALSE;
3675 if (all_string_result_p(node->nd_body))
3676 return all_string_result_p(node->nd_else);
3680 return all_string_result_p(node->nd_1st);
3681 if (!all_string_result_p(node->nd_1st))
3683 return all_string_result_p(node->nd_2nd);
3693 VALUE lit = node->nd_lit;
3708 if (
RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
3712 const NODE *
const head =
list->nd_head;
3725 if (
NIL_P(lit) && first_lit) {
3726 ELEM_REMOVE(first_lit);
3756 const int line =
nd_line(node);
3767 ADD_INSNL(ret, line, branchunless, else_label);
3777 ADD_INSNL(ret, line, branchunless, then_label);
3794 CHECK(compile_branch_condition(
iseq, ret, cond->nd_1st, label,
3796 if (!label->
refcnt)
break;
3798 cond = cond->nd_2nd;
3804 CHECK(compile_branch_condition(
iseq, ret, cond->nd_1st, then_label,
3806 if (!label->
refcnt)
break;
3808 cond = cond->nd_2nd;
3832 CHECK(compile_flip_flop(
iseq, ret, cond,
TRUE, then_label, else_label));
3835 CHECK(compile_flip_flop(
iseq, ret, cond,
FALSE, then_label, else_label));
3851 keyword_node_p(
const NODE *
const node)
3858 const NODE *
const root_node,
3864 if (keyword_node_p(root_node) && root_node->nd_head &&
nd_type(root_node->nd_head) ==
NODE_LIST) {
3865 const NODE *node = root_node->nd_head;
3868 const NODE *key_node = node->nd_head;
3882 node = node->nd_next;
3883 node = node->nd_next;
3887 node = root_node->nd_head;
3889 int len = (
int)node->nd_alen / 2;
3896 *kw_arg_ptr = kw_arg;
3898 for (
i=0; node !=
NULL;
i++, node = node->nd_next->nd_next) {
3899 const NODE *key_node = node->nd_head;
3900 const NODE *val_node = node->nd_next->nd_head;
3917 for (; node;
len++, node = node->nd_next) {
3922 if (node->nd_next ==
NULL &&
3923 compile_keyword_arg(
iseq, ret, node->nd_head, keywords_ptr, flag)) {
3937 node = node->nd_head;
3945 return ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal;
3954 node = node->nd_head;
3974 return node->nd_lit;
3993 for (; node; node = node->nd_next) {
4036 const int max_stack_len = 0x100;
4037 const int min_tmp_ary_len = 0x40;
4039 int first_chunk = 1;
4042 #define FLUSH_CHUNK(newarrayinsn) \
4044 ADD_INSN1(ret, line, newarrayinsn, INT2FIX(stack_len)); \
4045 if (!first_chunk) ADD_INSN(ret, line, concatarray); \
4046 first_chunk = stack_len = 0; \
4053 if (static_literal_node_p(node,
iseq)) {
4055 const NODE *node_tmp = node->nd_next;
4056 for (; node_tmp && static_literal_node_p(node_tmp,
iseq); node_tmp = node_tmp->nd_next)
4059 if ((first_chunk && stack_len == 0 && !node_tmp) ||
count >= min_tmp_ary_len) {
4083 for (;
count;
count--, node = node->nd_next) {
4091 if (!node->nd_next && keyword_node_p(node->nd_head)) {
4098 if (stack_len >= max_stack_len)
FLUSH_CHUNK(newarray);
4110 return node->nd_head && static_literal_node_p(node,
iseq) && static_literal_node_p(node->nd_next,
iseq);
4118 node = node->nd_head;
4130 for (; node; node = node->nd_next) {
4154 const int max_stack_len = 0x100;
4155 const int min_tmp_hash_len = 0x800;
4157 int first_chunk = 1;
4162 #define FLUSH_CHUNK() \
4164 if (first_chunk) { \
4165 APPEND_LIST(ret, anchor); \
4166 ADD_INSN1(ret, line, newhash, INT2FIX(stack_len)); \
4169 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \
4170 ADD_INSN(ret, line, swap); \
4171 APPEND_LIST(ret, anchor); \
4172 ADD_SEND(ret, line, id_core_hash_merge_ptr, INT2FIX(stack_len + 1)); \
4174 INIT_ANCHOR(anchor); \
4175 first_chunk = stack_len = 0; \
4182 if (static_literal_node_pair_p(node,
iseq)) {
4184 const NODE *node_tmp = node->nd_next->nd_next;
4185 for (; node_tmp && static_literal_node_pair_p(node_tmp,
iseq); node_tmp = node_tmp->nd_next->nd_next)
4188 if ((first_chunk && stack_len == 0 && !node_tmp) ||
count >= min_tmp_hash_len) {
4193 for (;
count;
count--, node = node->nd_next->nd_next) {
4195 elem[0] = static_literal_value(node,
iseq);
4196 elem[1] = static_literal_value(node->nd_next,
iseq);
4223 for (;
count;
count--, node = node->nd_next->nd_next) {
4229 if (node->nd_head) {
4232 NO_CHECK(
COMPILE_(anchor,
"hash value element", node->nd_next->nd_head, 0));
4242 const NODE *kw = node->nd_next->nd_head;
4244 int first_kw = first_chunk && stack_len == 0;
4245 int last_kw = !node->nd_next->nd_next;
4246 int only_kw = last_kw && first_kw;
4256 else if (first_kw) {
4317 LABEL *l1,
int only_special_literals,
VALUE literals)
4320 const NODE *val = vals->nd_head;
4324 only_special_literals = 0;
4339 if (!
COMPILE(cond_seq,
"when cond", val))
return -1;
4344 vals = vals->nd_next;
4346 return only_special_literals;
4351 LABEL *l1,
int only_special_literals,
VALUE literals)
4353 const int line =
nd_line(vals);
4357 if (when_vals(
iseq, cond_seq, vals, l1, only_special_literals, literals) < 0)
4365 ADD_INSNL(cond_seq, line, branchif, l1);
4368 CHECK(when_splat_vals(
iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
4369 CHECK(when_splat_vals(
iseq, cond_seq, vals->nd_body, l1, only_special_literals, literals));
4372 CHECK(when_splat_vals(
iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
4374 CHECK(
COMPILE(cond_seq,
"when argspush body", vals->nd_body));
4376 ADD_INSNL(cond_seq, line, branchif, l1);
4383 ADD_INSNL(cond_seq, line, branchif, l1);
4402 iobj = (
INSN *)get_prev_insn((
INSN *)LAST_ELEMENT(ret));
4420 ELEM_REMOVE(FIRST_ELEMENT(anchor));
4428 ELEM_REMOVE(FIRST_ELEMENT(anchor));
4440 CHECK(compile_massign_opt_lhs(
iseq, ret, lhsn->nd_next));
4441 CHECK(compile_massign_lhs(
iseq, ret, lhsn->nd_head));
4448 const NODE *rhsn,
const NODE *orig_lhsn)
4453 int llen = 0, rlen = 0;
4455 const NODE *lhsn = orig_lhsn;
4457 #define MEMORY(v) { \
4459 if (memindex == memsize) return 0; \
4460 for (i=0; i<memindex; i++) { \
4461 if (mem[i] == (v)) return 0; \
4463 mem[memindex++] = (v); \
4471 const NODE *ln = lhsn->nd_head;
4485 lhsn = lhsn->nd_next;
4496 rhsn = rhsn->nd_next;
4501 for (
i=0;
i<llen-rlen;
i++) {
4506 compile_massign_opt_lhs(
iseq, ret, orig_lhsn);
4514 do {
ADD_INSN(ret, line, putnil);}
while (++rlen < llen);
4516 else if (rlen > llen) {
4517 do {
ADD_INSN(ret, line, pop);}
while (--rlen > llen);
4524 const NODE *rhsn = node->nd_value;
4525 const NODE *splatn = node->nd_args;
4526 const NODE *lhsn = node->nd_head;
4529 if (!popped || splatn || !compile_massign_opt(
iseq, ret, rhsn, lhsn)) {
4537 CHECK(compile_massign_lhs(
iseq, lhsseq, lhsn->nd_head));
4539 lhsn = lhsn->nd_next;
4547 else if (!lhs_splat) {
4551 last->operand_size == 1) {
4556 adjust_stack(
iseq, ret,
nd_line(node), rlen, llen);
4560 else if (llen > 2 && llen != rlen) {
4562 adjust_stack(
iseq, ret,
nd_line(node), rlen, llen);
4566 else if (llen > 2) {
4581 const NODE *postn = splatn->nd_2nd;
4582 const NODE *restn = splatn->nd_1st;
4583 int num = (
int)postn->nd_alen;
4590 CHECK(compile_massign_lhs(
iseq, ret, restn));
4593 CHECK(compile_massign_lhs(
iseq, ret, postn->nd_head));
4594 postn = postn->nd_next;
4599 CHECK(compile_massign_lhs(
iseq, ret, splatn));
4612 debugi(
"compile_const_prefix - colon", node->nd_vid);
4617 debugi(
"compile_const_prefix - colon3", node->nd_mid);
4624 CHECK(compile_const_prefix(
iseq, node->nd_head, pref, body));
4625 debugi(
"compile_const_prefix - colon2", node->nd_mid);
4644 else if (cpath->nd_head) {
4658 private_recv_p(
const NODE *node)
4661 NODE *
self = node->nd_recv;
4662 return self->nd_state != 0;
4677 const int line =
nd_line(node);
4696 const NODE *vals = node;
4699 defined_expr0(
iseq, ret, vals->nd_head, lfinish,
Qfalse);
4704 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4705 }
while ((vals = vals->nd_next) !=
NULL);
4726 ID2SYM(node->nd_vid), needstr);
4732 ID2SYM(node->nd_entry->
id), needstr);
4738 ID2SYM(node->nd_vid), needstr);
4744 ID2SYM(node->nd_vid), needstr);
4750 defined_expr0(
iseq, ret, node->nd_head, lfinish,
Qfalse);
4751 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4757 ID2SYM(node->nd_mid), needstr);
4771 const int explicit_receiver =
4775 if (!lfinish[1] && (node->nd_args || explicit_receiver)) {
4778 if (node->nd_args) {
4779 defined_expr0(
iseq, ret, node->nd_args, lfinish,
Qfalse);
4780 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4782 if (explicit_receiver) {
4783 defined_expr0(
iseq, ret, node->nd_recv, lfinish,
Qfalse);
4784 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4787 ID2SYM(node->nd_mid), needstr);
4792 ID2SYM(node->nd_mid), needstr);
4849 iseq_set_exception_local_table(
iseq);
4857 defined_expr0(
iseq, ret, node, lfinish, needstr);
4864 rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq,
NULL);
4865 rescue = new_child_iseq_with_callback(
iseq, ifunc,
4868 iseq, ISEQ_TYPE_RESCUE, 0);
4880 const int line =
nd_line(node);
4881 if (!node->nd_head) {
4890 defined_expr(
iseq, ret, node->nd_head, lfinish, needstr);
4892 ELEM_INSERT_NEXT(
last, &new_insn_body(
iseq, line,
BIN(putnil), 0)->
link);
4903 make_name_for_block(
const rb_iseq_t *orig_iseq)
4931 enl->
prev = ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack;
4933 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = enl;
4943 while (erange->
next != 0) {
4944 erange = erange->
next;
4948 ne->end = erange->
end;
4949 erange->
end = lstart;
4958 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack;
4970 add_ensure_range(
iseq, enlp->
erange, lstart, lend);
4972 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = enlp->
prev;
4985 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = prev_enlp;
4990 check_keyword(
const NODE *node)
4995 while (node->nd_next) {
4996 node = node->nd_next;
4998 node = node->nd_head;
5001 return keyword_node_p(node);
5022 int rest_len = compile_args(
iseq, args, argn->nd_body,
NULL,
NULL);
5032 if (check_keyword(argn->nd_body))
5053 int len = compile_args(
iseq, args, argn, keywords, flag);
5075 ret = setup_args_core(
iseq, args, argn->nd_head, 0, flag, keywords);
5077 if (LIST_INSN_SIZE_ONE(arg_block)) {
5079 if (elem->
type == ISEQ_ELEMENT_INSN) {
5089 ret = setup_args_core(
iseq, args, argn, 0, flag, keywords);
5105 iseq_set_local_table(
iseq, 0);
5116 #if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0)
5122 ADD_INSNL(ret, line, branchunless, fail_label);
5126 if (
vars->nd_next) {
5135 #if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
5136 if (!
vars->nd_next &&
vars == node) {
5168 number_literal_p(
const NODE *
n)
5177 const NODE *
const node_body =
type ==
NODE_IF ? node->nd_body : node->nd_else;
5178 const NODE *
const node_else =
type ==
NODE_IF ? node->nd_else : node->nd_body;
5180 const int line =
nd_line(node);
5188 LABEL *then_label, *else_label, *end_label;
5201 compile_branch_condition(
iseq, cond_seq, node->nd_cond,
5202 then_label, else_label);
5208 if (!then_label->
refcnt) {
5221 if (!else_label->
refcnt) {
5236 if (then_label->
refcnt) {
5238 if (else_label->
refcnt) {
5248 ADD_INSNL(then_seq, line, jump, end_label);
5253 if (else_label->
refcnt) {
5255 if (then_label->
refcnt) {
5279 const NODE *node = orig_node;
5280 LABEL *endlabel, *elselabel;
5284 int only_special_literals = 1;
5286 int line, lineno, column, last_lineno, last_column;
5300 node = node->nd_body;
5328 CHECK(
COMPILE_(body_seq,
"when body", node->nd_body, popped));
5329 ADD_INSNL(body_seq, line, jump, endlabel);
5331 vals = node->nd_head;
5335 only_special_literals = when_vals(
iseq, cond_seq, vals, l1, only_special_literals, literals);
5336 if (only_special_literals < 0)
return COMPILE_NG;
5341 only_special_literals = 0;
5342 CHECK(when_splat_vals(
iseq, cond_seq, vals, l1, only_special_literals, literals));
5352 node = node->nd_next;
5369 ADD_INSNL(cond_seq, line, jump, endlabel);
5372 debugs(
"== else (implicit)\n");
5382 if (only_special_literals && ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction) {
5384 ADD_INSN2(ret,
nd_line(orig_node), opt_case_dispatch, literals, elselabel);
5400 const NODE *node = orig_node->nd_body;
5411 const int line =
nd_line(node);
5427 ADD_INSNL(body_seq, line, jump, endlabel);
5429 vals = node->nd_head;
5437 val = vals->nd_head;
5440 CHECK(compile_branch_condition(
iseq, ret, val, l1, lnext));
5442 vals = vals->nd_next;
5456 node = node->nd_next;
5478 const int line =
nd_line(node);
5541 const int min_argc = pre_args_num + post_args_num;
5545 LABEL *match_failed, *type_error, *fin;
5556 if (node->nd_pconst) {
5560 ADD_INSNL(ret, line, branchunless, match_failed);
5566 ADD_INSNL(ret, line, branchunless, match_failed);
5572 ADD_INSNL(ret, line, branchunless, type_error);
5578 ADD_INSNL(ret, line, branchunless, match_failed);
5580 for (
i = 0;
i < pre_args_num;
i++) {
5584 iseq_compile_pattern_each(
iseq, ret, args->nd_head, in_alt_pattern);
5585 args = args->nd_next;
5586 ADD_INSNL(ret, line, branchunless, match_failed);
5600 iseq_compile_pattern_each(
iseq, ret, apinfo->
rest_arg, in_alt_pattern);
5601 ADD_INSNL(ret, line, branchunless, match_failed);
5604 if (post_args_num > 0) {
5616 for (
i = 0;
i < post_args_num;
i++) {
5624 iseq_compile_pattern_each(
iseq, ret, args->nd_head, in_alt_pattern);
5625 args = args->nd_next;
5626 ADD_INSNL(ret, line, branchunless, match_failed);
5714 LABEL *match_failed, *type_error, *fin;
5721 if (node->nd_pkwargs && !node->nd_pkwrestarg) {
5722 const NODE *kw_args = node->nd_pkwargs->nd_head;
5726 kw_args = kw_args->nd_next->nd_next;
5730 if (node->nd_pconst) {
5734 ADD_INSNL(ret, line, branchunless, match_failed);
5740 ADD_INSNL(ret, line, branchunless, match_failed);
5753 ADD_INSNL(ret, line, branchunless, type_error);
5755 if (node->nd_pkwrestarg) {
5759 if (node->nd_pkwargs) {
5763 args = node->nd_pkwargs->nd_head;
5768 for (
i = 0;
i < keys_num;
i++) {
5769 NODE *key_node = args->nd_head;
5770 NODE *value_node = args->nd_next->nd_head;
5776 key = key_node->nd_lit;
5781 ADD_INSNL(ret, line, branchunless, match_failed);
5786 iseq_compile_pattern_each(
iseq, match_values, value_node, in_alt_pattern);
5787 ADD_INSNL(match_values, line, branchunless, match_failed);
5788 args = args->nd_next->nd_next;
5796 ADD_INSNL(ret, line, branchunless, match_failed);
5799 if (node->nd_pkwrestarg) {
5803 ADD_INSNL(ret, line, branchunless, match_failed);
5807 iseq_compile_pattern_each(
iseq, ret, node->nd_pkwrestarg, in_alt_pattern);
5808 ADD_INSNL(ret, line, branchunless, match_failed);
5854 ID id = node->nd_vid;
5857 if (in_alt_pattern) {
5873 ID id = node->nd_vid;
5875 idx = get_dyna_var_idx(
iseq,
id, &lv, &ls);
5877 if (in_alt_pattern) {
5897 LABEL *match_failed, *fin;
5900 iseq_compile_pattern_each(
iseq, ret, node->nd_body, in_alt_pattern);
5901 ADD_INSNL(ret, line, branchunless, match_failed);
5904 ADD_INSNL(ret, line, branchunless, match_failed);
5907 ADD_INSNL(ret, line, branchif, match_failed);
5920 LABEL *match_failed, *fin;
5931 iseq_compile_pattern_each(
iseq, ret,
n->nd_head, in_alt_pattern);
5932 ADD_INSNL(ret, line, branchunless, match_failed);
5933 iseq_compile_pattern_each(
iseq, ret,
n->nd_next->nd_head, in_alt_pattern);
5944 LABEL *match_succeeded, *fin;
5949 iseq_compile_pattern_each(
iseq, ret, node->nd_1st,
TRUE);
5950 ADD_INSNL(ret, line, branchif, match_succeeded);
5951 iseq_compile_pattern_each(
iseq, ret, node->nd_2nd,
TRUE);
5970 const NODE *pattern;
5971 const NODE *node = orig_node;
5972 LABEL *endlabel, *elselabel;
5976 int line, lineno, column, last_lineno, last_column;
5988 node = node->nd_body;
6016 CHECK(
COMPILE_(body_seq,
"in body", node->nd_body, popped));
6017 ADD_INSNL(body_seq, line, jump, endlabel);
6019 pattern = node->nd_head;
6022 iseq_compile_pattern_each(
iseq, cond_seq, pattern,
FALSE);
6030 node = node->nd_next;
6047 ADD_INSNL(cond_seq, line, jump, endlabel);
6050 debugs(
"== else (implicit)\n");
6079 LABEL *prev_start_label = ISEQ_COMPILE_DATA(
iseq)->start_label;
6080 LABEL *prev_end_label = ISEQ_COMPILE_DATA(
iseq)->end_label;
6081 LABEL *prev_redo_label = ISEQ_COMPILE_DATA(
iseq)->redo_label;
6082 int prev_loopval_popped = ISEQ_COMPILE_DATA(
iseq)->loopval_popped;
6096 ISEQ_COMPILE_DATA(
iseq)->loopval_popped = 0;
6099 if (node->nd_state == 1) {
6111 if (tmp_label)
ADD_LABEL(ret, tmp_label);
6127 compile_branch_condition(
iseq, ret, node->nd_cond,
6128 redo_label, end_label);
6132 compile_branch_condition(
iseq, ret, node->nd_cond,
6133 end_label, redo_label);
6139 if (node->nd_state ==
Qundef) {
6159 ISEQ_COMPILE_DATA(
iseq)->redo_label);
6161 ISEQ_COMPILE_DATA(
iseq)->start_label = prev_start_label;
6162 ISEQ_COMPILE_DATA(
iseq)->end_label = prev_end_label;
6163 ISEQ_COMPILE_DATA(
iseq)->redo_label = prev_redo_label;
6164 ISEQ_COMPILE_DATA(
iseq)->loopval_popped = prev_loopval_popped;
6165 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack->prev;
6172 const int line =
nd_line(node);
6173 const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(
iseq)->current_block;
6180 CHECK(
COMPILE(ret,
"iter caller (for)", node->nd_iter));
6182 ISEQ_COMPILE_DATA(
iseq)->current_block = child_iseq =
6184 ISEQ_TYPE_BLOCK, line);
6188 ISEQ_COMPILE_DATA(
iseq)->current_block = child_iseq =
6190 ISEQ_TYPE_BLOCK, line);
6199 ISEQ_COMPILE_DATA(
iseq)->current_block = prevblock;
6201 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l);
6211 const int line =
nd_line(node);
6212 const NODE *var = node->nd_var;
6220 ADD_INSNL(ret, line, branchunless, not_single);
6228 ADD_INSNL(ret, line, branchunless, not_ary);
6239 const int line =
nd_line(node);
6240 unsigned long throw_flag = 0;
6242 if (ISEQ_COMPILE_DATA(
iseq)->redo_label != 0) {
6247 CHECK(
COMPILE_(ret,
"break val (while/until)", node->nd_stts,
6248 ISEQ_COMPILE_DATA(
iseq)->loopval_popped));
6249 add_ensure_iseq(ret,
iseq, 0);
6250 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->end_label);
6260 CHECK(
COMPILE(ret,
"break val (block)", node->nd_stts));
6275 if (!ISEQ_COMPILE_DATA(ip)) {
6280 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6284 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6287 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6302 const int line =
nd_line(node);
6303 unsigned long throw_flag = 0;
6305 if (ISEQ_COMPILE_DATA(
iseq)->redo_label != 0) {
6307 debugs(
"next in while loop\n");
6309 CHECK(
COMPILE(ret,
"next val/valid syntax?", node->nd_stts));
6310 add_ensure_iseq(ret,
iseq, 0);
6312 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->start_label);
6318 else if (ISEQ_COMPILE_DATA(
iseq)->end_label) {
6320 debugs(
"next in block\n");
6324 add_ensure_iseq(ret,
iseq, 0);
6325 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->end_label);
6342 if (!ISEQ_COMPILE_DATA(ip)) {
6348 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6352 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6355 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6380 const int line =
nd_line(node);
6382 if (ISEQ_COMPILE_DATA(
iseq)->redo_label) {
6387 add_ensure_iseq(ret,
iseq, 0);
6388 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->redo_label);
6399 else if (ISEQ_COMPILE_DATA(
iseq)->start_label) {
6404 add_ensure_iseq(ret,
iseq, 0);
6406 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(
iseq)->start_label);
6417 if (!ISEQ_COMPILE_DATA(ip)) {
6422 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6425 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6428 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6453 const int line =
nd_line(node);
6473 const int line =
nd_line(node);
6479 ISEQ_TYPE_RESCUE, line);
6486 if (node->nd_else) {
6506 const int line =
nd_line(node);
6507 const NODE *resq = node;
6509 LABEL *label_miss, *label_hit;
6515 narg = resq->nd_args;
6523 ADD_INSNL(ret, line, branchif, label_hit);
6524 narg = narg->nd_next;
6533 ADD_INSNL(ret, line, branchif, label_hit);
6543 ADD_INSNL(ret, line, branchif, label_hit);
6548 if (ISEQ_COMPILE_DATA(
iseq)->option->tailcall_optimization) {
6553 resq = resq->nd_head;
6561 const int line =
nd_line(node);
6565 ISEQ_TYPE_ENSURE, line);
6583 push_ensure_entry(
iseq, &enl, &er, node->nd_ensr);
6586 CHECK(
COMPILE_(ret,
"ensure head", node->nd_head, (popped | last_leave)));
6589 if (!popped && last_leave)
ADD_INSN(ret, line, putnil);
6591 if (last_leave)
ADD_INSN(ret, line, pop);
6593 erange = ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack->erange;
6598 erange = erange->
next;
6602 ISEQ_COMPILE_DATA(
iseq)->ensure_node_stack = enl.prev;
6609 const int line =
nd_line(node);
6614 enum iseq_type t =
type;
6615 const NODE *retval = node->nd_stts;
6618 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) {
6624 case ISEQ_TYPE_MAIN:
6626 rb_warn(
"argument of top-level return is ignored");
6630 type = ISEQ_TYPE_METHOD;
6637 if (
type == ISEQ_TYPE_METHOD) {
6643 CHECK(
COMPILE(ret,
"return nd_stts (return val)", retval));
6645 if (
type == ISEQ_TYPE_METHOD) {
6646 add_ensure_iseq(ret,
iseq, 1);
6670 if (!popped && !all_string_result_p(node)) {
6671 const int line =
nd_line(node);
6693 DECL_BRANCH_BASE(br, first_lineno, first_column, last_lineno, last_column,
"&.");
6696 ADD_INSNL(recv, line, branchnil, else_label);
6705 if (!else_label)
return;
6722 node->nd_args ==
NULL &&
6723 ISEQ_COMPILE_DATA(
iseq)->current_block ==
NULL &&
6724 ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction) {
6743 if (node->nd_mid ==
idAREF && !private_recv_p(node) && node->nd_args &&
6746 ISEQ_COMPILE_DATA(
iseq)->current_block ==
NULL &&
6747 !ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal &&
6748 ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction) {
6765 return ISEQ_COMPILE_DATA(
iseq)->builtin_function_table !=
NULL;
6773 for (
i=0; table[
i].
index != -1;
i++) {
6782 iseq_builtin_function_name(
ID mid)
6785 static const char prefix[] =
"__builtin_";
6786 const size_t prefix_len =
sizeof(prefix) - 1;
6789 return &
name[prefix_len];
6805 unsigned int start=0;
6814 for (
unsigned int i=start;
i-start<
argc;
i++) {
6815 if (elem->
type == ISEQ_ELEMENT_INSN &&
6820 if (local_level == 0) {
6823 fprintf(
stderr,
"lvar:%s (%d), id:%s (%d) local_index:%d, local_size:%d\n",
6850 *pstart_index = start;
6867 ID mid = node->nd_mid;
6869 unsigned int flag = 0;
6871 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(
iseq)->current_block;
6875 ISEQ_COMPILE_DATA(
iseq)->current_block =
NULL;
6879 #if OPT_SUPPORT_JOKE
6885 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
6887 if (mid == id_bitblt) {
6891 else if (mid == id_answer) {
6905 (mid == goto_id || mid == label_id)) {
6908 st_table *labels_table = ISEQ_COMPILE_DATA(
iseq)->labels_table;
6911 if (!labels_table) {
6913 ISEQ_COMPILE_DATA(
iseq)->labels_table = labels_table;
6916 SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
6918 label_name = node->nd_args->nd_head->nd_lit;
6925 label = (
LABEL *)data;
6933 if (mid == goto_id) {
6943 const char *builtin_func;
6944 NODE *args_node = node->nd_args;
6947 (builtin_func = iseq_builtin_function_name(mid)) !=
NULL) {
6949 if (parent_block !=
NULL) {
6954 char inline_func[0x20];
6955 bool cconst =
false;
6960 if (
strcmp(
"cstmt!", builtin_func) == 0 ||
6961 strcmp(
"cexpr!", builtin_func) == 0) {
6963 int inline_index =
GET_VM()->builtin_inline_index++;
6964 snprintf(inline_func, 0x20,
"_bi%d", inline_index);
6965 builtin_func = inline_func;
6969 else if (
strcmp(
"cconst!", builtin_func) == 0) {
6973 else if (
strcmp(
"cinit!", builtin_func) == 0) {
6975 GET_VM()->builtin_inline_index++;
6980 rb_bug(
"can't find builtin function:%s", builtin_func);
6989 typedef VALUE(*builtin_func0)(
void *,
VALUE);
6991 ADD_INSN1(ret, line, putobject, const_val);
6997 argc = setup_args(
iseq, args, args_node, &flag, &keywords);
7005 unsigned int start_index;
7007 ADD_INSN2(ret, line, opt_invokebuiltin_delegate, bf,
INT2FIX(start_index));
7014 if (popped)
ADD_INSN(ret, line, pop);
7026 iseq_block_param_id_p(
iseq, node->nd_recv->nd_vid, &idx, &level)) {
7029 else if (private_recv_p(node)) {
7038 else_label = qcall_branch_start(
iseq, recv, &branches, node, line);
7047 argc = setup_args(
iseq, args, node->nd_args, &flag, &keywords);
7060 switch ((
int)
type) {
7070 qcall_branch_end(
iseq, ret, else_label, branches, node, line);
7091 int lineno = ISEQ_COMPILE_DATA(
iseq)->last_line;
7093 debugs(
"node: NODE_NIL(implicit)\n");
7098 return iseq_compile_each0(
iseq, ret, node, popped);
7107 case ISEQ_TYPE_MAIN:
7109 case ISEQ_TYPE_CLASS:
7113 "`yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]");
7128 if (ISEQ_COMPILE_DATA(
iseq)->last_line == line) {
7134 ISEQ_COMPILE_DATA(
iseq)->last_line = line;
7143 #undef BEFORE_RETURN
7144 #define BEFORE_RETURN debug_node_end()
7150 (node->nd_next ? 1 : popped)));
7151 node = node->nd_next;
7163 CHECK(compile_case(
iseq, ret, node, popped));
7166 CHECK(compile_case2(
iseq, ret, node, popped));
7169 CHECK(compile_case3(
iseq, ret, node, popped));
7177 CHECK(compile_iter(
iseq, ret, node, popped));
7180 CHECK(compile_for_masgn(
iseq, ret, node, popped));
7183 CHECK(compile_break(
iseq, ret, node, popped));
7186 CHECK(compile_next(
iseq, ret, node, popped));
7189 CHECK(compile_redo(
iseq, ret, node, popped));
7192 CHECK(compile_retry(
iseq, ret, node, popped));
7199 CHECK(compile_rescue(
iseq, ret, node, popped));
7202 CHECK(compile_resbody(
iseq, ret, node, popped));
7205 CHECK(compile_ensure(
iseq, ret, node, popped));
7216 ADD_INSNL(ret, line, branchunless, end_label);
7219 ADD_INSNL(ret, line, branchif, end_label);
7230 compile_massign(
iseq, ret, node, popped);
7235 ID id = node->nd_vid;
7250 ID id = node->nd_vid;
7258 idx = get_dyna_var_idx(
iseq,
id, &lv, &ls);
7275 ((
VALUE)node->nd_entry | 1));
7283 ADD_INSN2(ret, line, setinstancevariable,
7285 get_ivar_ic_value(
iseq,node->nd_vid));
7301 compile_cpath(ret,
iseq, node->nd_else);
7317 unsigned int flag = 0;
7319 ID id = node->nd_mid;
7348 asgnflag =
COMPILE_RECV(ret,
"NODE_OP_ASGN1 recv", node);
7349 CHECK(asgnflag != -1);
7350 switch (
nd_type(node->nd_args->nd_head)) {
7358 argc = setup_args(
iseq, ret, node->nd_args->nd_head, &flag,
NULL);
7382 ADD_INSNL(ret, line, branchunless, label);
7386 CHECK(
COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
7420 CHECK(
COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
7451 ID atype = node->nd_next->nd_mid;
7499 asgnflag =
COMPILE_RECV(ret,
"NODE_OP_ASGN2#recv", node);
7500 CHECK(asgnflag != -1);
7501 if (node->nd_next->nd_aid) {
7515 ADD_INSNL(ret, line, branchunless, lcfin);
7518 CHECK(
COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
7538 CHECK(
COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
7545 if (lskip && popped) {
7549 if (lskip && !popped) {
7560 switch (
nd_type(node->nd_head)) {
7565 CHECK(
COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
7572 mid = node->nd_head->nd_mid;
7574 if (node->nd_aid ==
idOROP) {
7579 ADD_INSNL(ret, line, branchunless, lassign);
7588 if (node->nd_aid ==
idOROP)
7591 ADD_INSNL(ret, line, branchunless, lfin);
7593 if (!popped)
ADD_INSN(ret, line, pop);
7595 CHECK(
COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
7605 if (!popped)
ADD_INSN(ret, line, swap);
7609 CHECK(
COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
7631 defined_expr(
iseq, ret, node->nd_head, lfinish,
Qfalse);
7632 lassign = lfinish[1];
7636 ADD_INSNL(ret, line, branchunless, lassign);
7642 CHECK(
COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
7646 ADD_INSNL(ret, line, branchunless, lfin);
7654 CHECK(
COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_value", node->nd_value));
7665 if (compile_call_precheck_freeze(
iseq, ret, node, line, popped) ==
TRUE) {
7679 unsigned int flag = 0;
7681 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(
iseq)->current_block;
7684 ISEQ_COMPILE_DATA(
iseq)->current_block =
NULL;
7695 const struct rb_iseq_param_keyword *
const local_kwd = local_body->
param.
keyword;
7696 int lvar_level = get_lvar_level(
iseq);
7733 for (j=0; j<post_len; j++) {
7738 ADD_INSN (args, line, concatarray);
7743 for (j=0; j<post_len; j++) {
7747 argc = post_len + post_start;
7765 for (
i = 0;
i < local_kwd->num; ++
i) {
7766 ID id = local_kwd->table[
i];
7767 int idx =
local_size - get_local_var_idx(liseq,
id);
7774 ADD_INSN (args, line, concatarray);
7779 else if (local_body->
param.
flags.has_kwrest) {
7786 ADD_INSN (args, line, concatarray);
7807 CHECK(compile_array(
iseq, ret, node, popped) >= 0);
7817 const NODE *
n = node;
7829 CHECK(compile_hash(
iseq, ret, node, popped) >= 0);
7832 CHECK(compile_return(
iseq, ret, node, popped));
7837 unsigned int flag = 0;
7842 if (check_yield_place(
iseq, line) ==
FALSE) {
7847 if (node->nd_head) {
7865 ID id = node->nd_vid;
7875 debugi(
"nd_vid", node->nd_vid);
7877 idx = get_dyna_var_idx(
iseq, node->nd_vid, &lv, &ls);
7889 ((
VALUE)node->nd_entry | 1));
7896 debugi(
"nd_vid", node->nd_vid);
7898 ADD_INSN2(ret, line, getinstancevariable,
7900 get_ivar_ic_value(
iseq,node->nd_vid));
7905 debugi(
"nd_vid", node->nd_vid);
7907 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
7909 int ic_index = body->
is_size++;
7937 if (!node->nd_nth) {
7949 INT2FIX(0x01 | (node->nd_nth << 1)));
7963 ADD_INSN1(recv, line, putobject, node->nd_lit);
7981 if (node->nd_args) {
7982 compile_named_capture_assign(
iseq, ret, node->nd_args);
7993 ADD_INSN1(ret, line, putobject, node->nd_lit);
8000 VALUE lit = node->nd_lit;
8001 if (!ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal) {
8023 compile_dstr(
iseq, ret, node);
8029 if (ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal) {
8034 ADD_INSN1(ret, line, freezestring, debug_info);
8035 if (!
NIL_P(debug_info)) {
8056 compile_dstr(
iseq, ret, node);
8065 CHECK(compile_evstr(
iseq, ret, node->nd_body, popped));
8068 compile_dregx(
iseq, ret, node);
8076 int ic_index = body->
is_size++;
8078 block_iseq =
NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(
iseq), ISEQ_TYPE_PLAIN, line);
8109 CHECK(
COMPILE_(ret,
"argspush body", node->nd_body, popped));
8113 CHECK(
COMPILE_(ret,
"argspush body", node->nd_body, popped));
8129 ID mid = node->nd_mid;
8132 ISEQ_TYPE_METHOD, line);
8145 ID mid = node->nd_mid;
8148 ISEQ_TYPE_METHOD, line);
8152 ADD_INSN2(ret, line, definesmethod,
ID2SYM(mid), singleton_method_iseq);
8197 ISEQ_TYPE_CLASS, line);
8200 compile_cpath(ret,
iseq, node->nd_cpath);
8214 ISEQ_TYPE_CLASS, line);
8216 compile_cpath(ret,
iseq, node->nd_cpath);
8230 ISEQ_TYPE_CLASS, line);
8234 CONST_ID(singletonclass,
"singletonclass");
8236 ID2SYM(singletonclass), singleton_class,
8249 int ic_index = body->
is_size++;
8256 CHECK(compile_const_prefix(
iseq, node, pref, body));
8257 if (LIST_INSN_SIZE_ZERO(pref)) {
8258 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
8267 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
8290 int ic_index = body->
is_size++;
8292 debugi(
"colon3#nd_mid", node->nd_mid);
8295 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
8304 if (ISEQ_COMPILE_DATA(
iseq)->option->inline_const_cache) {
8318 const NODE *b = node->nd_beg;
8319 const NODE *e = node->nd_end;
8320 if (number_literal_p(b) && number_literal_p(e)) {
8377 if (body->
type == ISEQ_TYPE_RESCUE) {
8384 if (ip->
body->
type == ISEQ_TYPE_RESCUE) {
8409 int is_index = body->
is_size++;
8411 rb_iseq_new_with_callback_new_callback(build_postexe_iseq, node->nd_body);
8413 new_child_iseq_with_callback(
iseq, ifunc,
8427 const NODE *default_value = node->nd_body->nd_value;
8450 ADD_INSNL(ret, line, branchif, end_label);
8458 compile_dstr(
iseq, ret, node);
8470 unsigned int flag = 0;
8471 ID mid = node->nd_mid;
8479 if (mid ==
idASET && !private_recv_p(node) && node->nd_args &&
8482 ISEQ_COMPILE_DATA(
iseq)->current_block ==
NULL &&
8483 !ISEQ_COMPILE_DATA(
iseq)->option->frozen_string_literal &&
8484 ISEQ_COMPILE_DATA(
iseq)->option->specialized_instruction)
8488 CHECK(
COMPILE(ret,
"value", node->nd_args->nd_next->nd_head));
8502 argc = setup_args(
iseq, args, node->nd_args, &flag,
NULL);
8506 CHECK(asgnflag != -1);
8507 flag |= (
unsigned int)asgnflag;
8515 else_label = qcall_branch_start(
iseq, recv, &branches, node, line);
8547 qcall_branch_end(
iseq, ret, else_label, branches, node, line);
8582 insn_data_length(
INSN *iobj)
8584 return insn_len(iobj->
insn_id);
8588 calc_sp_depth(
int depth,
INSN *insn)
8590 return comptime_insn_stack_increase(depth, insn->
insn_id, insn->
operands);
8596 struct RBasic *r = (
struct RBasic *)
obj;
8613 insn_data_to_s_detail(
INSN *iobj)
8621 for (j = 0;
types[j]; j++) {
8681 if (dladdr(func, &info) && info.dli_sname) {
8690 rb_bug(
"unsupported: TS_BUILTIN");
8718 printf(
"-- raw disasm--------\n");
8722 switch (
link->type) {
8723 case ISEQ_ELEMENT_INSN:
8726 str = insn_data_to_s_detail(iobj);
8728 pos += insn_data_length(iobj);
8731 case ISEQ_ELEMENT_LABEL:
8735 dest == lobj ?
" <---" :
"");
8738 case ISEQ_ELEMENT_TRACE:
8744 case ISEQ_ELEMENT_ADJUST:
8756 printf(
"---------------------\n");
8763 return insn_name(
i);
8789 label = (
LABEL *)tmp;
8799 #define rb_intern(str) rb_intern_const(str)
8800 static VALUE symRescue, symEnsure, symRetry;
8801 static VALUE symBreak, symRedo, symNext;
8803 if (symRescue == 0) {
8812 if (
sym == symRescue)
return CATCH_TYPE_RESCUE;
8813 if (
sym == symEnsure)
return CATCH_TYPE_ENSURE;
8814 if (
sym == symRetry)
return CATCH_TYPE_RETRY;
8815 if (
sym == symBreak)
return CATCH_TYPE_BREAK;
8816 if (
sym == symRedo)
return CATCH_TYPE_REDO;
8817 if (
sym == symNext)
return CATCH_TYPE_NEXT;
8831 LABEL *lstart, *lend, *lcont;
8852 if (
type == CATCH_TYPE_RESCUE ||
8853 type == CATCH_TYPE_BREAK ||
8854 type == CATCH_TYPE_NEXT) {
8868 insn_make_insn_table(
void)
8906 unsigned int flag = 0;
8917 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
8919 if (!
NIL_P(vkw_arg)) {
8922 size_t n = rb_call_info_kw_arg_bytes(
len);
8926 for (
i = 0;
i <
len;
i++) {
8940 #define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern(#ev))) return ev;
8966 static struct st_table *insn_table;
8968 if (insn_table == 0) {
8969 insn_table = insn_make_insn_table();
8981 LABEL *label = register_label(
iseq, labels_table,
obj);
8998 "unknown instruction: %+"PRIsVALUE, insn);
9003 if (
argc != insn_len((
VALUE)insn_id)-1) {
9005 "operand size mismatch");
9012 for (j=0; j<
argc; j++) {
9014 switch (insn_op_type((
VALUE)insn_id, j)) {
9016 LABEL *label = register_label(
iseq, labels_table, op);
9056 argv[j] = iseq_build_callinfo_from_hash(
iseq, op);
9072 register_label(
iseq, labels_table,
sym);
9082 #if SIZEOF_VALUE <= SIZEOF_LONG
9104 validate_labels(
iseq, labels_table);
9105 if (!ret)
return ret;
9106 return iseq_setup(
iseq, anchor);
9109 #define CHECK_ARRAY(v) rb_to_array_type(v)
9110 #define CHECK_SYMBOL(v) rb_to_symbol_type(v)
9120 else if (!
NIL_P(val)) {
9127 static const struct rb_iseq_param_keyword *
9136 struct rb_iseq_param_keyword *keyword =
ZALLOC(
struct rb_iseq_param_keyword);
9141 #define SYM(s) ID2SYM(rb_intern(#s))
9142 (
void)int_param(&keyword->bits_start, params,
SYM(kwbits));
9143 i = keyword->bits_start - keyword->num;
9148 for (
i = 0;
i <
len;
i++) {
9152 goto default_values;
9155 keyword->required_num++;
9159 default_len =
len -
i;
9160 if (default_len == 0) {
9161 keyword->table = ids;
9164 else if (default_len < 0) {
9170 for (j = 0;
i <
len;
i++, j++) {
9187 dvs[j] = default_val;
9190 keyword->table = ids;
9191 keyword->default_values = dvs;
9201 unsigned int pos = 0;
9204 #ifdef STRICT_ALIGNMENT
9205 size_t padding = calc_padding((
void *)&storage->
buff[pos],
size);
9207 const size_t padding = 0;
9209 size_t offset = pos +
size + padding;
9210 if (offset > storage->
size || offset > storage->
pos) {
9212 storage = storage->
next;
9215 #ifdef STRICT_ALIGNMENT
9216 pos += (
int)padding;
9219 iobj = (
INSN *)&storage->
buff[pos];
9225 for (j = 0;
types[j]; j++) {
9252 #define SYM(s) ID2SYM(rb_intern(#s))
9254 unsigned int arg_size,
local_size, stack_max;
9268 for (
i = 0;
i <
len;
i++) {
9271 if (sym_arg_rest == lv) {
9279 #define INT_PARAM(F) int_param(&iseq->body->param.F, params, SYM(F))
9289 #define INT_PARAM(F) F = (int_param(&x, misc, SYM(F)) ? (unsigned int)x : 0)
9304 for (
i = 0;
i <
len;
i++) {
9306 LABEL *label = register_label(
iseq, labels_table, ent);
9307 opt_table[
i] = (
VALUE)label;
9314 else if (!
NIL_P(arg_opt_labels)) {
9322 else if (!
NIL_P(keywords)) {
9331 if (int_param(&
i, params,
SYM(kwrest))) {
9332 struct rb_iseq_param_keyword *keyword = (
struct rb_iseq_param_keyword *)
iseq->
body->
param.
keyword;
9336 keyword->rest_start =
i;
9340 iseq_calc_param_size(
iseq);
9343 iseq_build_from_ary_exception(
iseq, labels_table, exception);
9346 iseq_build_from_ary_body(
iseq, anchor, body, labels_wrapper);
9433 rb_iseq_new_with_callback_new_callback(build, &acc);
9443 const int line = args->
line;
9446 iseq_set_local_table(
iseq, 0);
9458 const int line = args->
line;
9478 return method_for_self(
name,
arg, func, for_self_aref);
9487 return method_for_self(
name,
arg, func, for_self_aset);
9492 #ifndef IBF_ISEQ_DEBUG
9493 #define IBF_ISEQ_DEBUG 0
9496 #ifndef IBF_ISEQ_ENABLE_LOCAL_BUFFER
9497 #define IBF_ISEQ_ENABLE_LOCAL_BUFFER 0
9501 #define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
9503 #define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
9505 #define IBF_DEVEL_VERSION 2
9506 #define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
9508 #define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
9558 ibf_dump_pos(
struct ibf_dump *dump)
9561 #if SIZEOF_LONG > SIZEOF_INT
9566 return (
unsigned int)pos;
9570 ibf_dump_align(
struct ibf_dump *dump,
size_t align)
9574 static const char padding[
sizeof(
VALUE)];
9576 #if SIZEOF_LONG > SIZEOF_INT
9581 for (;
size >
sizeof(padding);
size -=
sizeof(padding)) {
9589 ibf_dump_write(
struct ibf_dump *dump,
const void *
buff,
unsigned long size)
9598 ibf_dump_write_byte(
struct ibf_dump *dump,
unsigned char byte)
9600 return ibf_dump_write(dump, &
byte,
sizeof(
unsigned char));
9604 ibf_dump_overwrite(
struct ibf_dump *dump,
void *
buff,
unsigned int size,
long offset)
9609 rb_bug(
"ibf_dump_overwrite: overflow");
9625 size_t size = x * y;
9630 #define IBF_W_ALIGN(type) (RUBY_ALIGNOF(type) > 1 ? ibf_dump_align(dump, RUBY_ALIGNOF(type)) : (void)0)
9632 #define IBF_W(b, type, n) (IBF_W_ALIGN(type), (type *)(VALUE)IBF_WP(b, type, n))
9633 #define IBF_WV(variable) ibf_dump_write(dump, &(variable), sizeof(variable))
9634 #define IBF_WP(b, type, n) ibf_dump_write(dump, (b), sizeof(type) * (n))
9635 #define IBF_R(val, type, n) (type *)ibf_load_alloc(load, IBF_OFFSET(val), sizeof(type), (n))
9636 #define IBF_ZERO(variable) memset(&(variable), 0, sizeof(variable))
9654 int index = ibf_table_lookup(table,
key);
9672 ibf_dump_object_list_new(
void)
9699 return ibf_dump_object(dump,
rb_id2sym(
id));
9703 ibf_load_id(
const struct ibf_load *load,
const ID id_index)
9705 if (id_index == 0) {
9708 VALUE sym = ibf_load_object(load, id_index);
9730 if (iseq_index < 0) {
9741 return (
VALUE)ibf_dump_id(dump, entry->
id);
9747 ID gid = ibf_load_id(load, (
ID)(
VALUE)entry);
9751 static unsigned char
9772 ibf_dump_write(dump, &x,
sizeof(
VALUE));
9775 enum { max_byte_length =
sizeof(
VALUE) + 1 };
9777 unsigned char bytes[max_byte_length];
9780 for (
n = 0;
n <
sizeof(
VALUE) && (x >> (7 -
n));
n++, x >>= 8) {
9781 bytes[max_byte_length - 1 -
n] = (
unsigned char)x;
9787 bytes[max_byte_length - 1 -
n] = (
unsigned char)x;
9790 ibf_dump_write(dump, bytes + max_byte_length -
n,
n);
9800 *offset +=
sizeof(
VALUE);
9805 enum { max_byte_length =
sizeof(
VALUE) + 1 };
9808 const unsigned char c = buffer[*offset];
9812 c == 0 ? 9 : ntz_int32(c) + 1;
9820 for (
i = 1;
i <
n;
i++) {
9822 x |= (
VALUE)buffer[*offset +
i];
9836 ibf_dump_write_small_value(dump, (
VALUE)bf->
index);
9839 ibf_dump_write_small_value(dump, (
VALUE)
len);
9840 ibf_dump_write(dump, bf->
name,
len);
9846 int i = (
int)ibf_load_small_value(load, offset);
9847 int len = (
int)ibf_load_small_value(load, offset);
9848 const char *
name = (
char *)ibf_load_ptr(load, offset,
len);
9875 for (code_index=0; code_index<
iseq_size;) {
9876 const VALUE insn = orig_code[code_index++];
9877 const char *
types = insn_op_types(insn);
9882 ibf_dump_write_small_value(dump, insn);
9885 for (op_index=0;
types[op_index]; op_index++, code_index++) {
9886 VALUE op = orig_code[code_index];
9889 switch (
types[op_index]) {
9892 wv = ibf_dump_object(dump, op);
9914 ibf_dump_write_byte(dump, c);
9918 wv = ibf_dump_id(dump, (
ID)op);
9933 ibf_dump_write_small_value(dump, wv);
9936 assert(insn_len(insn) == op_index+1);
9945 unsigned int code_index;
9954 for (code_index=0; code_index<iseq_size;) {
9956 const VALUE insn = code[code_index++] = ibf_load_small_value(load, &reading_pos);
9957 const char *
types = insn_op_types(insn);
9961 for (op_index=0;
types[op_index]; op_index++, code_index++) {
9962 switch (
types[op_index]) {
9966 VALUE op = ibf_load_small_value(load, &reading_pos);
9967 VALUE v = ibf_load_object(load, op);
9968 code[code_index] =
v;
9977 VALUE op = (
VALUE)ibf_load_small_value(load, &reading_pos);
9979 code[code_index] =
v;
9992 VALUE op = ibf_load_small_value(load, &reading_pos);
9993 code[code_index] = (
VALUE)&is_entries[op];
9998 unsigned char op = ibf_load_byte(load, &reading_pos);
9999 code[code_index] = op ? (
VALUE)cd_kw_entries++ : (
VALUE)cd_entries++;
10004 VALUE op = ibf_load_small_value(load, &reading_pos);
10005 code[code_index] = ibf_load_id(load, (
ID)(
VALUE)op);
10010 VALUE op = ibf_load_small_value(load, &reading_pos);
10018 code[code_index] = (
VALUE)ibf_load_builtin(load, &reading_pos);
10021 code[code_index] = ibf_load_small_value(load, &reading_pos);
10025 if (insn_len(insn) != op_index+1) {
10032 assert(code_index == iseq_size);
10033 assert(reading_pos == bytecode_offset + bytecode_size);
10047 return ibf_dump_pos(dump);
10052 ibf_load_param_opt_table(
const struct ibf_load *load,
ibf_offset_t opt_table_offset,
int opt_num)
10070 struct rb_iseq_param_keyword dump_kw = *kw;
10071 int dv_num = kw->num - kw->required_num;
10076 for (
i=0;
i<kw->num;
i++) ids[
i] = (
ID)ibf_dump_id(dump, kw->table[
i]);
10077 for (
i=0;
i<dv_num;
i++) dvs[
i] = (
VALUE)ibf_dump_object(dump, kw->default_values[
i]);
10079 dump_kw.table =
IBF_W(ids,
ID, kw->num);
10080 dump_kw.default_values =
IBF_W(dvs,
VALUE, dv_num);
10082 return ibf_dump_write(dump, &dump_kw,
sizeof(
struct rb_iseq_param_keyword) * 1);
10089 static const struct rb_iseq_param_keyword *
10092 if (param_keyword_offset) {
10093 struct rb_iseq_param_keyword *kw =
IBF_R(param_keyword_offset,
struct rb_iseq_param_keyword, 1);
10094 ID *ids =
IBF_R(kw->table,
ID, kw->num);
10095 int dv_num = kw->num - kw->required_num;
10099 for (
i=0;
i<kw->num;
i++) {
10100 ids[
i] = ibf_load_id(load, ids[
i]);
10102 for (
i=0;
i<dv_num;
i++) {
10103 dvs[
i] = ibf_load_object(load, dvs[
i]);
10107 kw->default_values = dvs;
10138 entries[
i].line_no = (
int)ibf_load_small_value(load, &reading_pos);
10146 ibf_dump_insns_info_positions(
struct ibf_dump *dump,
const unsigned int *positions,
unsigned int size)
10150 unsigned int last = 0;
10153 ibf_dump_write_small_value(dump, positions[
i] -
last);
10154 last = positions[
i];
10160 static unsigned int *
10164 unsigned int *positions =
ALLOC_N(
unsigned int,
size);
10166 unsigned int last = 0;
10169 positions[
i] =
last + (
unsigned int)ibf_load_small_value(load, &reading_pos);
10170 last = positions[
i];
10189 return ibf_dump_write(dump,
table,
sizeof(
ID) *
size);
10218 for (
i=0;
i<table->
size;
i++) {
10219 iseq_indices[
i] = ibf_dump_iseq(dump, table->
entries[
i].
iseq);
10224 for (
i=0;
i<table->
size;
i++) {
10225 ibf_dump_write_small_value(dump, iseq_indices[
i]);
10226 ibf_dump_write_small_value(dump, table->
entries[
i].
type);
10228 ibf_dump_write_small_value(dump, table->
entries[
i].
end);
10229 ibf_dump_write_small_value(dump, table->
entries[
i].
cont);
10230 ibf_dump_write_small_value(dump, table->
entries[
i].
sp);
10235 return ibf_dump_pos(dump);
10249 for (
i=0;
i<table->
size;
i++) {
10250 int iseq_index = (
int)ibf_load_small_value(load, &reading_pos);
10251 table->
entries[
i].
type = (
enum catch_type)ibf_load_small_value(load, &reading_pos);
10252 table->
entries[
i].
start = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10253 table->
entries[
i].
end = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10254 table->
entries[
i].
cont = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10255 table->
entries[
i].
sp = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10279 for (
i = 0;
i < ci_size;
i++) {
10280 VALUE mid = ibf_dump_id(dump, calls[
i].
ci.mid);
10282 ibf_dump_write_small_value(dump, mid);
10283 ibf_dump_write_small_value(dump, calls[
i].
ci.flag);
10284 ibf_dump_write_small_value(dump, calls[
i].
ci.orig_argc);
10287 for (
i = 0;
i < ci_kw_size;
i++) {
10290 VALUE mid = ibf_dump_id(dump, kw_calls[
i].ci_kw.ci.mid);
10292 ibf_dump_write_small_value(dump, mid);
10293 ibf_dump_write_small_value(dump, kw_calls[
i].ci_kw.ci.flag);
10294 ibf_dump_write_small_value(dump, kw_calls[
i].ci_kw.ci.orig_argc);
10296 ibf_dump_write_small_value(dump, kw_arg->
keyword_len);
10300 VALUE keyword = ibf_dump_object(dump, kw_arg->
keywords[j]);
10302 ibf_dump_write_small_value(dump, keyword);
10311 ibf_load_ci_entries(
const struct ibf_load *load,
10313 unsigned int ci_size,
10314 unsigned int ci_kw_size)
10326 for (
i = 0;
i < ci_size;
i++) {
10327 VALUE mid_index = ibf_load_small_value(load, &reading_pos);
10329 calls[
i].
ci.
mid = ibf_load_id(load, mid_index);
10330 calls[
i].
ci.
flag = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10331 calls[
i].
ci.
orig_argc = (
int)ibf_load_small_value(load, &reading_pos);
10334 for (
i = 0;
i < ci_kw_size;
i++) {
10335 VALUE mid_index = ibf_load_small_value(load, &reading_pos);
10337 kw_calls[
i].
ci_kw.
ci.
mid = ibf_load_id(load, mid_index);
10338 kw_calls[
i].
ci_kw.
ci.
flag = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10341 int keyword_len = (
int)ibf_load_small_value(load, &reading_pos);
10350 VALUE keyword = ibf_load_small_value(load, &reading_pos);
10364 unsigned int *positions;
10372 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10378 buffer.obj_list = ibf_dump_object_list_new();
10383 const ibf_offset_t bytecode_size = ibf_dump_pos(dump) - bytecode_offset;
10384 const ibf_offset_t param_opt_table_offset = ibf_dump_param_opt_table(dump,
iseq);
10385 const ibf_offset_t param_keyword_offset = ibf_dump_param_keyword(dump,
iseq);
10386 const ibf_offset_t insns_info_body_offset = ibf_dump_insns_info_body(dump,
iseq);
10399 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10401 unsigned int local_obj_list_size;
10403 ibf_dump_object_list(dump, &local_obj_list_offset, &local_obj_list_size);
10409 unsigned int param_flags =
10421 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10422 # define IBF_BODY_OFFSET(x) (x)
10424 # define IBF_BODY_OFFSET(x) (body_offset - (x))
10427 ibf_dump_write_small_value(dump, body->
type);
10428 ibf_dump_write_small_value(dump, body->
iseq_size);
10430 ibf_dump_write_small_value(dump, bytecode_size);
10431 ibf_dump_write_small_value(dump, param_flags);
10432 ibf_dump_write_small_value(dump, body->
param.
size);
10434 ibf_dump_write_small_value(dump, body->
param.
opt_num);
10439 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(param_opt_table_offset));
10440 ibf_dump_write_small_value(dump, param_keyword_offset);
10441 ibf_dump_write_small_value(dump, location_pathobj_index);
10442 ibf_dump_write_small_value(dump, location_base_label_index);
10443 ibf_dump_write_small_value(dump, location_label_index);
10450 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(insns_info_body_offset));
10451 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(insns_info_positions_offset));
10453 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(local_table_offset));
10454 ibf_dump_write_small_value(dump, catch_table_size);
10455 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(catch_table_offset));
10456 ibf_dump_write_small_value(dump, parent_iseq_index);
10457 ibf_dump_write_small_value(dump, local_iseq_index);
10458 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(ci_entries_offset));
10461 ibf_dump_write_small_value(dump, body->
is_size);
10462 ibf_dump_write_small_value(dump, body->
ci_size);
10463 ibf_dump_write_small_value(dump, body->
ci_kw_size);
10464 ibf_dump_write_small_value(dump, body->
stack_max);
10467 #undef IBF_BODY_OFFSET
10469 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10473 ibf_dump_write(dump,
RSTRING_PTR(buffer.str), iseq_length_bytes);
10476 ibf_dump_write_small_value(dump, iseq_start);
10477 ibf_dump_write_small_value(dump, iseq_length_bytes);
10478 ibf_dump_write_small_value(dump, body_offset);
10480 ibf_dump_write_small_value(dump, local_obj_list_offset);
10481 ibf_dump_write_small_value(dump, local_obj_list_size);
10485 return body_offset;
10490 ibf_load_location_str(
const struct ibf_load *load,
VALUE str_index)
10492 VALUE str = ibf_load_object(load, str_index);
10506 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10510 const ibf_offset_t iseq_start = ibf_load_small_value(load, &reading_pos);
10511 const ibf_offset_t iseq_length_bytes = ibf_load_small_value(load, &reading_pos);
10512 const ibf_offset_t body_offset = ibf_load_small_value(load, &reading_pos);
10516 buffer.size = iseq_length_bytes;
10517 buffer.obj_list_offset = ibf_load_small_value(load, &reading_pos);
10518 buffer.obj_list_size = ibf_load_small_value(load, &reading_pos);
10523 reading_pos = body_offset;
10526 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10527 # define IBF_BODY_OFFSET(x) (x)
10529 # define IBF_BODY_OFFSET(x) (offset - (x))
10532 const unsigned int type = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10533 const unsigned int iseq_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10536 const unsigned int param_flags = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10537 const unsigned int param_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10538 const int param_lead_num = (
int)ibf_load_small_value(load, &reading_pos);
10539 const int param_opt_num = (
int)ibf_load_small_value(load, &reading_pos);
10540 const int param_rest_start = (
int)ibf_load_small_value(load, &reading_pos);
10541 const int param_post_start = (
int)ibf_load_small_value(load, &reading_pos);
10542 const int param_post_num = (
int)ibf_load_small_value(load, &reading_pos);
10543 const int param_block_start = (
int)ibf_load_small_value(load, &reading_pos);
10546 const VALUE location_pathobj_index = ibf_load_small_value(load, &reading_pos);
10547 const VALUE location_base_label_index = ibf_load_small_value(load, &reading_pos);
10548 const VALUE location_label_index = ibf_load_small_value(load, &reading_pos);
10549 const VALUE location_first_lineno = ibf_load_small_value(load, &reading_pos);
10550 const int location_node_id = (
int)ibf_load_small_value(load, &reading_pos);
10551 const int location_code_location_beg_pos_lineno = (
int)ibf_load_small_value(load, &reading_pos);
10552 const int location_code_location_beg_pos_column = (
int)ibf_load_small_value(load, &reading_pos);
10553 const int location_code_location_end_pos_lineno = (
int)ibf_load_small_value(load, &reading_pos);
10554 const int location_code_location_end_pos_column = (
int)ibf_load_small_value(load, &reading_pos);
10557 const unsigned int insns_info_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10559 const unsigned int catch_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10561 const int parent_iseq_index = (
int)ibf_load_small_value(load, &reading_pos);
10562 const int local_iseq_index = (
int)ibf_load_small_value(load, &reading_pos);
10564 const rb_snum_t variable_flip_count = (
rb_snum_t)ibf_load_small_value(load, &reading_pos);
10565 const unsigned int local_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10566 const unsigned int is_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10567 const unsigned int ci_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10568 const unsigned int ci_kw_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10569 const unsigned int stack_max = (
unsigned int)ibf_load_small_value(load, &reading_pos);
10570 const char catch_except_p = (
char)ibf_load_small_value(load, &reading_pos);
10572 #undef IBF_BODY_OFFSET
10576 load_body->
param.
flags.has_lead = (param_flags >> 0) & 1;
10577 load_body->
param.
flags.has_opt = (param_flags >> 1) & 1;
10578 load_body->
param.
flags.has_rest = (param_flags >> 2) & 1;
10579 load_body->
param.
flags.has_post = (param_flags >> 3) & 1;
10581 load_body->
param.
flags.has_kwrest = (param_flags >> 5) & 1;
10582 load_body->
param.
flags.has_block = (param_flags >> 6) & 1;
10583 load_body->
param.
flags.ambiguous_param0 = (param_flags >> 7) & 1;
10584 load_body->
param.
flags.accepts_no_kwarg = (param_flags >> 8) & 1;
10585 load_body->
param.
flags.ruby2_keywords = (param_flags >> 9) & 1;
10594 load_body->
is_size = is_size;
10595 load_body->
ci_size = ci_size;
10600 ISEQ_ORIGINAL_ISEQ_CLEAR(
iseq);
10612 load_body->
call_data = ibf_load_ci_entries(load, ci_entries_offset, ci_size, ci_kw_size);
10613 load_body->
param.
opt_table = ibf_load_param_opt_table(load, param_opt_table_offset, param_opt_num);
10614 load_body->
param.
keyword = ibf_load_param_keyword(load, param_keyword_offset);
10615 load_body->
param.
flags.has_kw = (param_flags >> 4) & 1;
10616 load_body->
insns_info.
body = ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size);
10617 load_body->
insns_info.
positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size);
10618 load_body->
local_table = ibf_load_local_table(load, local_table_offset, local_table_size);
10619 load_body->
catch_table = ibf_load_catch_table(load, catch_table_offset, catch_table_size);
10623 ibf_load_code(load,
iseq, bytecode_offset, bytecode_size, iseq_size);
10624 #if VM_INSN_INFO_TABLE_IMPL == 2
10628 rb_iseq_translate_threaded_code(
iseq);
10630 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10664 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10667 verify_call_cache(
iseq);
10693 #define IBF_OBJECT_INTERNAL FL_PROMOTED0
10705 unsigned int internal: 1;
10751 #define IBF_ALIGNED_OFFSET(align, offset) \
10752 ((((offset) - 1) / (align) + 1) * (align))
10753 #define IBF_OBJBODY(type, offset) (const type *)\
10754 ibf_load_check_offset(load, IBF_ALIGNED_OFFSET(RUBY_ALIGNOF(type), offset))
10756 static const void *
10757 ibf_load_check_offset(
const struct ibf_load *load,
size_t offset)
10804 rb_bug(
"unsupported class");
10806 ibf_dump_write_small_value(dump, (
VALUE)cindex);
10841 const double *dblp =
IBF_OBJBODY(
double, offset);
10858 ibf_dump_write_small_value(dump, encindex);
10859 ibf_dump_write_small_value(dump,
len);
10868 int encindex = (
int)ibf_load_small_value(load, &reading_pos);
10869 const long len = (
long)ibf_load_small_value(load, &reading_pos);
10892 regexp.srcstr = (
long)ibf_dump_object(dump,
srcstr);
10894 ibf_dump_write_byte(dump, (
unsigned char)regexp.option);
10895 ibf_dump_write_small_value(dump, regexp.srcstr);
10902 regexp.
option = ibf_load_byte(load, &offset);
10903 regexp.srcstr = ibf_load_small_value(load, &offset);
10905 VALUE srcstr = ibf_load_object(load, regexp.srcstr);
10918 ibf_dump_write_small_value(dump,
len);
10921 ibf_dump_write_small_value(dump,
index);
10930 const long len = (
long)ibf_load_small_value(load, &reading_pos);
10936 const VALUE index = ibf_load_small_value(load, &reading_pos);
10952 VALUE val_index = ibf_dump_object(dump, (
VALUE)val);
10954 ibf_dump_write_small_value(dump, key_index);
10955 ibf_dump_write_small_value(dump, val_index);
10963 ibf_dump_write_small_value(dump, (
VALUE)
len);
10971 long len = (
long)ibf_load_small_value(load, &offset);
10975 for (
i = 0;
i <
len;
i++) {
10976 VALUE key_index = ibf_load_small_value(load, &offset);
10977 VALUE val_index = ibf_load_small_value(load, &offset);
10979 VALUE key = ibf_load_object(load, key_index);
10980 VALUE val = ibf_load_object(load, val_index);
10999 range.class_index = 0;
11041 int sign = bignum->
slen > 0;
11064 ibf_dump_object_unsupported(dump,
obj);
11074 const char *data = (
const char *)&body[2];
11084 return ibf_load_object_unsupported(load, header, offset);
11101 VALUE a = ibf_load_object(load, nums->
a);
11102 VALUE b = ibf_load_object(load, nums->
b);
11115 VALUE str_index = ibf_dump_object(dump,
str);
11117 ibf_dump_write_small_value(dump, str_index);
11123 VALUE str_index = ibf_load_small_value(load, &offset);
11124 VALUE str = ibf_load_object(load, str_index);
11131 ibf_dump_object_unsupported,
11132 ibf_dump_object_unsupported,
11133 ibf_dump_object_class,
11134 ibf_dump_object_unsupported,
11135 ibf_dump_object_float,
11136 ibf_dump_object_string,
11137 ibf_dump_object_regexp,
11138 ibf_dump_object_array,
11139 ibf_dump_object_hash,
11140 ibf_dump_object_struct,
11141 ibf_dump_object_bignum,
11142 ibf_dump_object_unsupported,
11143 ibf_dump_object_data,
11144 ibf_dump_object_unsupported,
11145 ibf_dump_object_complex_rational,
11146 ibf_dump_object_complex_rational,
11147 ibf_dump_object_unsupported,
11148 ibf_dump_object_unsupported,
11149 ibf_dump_object_unsupported,
11150 ibf_dump_object_unsupported,
11151 ibf_dump_object_symbol,
11152 ibf_dump_object_unsupported,
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,
11168 unsigned char byte =
11169 (header.
type << 0) |
11180 unsigned char byte = ibf_load_byte(load, offset);
11183 header.
type = (
byte >> 0) & 0x1f;
11185 header.
frozen = (
byte >> 6) & 0x01;
11186 header.
internal = (
byte >> 7) & 0x01;
11200 current_offset = ibf_dump_pos(dump);
11205 obj_header.internal =
FALSE;
11208 obj_header.special_const =
TRUE;
11209 obj_header.frozen =
TRUE;
11210 obj_header.internal =
TRUE;
11211 ibf_dump_object_object_header(dump, obj_header);
11212 ibf_dump_write_small_value(dump,
obj);
11217 obj_header.special_const =
FALSE;
11219 ibf_dump_object_object_header(dump, obj_header);
11220 (*dump_object_functions[obj_header.type])(dump,
obj);
11223 return current_offset;
11228 ibf_load_object_unsupported,
11229 ibf_load_object_unsupported,
11230 ibf_load_object_class,
11231 ibf_load_object_unsupported,
11232 ibf_load_object_float,
11233 ibf_load_object_string,
11234 ibf_load_object_regexp,
11235 ibf_load_object_array,
11236 ibf_load_object_hash,
11237 ibf_load_object_struct,
11238 ibf_load_object_bignum,
11239 ibf_load_object_unsupported,
11240 ibf_load_object_data,
11241 ibf_load_object_unsupported,
11242 ibf_load_object_complex_rational,
11243 ibf_load_object_complex_rational,
11244 ibf_load_object_unsupported,
11245 ibf_load_object_unsupported,
11246 ibf_load_object_unsupported,
11247 ibf_load_object_unsupported,
11248 ibf_load_object_symbol,
11249 ibf_load_object_unsupported,
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,
11263 ibf_load_object(
const struct ibf_load *load,
VALUE object_index)
11265 if (object_index == 0) {
11276 const struct ibf_object_header header = ibf_load_object_object_header(load, &offset);
11279 fprintf(
stderr,
"ibf_load_object: list=%#x offsets=%p offset=%#x\n",
11281 fprintf(
stderr,
"ibf_load_object: type=%#x special=%d frozen=%d internal=%d\n",
11291 obj = ibf_load_small_value(load, &reading_pos);
11294 obj = (*load_object_functions[header.
type])(load, &header, offset);
11301 object_index,
obj);
11308 ibf_dump_object_list(
struct ibf_dump *dump,
ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size)
11321 *obj_list_offset = ibf_dump_pos(dump);
11328 *obj_list_size =
size;
11332 ibf_dump_mark(
void *
ptr)
11341 ibf_dump_free(
void *
ptr)
11352 ibf_dump_memsize(
const void *
ptr)
11355 size_t size =
sizeof(*dump);
11362 {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
11394 ibf_dump_setup(dump, dump_obj);
11396 ibf_dump_write(dump, &header,
sizeof(header));
11398 ibf_dump_iseq(dump,
iseq);
11400 header.
magic[0] =
'Y';
11401 header.
magic[1] =
'A';
11402 header.
magic[2] =
'R';
11403 header.
magic[3] =
'B';
11406 ibf_dump_iseq_list(dump, &header);
11408 header.
size = ibf_dump_pos(dump);
11411 VALUE opt_str = opt;
11420 ibf_dump_overwrite(dump, &header,
sizeof(header), 0);
11423 ibf_dump_free(dump);
11430 ibf_iseq_list(
const struct ibf_load *load)
11443 fprintf(
stderr,
"rb_ibf_load_iseq_complete: index=%#x offset=%#x size=%#x\n",
11447 ibf_load_iseq_each(load,
iseq, offset);
11448 ISEQ_COMPILE_DATA_CLEAR(
iseq);
11451 load->
iseq = prev_src_iseq;
11466 int iseq_index = (
int)(
VALUE)index_iseq;
11469 fprintf(
stderr,
"ibf_load_iseq: index_iseq=%p iseq_list=%p\n",
11470 (
void *)index_iseq, (
void *)load->
iseq_list);
11472 if (iseq_index == -1) {
11479 fprintf(
stderr,
"ibf_load_iseq: iseqv=%p\n", (
void *)iseqv);
11481 if (iseqv !=
Qnil) {
11493 fprintf(
stderr,
"ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n",
11504 if (
GET_VM()->builtin_function_table) {
11511 (
void *)
iseq, (
void *)load->
iseq);
11534 if (size < load->header->size) {
11574 ibf_loader_mark(
void *
ptr)
11583 ibf_loader_free(
void *
ptr)
11590 ibf_loader_memsize(
const void *
ptr)
11597 {ibf_loader_mark, ibf_loader_free, ibf_loader_memsize,},
11609 iseq = ibf_load_iseq(load, 0);
11623 iseq = ibf_load_iseq(load, 0);