17 #define USE_INSN_STACK_INCREASE 1 21 #include "insns_info.inc" 29 #undef RUBY_UNTYPED_DATA_WARNING 30 #define RUBY_UNTYPED_DATA_WARNING 0 32 #define ISEQ_TYPE_ONCE_GUARD ISEQ_TYPE_DEFINED_GUARD 34 #define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG)) 35 #define FIXNUM_OR(n, i) ((n)|INT2FIX(i)) 74 enum ruby_vminsn_type insn_id;
117 #define compile_debug CPDEBUG 119 #define compile_debug ISEQ_COMPILE_DATA(iseq)->option->debug_level 124 #define compile_debug_print_indent(level) \ 125 ruby_debug_print_indent((level), compile_debug, gl_node_level * 2) 127 #define debugp(header, value) (void) \ 128 (compile_debug_print_indent(1) && \ 129 ruby_debug_print_value(1, compile_debug, (header), (value))) 131 #define debugi(header, id) (void) \ 132 (compile_debug_print_indent(1) && \ 133 ruby_debug_print_id(1, compile_debug, (header), (id))) 135 #define debugp_param(header, value) (void) \ 136 (compile_debug_print_indent(1) && \ 137 ruby_debug_print_value(1, compile_debug, (header), (value))) 139 #define debugp_verbose(header, value) (void) \ 140 (compile_debug_print_indent(2) && \ 141 ruby_debug_print_value(2, compile_debug, (header), (value))) 143 #define debugp_verbose_node(header, value) (void) \ 144 (compile_debug_print_indent(10) && \ 145 ruby_debug_print_value(10, compile_debug, (header), (value))) 147 #define debug_node_start(node) ((void) \ 148 (compile_debug_print_indent(1) && \ 149 (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)(node)), gl_node_level)), \ 152 #define debug_node_end() gl_node_level -- 168 #define debugi(header, id) r_id(id) 169 #define debugp(header, value) r_value(value) 170 #define debugp_verbose(header, value) r_value(value) 171 #define debugp_verbose_node(header, value) r_value(value) 172 #define debugp_param(header, value) r_value(value) 173 #define debug_node_start(node) ((void)0) 174 #define debug_node_end() ((void)0) 177 #if CPDEBUG > 1 || CPDEBUG < 0 178 #define printf ruby_debug_printf 179 #define debugs if (compile_debug_print_indent(1)) ruby_debug_printf 180 #define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v)) 182 #define debugs if(0)printf 183 #define debug_compile(msg, v) (v) 186 #define LVAR_ERRINFO (1) 189 #define NEW_LABEL(l) new_label_body(iseq, (l)) 191 #define iseq_path(iseq) ((iseq)->body->location.path) 192 #define iseq_absolute_path(iseq) ((iseq)->body->location.absolute_path) 194 #define NEW_ISEQ(node, name, type, line_no) \ 195 new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no)) 197 #define NEW_CHILD_ISEQ(node, name, type, line_no) \ 198 new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no)) 201 #define ADD_SEQ(seq1, seq2) \ 202 APPEND_LIST((seq1), (seq2)) 205 #define ADD_INSN(seq, line, insn) \ 206 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0)) 209 #define INSERT_BEFORE_INSN(prev, line, insn) \ 210 INSERT_ELEM_PREV(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0)) 213 #define ADD_INSN1(seq, line, insn, op1) \ 214 ADD_ELEM((seq), (LINK_ELEMENT *) \ 215 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1))) 218 #define INSERT_BEFORE_INSN1(prev, line, insn, op1) \ 219 INSERT_ELEM_PREV(&(prev)->link, (LINK_ELEMENT *) \ 220 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1))) 222 #define LABEL_REF(label) ((label)->refcnt++) 225 #define ADD_INSNL(seq, line, insn, label) (ADD_INSN1(seq, line, insn, label), LABEL_REF(label)) 227 #define ADD_INSN2(seq, line, insn, op1, op2) \ 228 ADD_ELEM((seq), (LINK_ELEMENT *) \ 229 new_insn_body(iseq, (line), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2))) 231 #define ADD_INSN3(seq, line, insn, op1, op2, op3) \ 232 ADD_ELEM((seq), (LINK_ELEMENT *) \ 233 new_insn_body(iseq, (line), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3))) 236 #define ADD_SEND(seq, line, id, argc) \ 237 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL) 239 #define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag) \ 240 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)(flag), NULL) 242 #define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block) \ 243 ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(0), NULL) 245 #define ADD_CALL_RECEIVER(seq, line) \ 246 ADD_INSN((seq), (line), putself) 248 #define ADD_CALL(seq, line, id, argc) \ 249 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL) 251 #define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \ 252 ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL) 254 #define ADD_SEND_R(seq, line, id, argc, block, flag, keywords) \ 255 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords))) 257 #define ADD_TRACE(seq, line, event) \ 259 if ((event) == RUBY_EVENT_LINE && ISEQ_COVERAGE(iseq) && \ 261 (line) != ISEQ_COMPILE_DATA(iseq)->last_coverable_line) { \ 262 RARRAY_ASET(ISEQ_COVERAGE(iseq), (line) - 1, INT2FIX(0)); \ 263 ISEQ_COMPILE_DATA(iseq)->last_coverable_line = (line); \ 264 ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \ 266 if (ISEQ_COMPILE_DATA(iseq)->option->trace_instruction) { \ 267 ADD_INSN1((seq), (line), trace, INT2FIX(event)); \ 271 #define ADD_GETLOCAL(seq, line, idx, level) \ 273 ADD_INSN2((seq), (line), getlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); \ 276 #define ADD_SETLOCAL(seq, line, idx, level) \ 278 ADD_INSN2((seq), (line), setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); \ 282 #define ADD_LABEL(seq, label) \ 283 ADD_ELEM((seq), (LINK_ELEMENT *) (label)) 285 #define APPEND_LABEL(seq, before, label) \ 286 APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label)) 288 #define ADD_ADJUST(seq, line, label) \ 289 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), (line))) 291 #define ADD_ADJUST_RESTORE(seq, label) \ 292 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1)) 294 #define LABEL_UNREMOVABLE(label) \ 295 ((label) ? (LABEL_REF(label), (label)->unremovable=1) : 0) 296 #define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \ 297 VALUE _e = rb_ary_new3(5, (type), \ 298 (VALUE)(ls) | 1, (VALUE)(le) | 1, \ 299 (VALUE)(iseqv), (VALUE)(lc) | 1); \ 300 LABEL_UNREMOVABLE(ls); \ 301 LABEL_UNREMOVABLE(le); \ 302 LABEL_UNREMOVABLE(lc); \ 303 rb_ary_push(ISEQ_COMPILE_DATA(iseq)->catch_table_ary, freeze_hide_obj(_e)); \ 307 #define COMPILE(anchor, desc, node) \ 308 (debug_compile("== " desc "\n", \ 309 iseq_compile_each(iseq, (anchor), (node), 0))) 312 #define COMPILE_POPPED(anchor, desc, node) \ 313 (debug_compile("== " desc "\n", \ 314 iseq_compile_each(iseq, (anchor), (node), 1))) 317 #define COMPILE_(anchor, desc, node, popped) \ 318 (debug_compile("== " desc "\n", \ 319 iseq_compile_each(iseq, (anchor), (node), (popped)))) 321 #define COMPILE_RECV(anchor, desc, node) \ 322 (private_recv_p(node) ? \ 323 (ADD_INSN(anchor, nd_line(node), putself), VM_CALL_FCALL) : \ 324 (COMPILE(anchor, desc, node->nd_recv), 0)) 326 #define OPERAND_AT(insn, idx) \ 327 (((INSN*)(insn))->operands[(idx)]) 329 #define INSN_OF(insn) \ 330 (((INSN*)(insn))->insn_id) 332 #define IS_INSN(link) ((link)->type == ISEQ_ELEMENT_INSN) 333 #define IS_LABEL(link) ((link)->type == ISEQ_ELEMENT_LABEL) 334 #define IS_ADJUST(link) ((link)->type == ISEQ_ELEMENT_ADJUST) 335 #define IS_INSN_ID(iobj, insn) (INSN_OF(iobj) == BIN(insn)) 351 if (
NIL_P(err_info)) {
376 #define COMPILE_ERROR prepare_compile_error(iseq) 378 #define ERROR_ARGS_AT(n) iseq, nd_line(n), 379 #define ERROR_ARGS ERROR_ARGS_AT(node) 381 #define EXPECT_NODE(prefix, node, ndtype) \ 383 NODE *error_node = (node); \ 384 enum node_type error_type = nd_type(error_node); \ 385 if (error_type != (ndtype)) { \ 386 compile_bug(ERROR_ARGS_AT(error_node) \ 387 prefix ": " #ndtype " is expected, but %s", \ 388 ruby_node_name(error_type)); \ 392 #define EXPECT_NODE_NONULL(prefix, parent, ndtype) \ 394 compile_bug(ERROR_ARGS_AT(parent) \ 395 prefix ": must be " #ndtype ", but 0"); \ 398 #define UNKNOWN_NODE(prefix, node) \ 400 NODE *error_node = (node); \ 401 compile_bug(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \ 402 ruby_node_name(nd_type(error_node))); \ 408 #define CHECK(sub) if (!(sub)) {BEFORE_RETURN;return COMPILE_NG;} 409 #define BEFORE_RETURN 413 #define DECL_ANCHOR(name) \ 414 LINK_ANCHOR name[1] = {{{0,},}} 415 #define INIT_ANCHOR(name) \ 416 (name->last = &name->anchor) 426 #include "optinsn.inc" 427 #if OPT_INSTRUCTIONS_UNIFICATION 428 #include "optunifs.inc" 433 #define ISEQ_ARG iseq, 434 #define ISEQ_ARG_DECLARE rb_iseq_t *iseq, 437 #define ISEQ_ARG_DECLARE 441 #define gl_node_level ISEQ_COMPILE_DATA(iseq)->node_level 483 if (plist != list->
prev) {
490 if (anchor->
last != plist && anchor->
last != 0) {
495 rb_bug(
"list verify error: %08x (%s)", flag, info);
500 #define verify_list(info, anchor) verify_list(iseq, (info), (anchor)) 509 elem->
prev = anchor->last;
510 anchor->last->
next = elem;
525 if (before == anchor->last) anchor->last = elem;
529 #define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem)) 530 #define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem)) 542 #define ruby_sourcefile RSTRING_PTR(iseq->body->location.path) 591 case ISEQ_TYPE_BLOCK:
610 case ISEQ_TYPE_CLASS:
617 case ISEQ_TYPE_METHOD:
633 (*ifunc->
func)(iseq, ret, ifunc->
data);
637 case ISEQ_TYPE_METHOD:
638 case ISEQ_TYPE_CLASS:
639 case ISEQ_TYPE_BLOCK:
646 case ISEQ_TYPE_RESCUE:
650 case ISEQ_TYPE_ENSURE:
654 case ISEQ_TYPE_DEFINED_GUARD:
663 if (iseq->
body->
type == ISEQ_TYPE_RESCUE || iseq->
body->
type == ISEQ_TYPE_ENSURE) {
684 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE 691 int len = insn_len(insn);
692 encoded[i] = (
VALUE)table[insn];
699 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE 701 rb_vm_insn_addr2insn(
const void *addr)
706 for (insn = 0; insn < VM_INSTRUCTION_SIZE; insn++) {
707 if (table[insn] == addr) {
711 rb_bug(
"rb_vm_insn_addr2insn: invalid insn address: %p", addr);
718 VALUE *original_code;
724 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE 729 const void *addr = (
const void *)original_code[i];
730 const int insn = rb_vm_insn_addr2insn(addr);
732 original_code[i] = insn;
737 return original_code;
750 #if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__) 751 #define STRICT_ALIGNMENT 754 #ifdef STRICT_ALIGNMENT 755 #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE 756 #define ALIGNMENT_SIZE SIZEOF_LONG_LONG 758 #define ALIGNMENT_SIZE SIZEOF_VALUE 760 #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1)) 761 #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX 764 #define PADDING_SIZE_MAX 0 767 #ifdef STRICT_ALIGNMENT 770 calc_padding(
void *ptr,
size_t size)
775 mis = (size_t)ptr & ALIGNMENT_SIZE_MASK;
777 padding = ALIGNMENT_SIZE - mis;
783 #if ALIGNMENT_SIZE > SIZEOF_VALUE 784 if (size ==
sizeof(
VALUE) && padding ==
sizeof(
VALUE)) {
799 #ifdef STRICT_ALIGNMENT 800 size_t padding = calc_padding((
void *)&storage->
buff[storage->
pos], size);
802 const size_t padding = 0;
806 if (storage->
pos + size + padding > storage->
size) {
807 unsigned int alloc_size = storage->
size;
818 storage->
size = alloc_size;
819 #ifdef STRICT_ALIGNMENT 820 padding = calc_padding((
void *)&storage->
buff[storage->
pos], size);
824 #ifdef STRICT_ALIGNMENT 825 storage->
pos += (int)padding;
828 ptr = (
void *)&storage->
buff[storage->
pos];
922 anchor->last = anchor->last->
prev;
923 anchor->last->
next = 0;
928 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor)) 955 anc1->last = anc2->
last;
960 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2)) 976 anc1->anchor.
next->
prev = &anc1->anchor;
982 anc1->last = anc2->
last;
989 #define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, (anc1), (anc2)) 998 printf(
"anch: %p, frst: %p, last: %p\n", &anchor->anchor,
999 anchor->anchor.next, anchor->last);
1001 printf(
"curr: %p, next: %p, prev: %p, type: %d\n", list, list->
next,
1011 #define debug_list(anc) debug_list(iseq, (anc)) 1038 adjust->
label = label;
1064 VALUE *operands = 0;
1070 for (i = 0; i <
argc; i++) {
1076 return new_insn_core(iseq, line_no, insn_id, argc, operands);
1088 ci->orig_argc = argc;
1092 ci_kw->kw_arg = kw_arg;
1101 kw_arg ==
NULL && !has_blockiseq) {
1113 operands[2] = (
VALUE)blockiseq;
1114 return new_insn_core(iseq, line_no, BIN(send), 3, operands);
1123 debugs(
"[new_child_iseq]> ---------------------------------------\n");
1127 debugs(
"[new_child_iseq]< ---------------------------------------\n");
1143 debugs(
"[compile step 3.1 (iseq_optimize)]\n");
1150 debugs(
"[compile step 3.2 (iseq_insns_unification)]\n");
1157 debugs(
"[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
1163 debugs(
"[compile step 4.1 (iseq_set_sequence)]\n");
1168 debugs(
"[compile step 4.2 (iseq_set_exception_table)]\n");
1171 debugs(
"[compile step 4.3 (set_optargs_table)] \n");
1174 debugs(
"[compile step 5 (iseq_translate_threaded_code)] \n");
1181 debugs(
"[compile step: finish]\n");
1197 ids[0] = id_dollar_bang;
1232 rb_bug(
"get_local_var_idx: %d", idx);
1241 int lv = 0, idx = -1;
1253 rb_bug(
"get_dyna_var_idx: -1");
1303 struct rb_iseq_param_keyword *keyword;
1306 int kw = 0, rkw = 0, di = 0, i;
1313 NODE *val_node = node->nd_body->nd_value;
1316 if (val_node == (
NODE *)-1) {
1322 dv = val_node->nd_lit;
1339 keyword->num = ++di;
1344 node = node->nd_next;
1353 keyword->required_num = rkw;
1354 keyword->table = &iseq->
body->
local_table[keyword->bits_start - keyword->num];
1359 for (i = 0; i <
RARRAY_LEN(default_values); i++) {
1361 if (dv == complex_mark) dv =
Qundef;
1365 keyword->default_values = dvs;
1372 debugs(
"iseq_set_arguments: %s\n", node_args ?
"" :
"0");
1411 node = node->nd_next;
1423 for (j = 0; j < i+1; j++) {
1437 struct rb_iseq_param_keyword *keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
1467 if (iseq->
body->
type == ISEQ_TYPE_BLOCK) {
1491 size = (
unsigned int)*tbl;
1512 if (val == lit)
return 0;
1522 return !
rb_eql(lit, val);
1583 unsigned int last_line = 0;
1585 VALUE *generated_iseq;
1587 int insn_num, code_index, line_info_index, sp, stack_max = 0, line = 0;
1591 insn_num = code_index = 0;
1593 switch (list->
type) {
1643 line_info_index = code_index = sp = 0;
1646 switch (list->
type) {
1656 if (sp > stack_max) {
1663 generated_iseq[code_index] = insn;
1664 types = insn_op_types(insn);
1665 len = insn_len(insn);
1671 xfree(generated_iseq);
1672 xfree(line_info_table);
1674 "operand size miss! (%d for %d)",
1679 for (j = 0; types[j]; j++) {
1680 char type = types[j];
1692 if (lobj->
sp == -1) {
1695 generated_iseq[code_index + 1 + j] = lobj->
position - (code_index +
len);
1700 VALUE map = operands[j];
1703 data.
pos = code_index;
1709 generated_iseq[code_index + 1 + j] = map;
1714 generated_iseq[code_index + 1 + j] =
FIX2INT(operands[j]);
1718 VALUE v = operands[j];
1719 generated_iseq[code_index + 1 + j] = v;
1724 VALUE v = operands[j];
1725 generated_iseq[code_index + 1 + j] = v;
1732 unsigned int ic_index =
FIX2UINT(operands[j]);
1735 rb_bug(
"iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->
body->
is_size);
1737 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
1758 generated_iseq[code_index + 1 + j] = (
VALUE)ci;
1764 generated_iseq[code_index + 1 + j] = (
VALUE)cc;
1768 generated_iseq[code_index + 1 + j] =
SYM2ID(operands[j]);
1774 generated_iseq[code_index + 1 + j] = (
VALUE)entry;
1778 generated_iseq[code_index + 1 + j] = operands[j];
1781 xfree(generated_iseq);
1782 xfree(line_info_table);
1784 "unknown operand type: %c", type);
1788 if (last_line != iobj->
line_no) {
1789 line_info_table[line_info_index].
line_no = last_line = iobj->
line_no;
1790 line_info_table[line_info_index].
position = code_index;
1799 if (lobj->
sp == -1) {
1812 if (adjust->
label) {
1820 if (orig_sp - sp > 0) {
1821 if (last_line != (
unsigned int)adjust->
line_no) {
1822 line_info_table[line_info_index].
line_no = last_line = adjust->
line_no;
1823 line_info_table[line_info_index].
position = code_index;
1826 generated_iseq[code_index++] = BIN(adjuststack);
1827 generated_iseq[code_index++] = orig_sp - sp;
1829 else if (orig_sp - sp == 0) {
1831 if (last_line != (
unsigned int)adjust->
line_no) {
1832 line_info_table[line_info_index].
line_no = last_line = adjust->
line_no;
1833 line_info_table[line_info_index].
position = code_index;
1836 generated_iseq[code_index++] = BIN(nop);
1837 generated_iseq[code_index++] = BIN(nop);
1841 "iseq_set_sequence: adjust bug %d < %d",
1880 const VALUE *tptr, *ptr;
1881 unsigned int tlen, i;
1891 for (i = 0; i < table->size; i++) {
1893 entry = &table->entries[i];
1900 if (entry->
iseq != 0) {
1911 if (entry->
type == CATCH_TYPE_RESCUE ||
1912 entry->
type == CATCH_TYPE_BREAK ||
1913 entry->
type == CATCH_TYPE_NEXT) {
2031 if (((
LABEL *)i)->unremovable)
return 0;
2032 if (((
LABEL *)i)->refcnt > 0) {
2033 if (i == first)
return 0;
2047 int pos,
len = insn_len(insn);
2048 for (pos = 0; pos <
len; ++pos) {
2049 switch (insn_op_types(insn)[pos]) {
2063 }
while ((i != end) && (i = i->
next) != 0);
2073 INSN *niobj, *diobj, *piobj;
2087 if (diobj == niobj) {
2097 else if (iobj != diobj &&
IS_INSN_ID(diobj, jump) &&
2143 ? BIN(branchunless) : BIN(branchif);
2182 else if (prev_dup &&
IS_INSN_ID(nobj, dup) &&
2271 enum ruby_vminsn_type previ = ((
INSN *)prev)->insn_id;
2272 if (previ == BIN(putobject) || previ == BIN(putnil) ||
2273 previ == BIN(putself) || previ == BIN(putstring)) {
2302 if (do_tailcallopt &&
2356 #define IS_TRACE_LINE(insn) \ 2357 (IS_INSN_ID(insn, trace) && \ 2358 OPERAND_AT(insn, 0) == INT2FIX(RUBY_EVENT_LINE)) 2375 if (insn_id == BIN(opt_neq)) {
2379 iobj->
operands[0] = old_operands[0];
2402 iobj->
insn_id = BIN(opt_newarray_max);
2406 iobj->
insn_id = BIN(opt_newarray_min);
2418 #define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt)) 2456 iobj->
insn_id = BIN(opt_send_without_block);
2470 case ISEQ_TYPE_EVAL:
2471 case ISEQ_TYPE_MAIN:
2473 case ISEQ_TYPE_RESCUE:
2474 case ISEQ_TYPE_ENSURE:
2486 const int do_peepholeopt =
ISEQ_COMPILE_DATA(iseq)->option->peephole_optimization;
2491 int rescue_level = 0;
2492 int tailcallopt = do_tailcallopt;
2498 if (do_peepholeopt) {
2505 insn_operands_unification((
INSN *)list);
2509 switch (((
LABEL *)list)->rescued) {
2512 tailcallopt =
FALSE;
2515 if (!--rescue_level) tailcallopt = do_tailcallopt;
2524 #if OPT_INSTRUCTIONS_UNIFICATION 2532 VALUE *operands = 0, *ptr = 0;
2536 for (i = 0; i <
size; i++) {
2537 iobj = (
INSN *)list;
2549 for (i = 0; i <
size; i++) {
2550 iobj = (
INSN *)list;
2568 #if OPT_INSTRUCTIONS_UNIFICATION 2577 iobj = (
INSN *)list;
2579 if (unified_insns_data[
id] != 0) {
2580 const int *
const *entry = unified_insns_data[
id];
2581 for (j = 1; j < (
intptr_t)entry[0]; j++) {
2582 const int *unified = entry[j];
2584 for (k = 2; k < unified[1]; k++) {
2586 ((
INSN *)li)->insn_id != unified[k]) {
2593 new_unified_insn(iseq, unified[0], unified[1] - 1,
2616 #if OPT_STACK_CACHING 2618 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)] 2619 #define SC_NEXT(insn) sc_insn_next[(insn)] 2621 #include "opt_sc.inc" 2630 iobj->
insn_id = SC_INSN(insn_id, state);
2631 nstate = SC_NEXT(iobj->
insn_id);
2633 if (insn_id == BIN(jump) ||
2634 insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
2641 printf(
"\n-- %d, %d\n", lobj->sc_state, nstate);
2643 "insn_set_sc_state error\n");
2650 if (insn_id == BIN(jump)) {
2654 else if (insn_id == BIN(leave)) {
2662 label_set_sc_state(
LABEL *lobj,
int state)
2682 #if OPT_STACK_CACHING 2694 switch (list->
type) {
2706 if (state != SCS_AX) {
2719 if (state == SCS_AB || state == SCS_BA) {
2720 state = (state == SCS_AB ? SCS_BA : SCS_AB);
2757 state = insn_set_sc_state(iseq, iobj, state);
2763 lobj = (
LABEL *)list;
2765 state = label_set_sc_state(lobj, state);
2780 VALUE lit = node->nd_lit;
2797 node = list->nd_head;
2807 list = list->nd_next;
2809 if (
NIL_P(lit) && first_lit) {
2840 const int line =
nd_line(node);
2851 ADD_INSNL(ret, line, branchunless, else_label);
2861 ADD_INSNL(ret, line, branchunless, then_label);
2924 const NODE *
const root_node,
2930 NODE *node = root_node->nd_head;
2933 NODE *key_node = node->nd_head;
2942 node = node->nd_next;
2943 node = node->nd_next;
2947 node = root_node->nd_head;
2949 int len = (int)node->nd_alen / 2;
2951 VALUE *keywords = kw_arg->keywords;
2953 kw_arg->keyword_len =
len;
2955 *kw_arg_ptr = kw_arg;
2957 for (i=0; node !=
NULL; i++, node = node->nd_next->nd_next) {
2958 NODE *key_node = node->nd_head;
2959 NODE *val_node = node->nd_next->nd_head;
2960 keywords[i] = key_node->nd_lit;
2961 COMPILE(ret,
"keyword values", val_node);
2979 node = node->nd_head;
2994 node = node->nd_head;
3003 return node->nd_lit;
3011 NODE *node = node_root;
3012 int line = (int)
nd_line(node);
3029 NODE *start_node = node, *end_node;
3031 const int max = 0x100;
3035 for (i=0; i<max && node; i++, len++, node = node->nd_next) {
3058 COMPILE_(anchor,
"array element", node->nd_head, popped);
3069 while (node != end_node) {
3071 node = node->nd_next;
3073 while (node && node->nd_next &&
3080 node = node->nd_next->nd_next;
3127 ADD_INSN(anchor, line, concatarray);
3148 if (i > 0 || !first)
ADD_INSN(ret, line, swap);
3149 COMPILE(ret,
"keyword splat", kw);
3181 VALUE v = node->nd_lit;
3199 return node->nd_lit =
rb_fstring(node->nd_lit);
3206 LABEL *l1,
int only_special_literals,
VALUE literals)
3213 only_special_literals = 0;
3218 "duplicated when clause is ignored");
3233 COMPILE(cond_seq,
"when cond", val);
3238 vals = vals->nd_next;
3240 return only_special_literals;
3306 int llen = 0, rlen = 0;
3308 NODE *lhsn = orig_lhsn;
3310 #define MEMORY(v) { \ 3312 if (memindex == memsize) return 0; \ 3313 for (i=0; i<memindex; i++) { \ 3314 if (mem[i] == (v)) return 0; \ 3316 mem[memindex++] = (v); \ 3324 NODE *ln = lhsn->nd_head;
3339 lhsn = lhsn->nd_next;
3348 COMPILE(ret,
"masgn val", rhsn->nd_head);
3350 rhsn = rhsn->nd_next;
3355 for (i=0; i<llen-rlen; i++) {
3368 do {
ADD_INSN(ret, line, putnil);}
while (++rlen < llen);
3370 else if (rlen > llen) {
3371 do {
ADD_INSN(ret, line, pop);}
while (--rlen > llen);
3378 NODE *rhsn = node->nd_value;
3379 NODE *splatn = node->nd_args;
3380 NODE *lhsn = node->nd_head;
3381 int lhs_splat = (splatn && (
VALUE)splatn != (
VALUE)-1) ? 1 : 0;
3393 lhsn = lhsn->nd_next;
3396 COMPILE(ret,
"normal masgn rhs", rhsn);
3401 else if (!lhs_splat) {
3414 else if (llen > 2 && llen != rlen) {
3420 else if (llen > 2) {
3435 NODE *postn = splatn->nd_2nd;
3436 NODE *restn = splatn->nd_1st;
3437 int num = (int)postn->nd_alen;
3448 postn = postn->nd_next;
3466 debugi(
"compile_colon2 - colon", node->nd_vid);
3470 debugi(
"compile_colon2 - colon3", node->nd_mid);
3477 debugi(
"compile_colon2 - colon2", node->nd_mid);
3495 else if (cpath->nd_head) {
3497 COMPILE(ret,
"nd_else->nd_head", cpath->nd_head);
3508 #define private_recv_p(node) (nd_type((node)->nd_recv) == NODE_SELF) 3510 #define defined_expr defined_expr0 3518 switch (type =
nd_type(node)) {
3544 }
while ((vals = vals->nd_next) !=
NULL);
3564 ID2SYM(node->nd_vid), needstr);
3570 ID2SYM(node->nd_entry->
id), needstr);
3576 ID2SYM(node->nd_vid), needstr);
3582 ID2SYM(node->nd_vid), needstr);
3592 COMPILE(ret,
"defined/colon2#nd_head", node->nd_head);
3594 ID2SYM(node->nd_mid), needstr);
3597 COMPILE(ret,
"defined/colon2#nd_head", node->nd_head);
3599 ID2SYM(node->nd_mid), needstr);
3613 const int explicit_receiver =
3620 if (node->nd_args) {
3624 if (explicit_receiver) {
3627 COMPILE(ret,
"defined/recv", node->nd_recv);
3629 ID2SYM(node->nd_mid), needstr);
3634 ID2SYM(node->nd_mid), needstr);
3696 int done = defined_expr0(iseq, ret, node, lfinish, needstr);
3703 (
"defined guard in "),
3705 ISEQ_TYPE_DEFINED_GUARD, 0);
3723 if (iseq->
body->
type == ISEQ_TYPE_BLOCK) {
3756 while (erange->
next != 0) {
3757 erange = erange->
next;
3762 erange->
end = lstart;
3814 COMPILE(arg_block,
"block", argn->nd_body);
3816 argn = argn->nd_head;
3823 COMPILE(args,
"args (splat)", argn->nd_head);
3836 COMPILE(tmp,
"args (cat: splat)", argn->nd_body);
3847 if (next_is_array) {
3851 argn = argn->nd_head;
3869 for (i=1; i<nsplat; i++) {
3905 #if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0) 3911 ADD_INSNL(ret, line, branchunless, fail_label);
3913 for (vars = node; vars; vars = vars->nd_next) {
3915 if (vars->nd_next) {
3924 #if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0 3925 if (!vars->nd_next && vars == node) {
3937 (nom->last->next = cap->link.
next)->
prev = nom->last;
3938 (cap->link.
next = nom->anchor.
next)->
prev = &cap->link;
3946 for (vars = node; vars; vars = vars->nd_next) {
3950 ((
INSN*)last)->insn_id = BIN(putnil);
3951 ((
INSN*)last)->operand_size = 0;
3978 debugs(
"node: NODE_NIL(implicit)\n");
3993 saved_last_element = ret->
last;
3998 #undef BEFORE_RETURN 3999 #define BEFORE_RETURN debug_node_end() 4007 (node->nd_next ? 1 : popped)));
4008 node = node->nd_next;
4019 LABEL *then_label, *else_label, *end_label;
4029 then_label, else_label);
4048 NODE *tempnode = node;
4049 LABEL *endlabel, *elselabel;
4053 int only_special_literals = 1;
4062 if (node->nd_head == 0) {
4068 node = node->nd_body;
4090 CHECK(
COMPILE_(body_seq,
"when body", node->nd_body, popped));
4091 ADD_INSNL(body_seq, line, jump, endlabel);
4093 vals = node->nd_head;
4097 only_special_literals =
when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
4102 only_special_literals = 0;
4116 node = node->nd_next;
4128 ADD_INSNL(cond_seq, line, jump, endlabel);
4131 debugs(
"== else (implicit)\n");
4140 if (only_special_literals) {
4156 NODE *orig_node = node;
4167 ADD_INSNL(body_seq, line, jump, endlabel);
4169 vals = node->nd_head;
4176 val = vals->nd_head;
4179 vals = vals->nd_next;
4193 node = node->nd_next;
4226 if (type ==
NODE_OPT_N || node->nd_state == 1) {
4238 if (tmp_label)
ADD_LABEL(ret, tmp_label);
4246 redo_label, end_label);
4251 end_label, redo_label);
4256 ADD_INSNL(ret, line, branchif, redo_label);
4263 if (node->nd_state ==
Qundef) {
4296 NODE *var = node->nd_var;
4304 ADD_INSNL(ret, line, branchunless, not_single);
4311 ADD_INSNL(ret, line, branchunless, not_ary);
4325 CHECK(
COMPILE(ret,
"iter caller (for)", node->nd_iter));
4328 ISEQ_TYPE_BLOCK, line);
4333 ISEQ_TYPE_BLOCK, line);
4344 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, 0, retry_end_l);
4349 unsigned long level = 0;
4356 CHECK(
COMPILE_(ret,
"break val (while/until)", node->nd_stts,
4366 else if (iseq->
body->
type == ISEQ_TYPE_BLOCK) {
4369 CHECK(
COMPILE(ret,
"break val (block)", node->nd_stts));
4375 else if (iseq->
body->
type == ISEQ_TYPE_EVAL) {
4394 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
4398 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
4410 unsigned long level = 0;
4414 debugs(
"next in while loop\n");
4416 CHECK(
COMPILE(ret,
"next val/valid syntax?", node->nd_stts));
4427 debugs(
"next in block\n");
4439 else if (iseq->
body->
type == ISEQ_TYPE_EVAL) {
4458 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
4461 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
4495 else if (iseq->
body->
type == ISEQ_TYPE_EVAL) {
4527 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
4530 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
4552 if (iseq->
body->
type == ISEQ_TYPE_RESCUE) {
4576 ISEQ_TYPE_RESCUE, line);
4583 if (node->nd_else) {
4602 LABEL *label_miss, *label_hit;
4608 narg = resq->nd_args;
4616 ADD_INSNL(ret, line, branchif, label_hit);
4617 narg = narg->nd_next;
4626 ADD_INSNL(ret, line, branchif, label_hit);
4636 ADD_INSNL(ret, line, branchif, label_hit);
4646 resq = resq->nd_head;
4654 ISEQ_TYPE_ENSURE, line);
4675 CHECK(
COMPILE_(ret,
"ensure head", node->nd_head, (popped | last_leave)));
4677 if (ensr->anchor.next == 0) {
4682 if (!popped && last_leave) {
4687 if (last_leave)
ADD_INSN(ret, line, pop);
4694 erange = erange->
next;
4710 ADD_INSNL(ret, line, branchunless, end_label);
4713 ADD_INSNL(ret, line, branchif, end_label);
4729 ID id = node->nd_vid;
4767 ((
VALUE)node->nd_entry | 1));
4776 ADD_INSN2(ret, line, setinstancevariable,
4811 unsigned int flag = 0;
4812 unsigned int asgnflag = 0;
4813 ID id = node->nd_mid;
4842 asgnflag =
COMPILE_RECV(ret,
"NODE_OP_ASGN1 recv", node);
4843 switch (
nd_type(node->nd_args->nd_head)) {
4851 argc =
setup_args(iseq, args, node->nd_args->nd_head, &flag,
NULL);
4858 if (
id == 0 ||
id == 1) {
4878 ADD_INSNL(ret, line, branchunless, label);
4882 CHECK(
COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
4916 CHECK(
COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
4947 ID atype = node->nd_next->nd_mid;
4995 asgnflag =
COMPILE_RECV(ret,
"NODE_OP_ASGN2#recv", node);
4996 if (node->nd_next->nd_aid) {
5004 if (atype == 0 || atype == 1) {
5010 ADD_INSNL(ret, line, branchunless, lcfin);
5013 CHECK(
COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
5033 CHECK(
COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
5052 switch (
nd_type(node->nd_head)) {
5057 CHECK(
COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
5064 mid = node->nd_head->nd_mid;
5066 if (node->nd_aid == 0) {
5071 ADD_INSNL(ret, line, branchunless, lassign);
5076 if (node->nd_aid == 0 || node->nd_aid == 1) {
5078 if (!popped)
ADD_INSN(ret, line, dup);
5079 if (node->nd_aid == 0)
5082 ADD_INSNL(ret, line, branchunless, lfin);
5084 if (!popped)
ADD_INSN(ret, line, pop);
5086 CHECK(
COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
5096 if (!popped)
ADD_INSN(ret, line, swap);
5100 CHECK(
COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
5123 lassign = lfinish[1];
5127 ADD_INSNL(ret, line, branchunless, lassign);
5133 CHECK(
COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
5137 ADD_INSNL(ret, line, branchunless, lfin);
5145 CHECK(
COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_value", node->nd_value));
5159 node->nd_mid == idFreeze && node->nd_args ==
NULL &&
5164 ADD_INSN1(ret, line, opt_str_freeze, str);
5179 node->nd_args->nd_head->nd_lit = str;
5200 ID mid = node->nd_mid;
5202 unsigned int flag = 0;
5215 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
5217 if (mid == id_bitblt) {
5221 else if (mid == id_answer) {
5235 (mid == goto_id || mid == label_id)) {
5241 if (!labels_table) {
5246 SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
5248 label_name =
SYM2ID(node->nd_args->nd_head->nd_lit);
5255 label = (
LABEL *)data;
5264 if (mid == goto_id) {
5280 ADD_INSNL(recv, line, branchnil, lskip);
5289 argc =
setup_args(iseq, args, node->nd_args, &flag, &keywords);
5323 unsigned int flag = 0;
5330 VALUE vargc =
setup_args(iseq, args, node->nd_args, &flag, &keywords);
5372 for (j=0; j<post_len; j++) {
5377 ADD_INSN (args, line, concatarray);
5382 for (j=0; j<post_len; j++) {
5386 argc = post_len + post_start;
5413 ADD_INSN (args, line, concatarray);
5424 ADD_INSN (args, line, concatarray);
5496 enum iseq_type type = is->
body->
type;
5498 enum iseq_type parent_type;
5500 if (type == ISEQ_TYPE_TOP) {
5508 else if ((type == ISEQ_TYPE_RESCUE || type == ISEQ_TYPE_ENSURE || type == ISEQ_TYPE_MAIN) &&
5510 ((parent_type = parent_iseq->
body->
type) == ISEQ_TYPE_TOP ||
5511 parent_type == ISEQ_TYPE_MAIN)) {
5521 if (type == ISEQ_TYPE_METHOD) {
5527 CHECK(
COMPILE(ret,
"return nd_stts (return val)", node->nd_stts));
5529 if (type == ISEQ_TYPE_METHOD) {
5552 unsigned int flag = 0;
5556 if (iseq->
body->
type == ISEQ_TYPE_TOP) {
5561 if (node->nd_head) {
5562 argc =
setup_args(iseq, args, node->nd_head, &flag, &keywords);
5578 ID id = node->nd_vid;
5588 debugi(
"nd_vid", node->nd_vid);
5601 ((
VALUE)node->nd_entry | 1));
5608 debugi(
"nd_vid", node->nd_vid);
5610 ADD_INSN2(ret, line, getinstancevariable,
5617 debugi(
"nd_vid", node->nd_vid);
5647 if (!node->nd_nth) {
5659 INT2FIX(0x01 | (node->nd_nth << 1)));
5673 ADD_INSN1(recv, line, putobject, node->nd_lit);
5689 if (recv->last == recv->anchor.next &&
5690 INSN_OF(recv->last) == BIN(putobject) &&
5708 if (node->nd_args) {
5720 ADD_INSN1(ret, line, putobject, node->nd_lit);
5729 ADD_INSN1(ret, line, putstring, node->nd_lit);
5740 ADD_INSN1(ret, line, putobject, node->nd_lit);
5759 ADD_INSN1(ret, line, freezestring, debug_info);
5767 ADD_INSN1(ret, line, putobject, node->nd_lit);
5839 CHECK(
COMPILE_(ret,
"argspush body", node->nd_body, popped));
5843 CHECK(
COMPILE_(ret,
"argspush body", node->nd_body, popped));
5861 ISEQ_TYPE_METHOD, line);
5867 ADD_INSN1(ret, line, putiseq, method_iseq);
5879 ISEQ_TYPE_METHOD, line);
5886 ADD_INSN1(ret, line, putiseq, singleton_method);
5931 ISEQ_TYPE_CLASS, line);
5948 ISEQ_TYPE_CLASS, line);
5964 ISEQ_TYPE_CLASS, line);
5968 CONST_ID(singletonclass,
"singletonclass");
5970 ID2SYM(singletonclass), singleton_class,
6025 debugi(
"colon3#nd_mid", node->nd_mid);
6050 NODE *b = node->nd_beg;
6051 NODE *e = node->nd_end;
6112 if (iseq->
body->
type == ISEQ_TYPE_RESCUE) {
6119 if (ip->
body->
type == ISEQ_TYPE_RESCUE) {
6137 if (!node->nd_head) {
6174 NODE *default_value = node->nd_body->nd_value;
6176 if (default_value == (
NODE *)-1) {
6195 ADD_INSNL(ret, line, branchif, end_label);
6215 unsigned int flag = 0;
6216 ID mid = node->nd_mid;
6230 node->nd_args->nd_head->nd_lit = str;
6233 CHECK(
COMPILE(ret,
"value", node->nd_args->nd_next->nd_head));
6259 ADD_INSNL(recv, line, branchnil, lskip);
6298 if (node->nd_orig) {
6327 if (saved_last_element &&
6328 ret->
last == saved_last_element &&
6329 ((
INSN *)saved_last_element)->insn_id == BIN(trace)) {
6344 return insn_len(iobj->
insn_id);
6378 const char *types = insn_op_types(iobj->
insn_id);
6381 for (j = 0; types[j]; j++) {
6382 char type = types[j];
6444 if (dladdr(func, &info) && info.dli_sname) {
6472 printf(
"-- raw disasm--------\n");
6475 switch (link->
type) {
6478 iobj = (
INSN *)link;
6486 lobj = (
LABEL *)link;
6487 printf(
"<L%03d>\n", lobj->
label_no);
6507 printf(
"---------------------\n");
6514 return insn_name_info[i];
6522 for (i = 0; i <
numberof(insn_name_info); i++) {
6535 if (
st_lookup(labels_table, obj, &tmp) == 0) {
6540 label = (
LABEL *)tmp;
6550 #define rb_intern(str) rb_intern_const(str) 6551 static VALUE symRescue, symEnsure, symRetry;
6552 static VALUE symBreak, symRedo, symNext;
6554 if (symRescue == 0) {
6563 if (sym == symRescue)
return CATCH_TYPE_RESCUE;
6564 if (sym == symEnsure)
return CATCH_TYPE_ENSURE;
6565 if (sym == symRetry)
return CATCH_TYPE_RETRY;
6566 if (sym == symBreak)
return CATCH_TYPE_BREAK;
6567 if (sym == symRedo)
return CATCH_TYPE_REDO;
6568 if (sym == symNext)
return CATCH_TYPE_NEXT;
6583 LABEL *lstart, *lend, *lcont;
6593 if (ptr[1] ==
Qnil) {
6621 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
6654 unsigned int flag = 0;
6665 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
6667 if (!
NIL_P(vkw_arg)) {
6674 for (i = 0; i <
len; i++) {
6700 static struct st_table *insn_table;
6702 if (insn_table == 0) {
6706 for (i=0; i<
len; i++) {
6726 "unknown instruction: %+"PRIsVALUE, insn);
6731 if (argc != insn_len((
VALUE)insn_id)-1) {
6733 "operand size mismatch");
6740 for (j=0; j<
argc; j++) {
6742 switch (insn_op_type((
VALUE)insn_id, j)) {
6745 argv[j] = (
VALUE)label;
6785 "Symbol",
"to_sym");
6808 #if SIZEOF_VALUE <= SIZEOF_LONG 6811 LONG_LONG funcptr = NUM2LL(op);
6813 argv[j] = (
VALUE)funcptr;
6823 (
enum ruby_vminsn_type)insn_id, argc, argv));
6831 if (!ret)
return ret;
6835 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary") 6836 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym") 6842 switch (
TYPE(val)) {
6855 static const struct rb_iseq_param_keyword *
6864 struct rb_iseq_param_keyword *keyword =
ZALLOC(
struct rb_iseq_param_keyword);
6869 #define SYM(s) ID2SYM(rb_intern(#s)) 6870 (void)
int_param(&keyword->bits_start, params,
SYM(kwbits));
6871 i = keyword->bits_start - keyword->num;
6876 for (i = 0; i <
len; i++) {
6880 goto default_values;
6883 keyword->required_num++;
6887 default_len = len - i;
6888 if (default_len == 0) {
6894 for (j = 0; i <
len; i++, j++) {
6911 dvs[j] = default_val;
6914 keyword->table = ids;
6915 keyword->default_values = dvs;
6924 #define SYM(s) ID2SYM(rb_intern(#s)) 6939 for (i = 0; i <
len; i++) {
6942 if (sym_arg_rest == lv) {
6955 #define INT_PARAM(F) int_param(&iseq->body->param.F, params, SYM(F)) 6965 switch (
TYPE(arg_opt_labels)) {
6973 for (i = 0; i <
len; i++) {
6976 opt_table[i] = (
VALUE)label;
6989 switch (
TYPE(keywords)) {
7004 struct rb_iseq_param_keyword *keyword = (
struct rb_iseq_param_keyword *)iseq->
body->
param.
keyword;
7008 keyword->rest_start = i;
7029 while (iseq->
body->
type == ISEQ_TYPE_BLOCK ||
7030 iseq->
body->
type == ISEQ_TYPE_RESCUE ||
7031 iseq->
body->
type == ISEQ_TYPE_ENSURE ||
7032 iseq->
body->
type == ISEQ_TYPE_EVAL ||
7081 *absolute_path = *path;
7096 VALUE path, absolute_path;
7104 INT2FIX(acc.line), 0, ISEQ_TYPE_METHOD, 0);
7111 const int line = args->
line;
7126 const int line = args->
line;
7127 static const ID vars[] = {1, idUScore};
7161 #define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr)) 7229 if ((
unsigned long)(size + offset) > (
unsigned long)
RSTRING_LEN(str))
7230 rb_bug(
"ibf_dump_overwrite: overflow");
7231 memcpy(ptr + offset, buff, size);
7242 #define IBF_W(b, type, n) (type *)(VALUE)ibf_dump_write(dump, (b), sizeof(type) * (n)) 7243 #define IBF_WV(variable) ibf_dump_write(dump, &(variable), sizeof(variable)) 7244 #define IBF_WP(b, type, n) ibf_dump_write(dump, (b), sizeof(type) * (n)) 7245 #define IBF_R(val, type, n) (type *)ibf_load_alloc(load, IBF_OFFSET(val), sizeof(type) * (n)) 7283 for (i=0; i<index; i++) {
7287 return (
VALUE)index;
7301 if (id_index == 0) {
7305 id = load->
id_list[(long)id_index];
7311 load->
id_list[(long)id_index] =
id;
7336 if (iseq_index < 0) {
7367 for (code_index=0; code_index<iseq_size;) {
7368 const VALUE insn = orig_code[code_index];
7369 const char *types = insn_op_types(insn);
7372 code[code_index++] = (
VALUE)insn;
7374 for (op_index=0; types[op_index]; op_index++, code_index++) {
7375 VALUE op = orig_code[code_index];
7376 switch (types[op_index]) {
7392 code[code_index] = i;
7399 code[code_index] = 0;
7411 code[code_index] = op;
7415 assert(insn_len(insn) == op_index+1);
7433 for (code_index=0; code_index<iseq_size;) {
7434 const VALUE insn = code[code_index++];
7435 const char *types = insn_op_types(insn);
7438 for (op_index=0; types[op_index]; op_index++, code_index++) {
7439 VALUE op = code[code_index];
7441 switch (types[op_index]) {
7450 code[code_index] = (
VALUE)&is_entries[(
int)op];
7453 code[code_index] = op ? (
VALUE)ci_kw_entries++ : (
VALUE)ci_entries++;
7456 code[code_index] = (
VALUE)cc_entries++;
7472 assert(insn_len(insn) == op_index+1);
7508 static struct rb_iseq_param_keyword *
7514 struct rb_iseq_param_keyword dump_kw = *kw;
7515 int dv_num = kw->num - kw->required_num;
7520 for (i=0; i<kw->num; i++) ids[i] = (
ID)
ibf_dump_id(dump, kw->table[i]);
7523 dump_kw.table =
IBF_W(ids,
ID, kw->num);
7524 dump_kw.default_values =
IBF_W(dvs,
VALUE, dv_num);
7525 return IBF_W(&dump_kw,
struct rb_iseq_param_keyword, 1);
7532 static const struct rb_iseq_param_keyword *
7536 struct rb_iseq_param_keyword *kw =
IBF_R(body->
param.
keyword,
struct rb_iseq_param_keyword, 1);
7537 ID *ids =
IBF_R(kw->table,
ID, kw->num);
7538 int dv_num = kw->num - kw->required_num;
7542 for (i=0; i<kw->num; i++) {
7545 for (i=0; i<dv_num; i++) {
7550 kw->default_values = dvs;
7577 for (i=0; i<
size; i++) {
7581 return IBF_W(table,
ID, size);
7593 for (i=0; i<
size; i++) {
7603 static struct iseq_catch_table *
7610 struct iseq_catch_table *dump_table = (
struct iseq_catch_table *)
ALLOCA_N(
char, byte_size);
7612 dump_table->size = table->size;
7613 for (i=0; i<table->size; i++) {
7614 dump_table->entries[i] = table->entries[i];
7615 dump_table->entries[i].iseq =
ibf_dump_iseq(dump, table->entries[i].iseq);
7624 static struct iseq_catch_table *
7628 struct iseq_catch_table *table;
7633 for (i=0; i<
size; i++) {
7651 int byte_size = ci_size *
sizeof(
struct rb_call_info) +
7657 memcpy(dump_ci_entries, ci_entries, byte_size);
7659 for (i=0; i<ci_size; i++) {
7660 dump_ci_entries[i].
mid =
ibf_dump_id(dump, dump_ci_entries[i].mid);
7662 for (i=0; i<ci_kw_size; i++) {
7672 dump_ci_kw_entries[i].
ci.
mid =
ibf_dump_id(dump, dump_ci_kw_entries[i].ci.mid);
7681 const unsigned int ci_size = body->
ci_size;
7682 const unsigned int ci_kw_size = body->
ci_kw_size;
7688 for (i=0; i<ci_size; i++) {
7691 for (i=0; i<ci_kw_size; i++) {
7694 const int keyword_len = *(
int *)(load->
buff + kw_arg_offset);
7695 const VALUE *keywords = (
VALUE *)(load->
buff + kw_arg_offset +
sizeof(
int));
7701 ci_kw_entries[i].
kw_arg = kw_arg;
7712 dump_body = *iseq->
body;
7715 dump_body.location.absolute_path =
ibf_dump_object(dump, dump_body.location.absolute_path);
7716 dump_body.location.base_label =
ibf_dump_object(dump, dump_body.location.base_label);
7717 dump_body.location.label =
ibf_dump_object(dump, dump_body.location.label);
7727 dump_body.is_entries =
NULL;
7729 dump_body.cc_entries =
NULL;
7794 for (i=0; i<
size; i++) {
7842 #define IBF_OBJECT_INTERNAL FL_PROMOTED0 7854 unsigned int internal: 1;
7909 #define IBF_OBJHEADER(offset) (struct ibf_object_header *)(load->buff + (offset)) 7910 #define IBF_OBJBODY(type, offset) (type *)(load->buff + sizeof(struct ibf_object_header) + (offset)) 7916 rb_bug(
"ibf_dump_object_unsupported: unsupported");
7942 rb_bug(
"unsupported class");
7962 rb_bug(
"ibf_load_object_class: unknown class (%d)", (
int)cindex);
8045 for (i=0; i<
len; i++) {
8058 for (i=0; i<array->
len; i++) {
8094 for (i=0; i<hash->
len; i++) {
8123 rb_bug(
"ibf_dump_object_struct: unsupported class");
8154 int sign = bignum->
slen > 0;
8155 ssize_t
len = sign > 0 ? bignum->
slen : -1 * bignum->
slen;
8273 ibf_dump_object_unsupported
8301 (*dump_object_functions[obj_header.
type])(dump, obj);
8304 return current_offset;
8340 ibf_load_object_unsupported
8346 if (object_index == 0) {
8356 ibf_offset_t offset = offsets[object_index];
8364 obj = (*load_object_functions[header->
type])(load, header, offset);
8388 for (i=0; i<
size; i++) {
8424 size_t size =
sizeof(*dump);
8472 header.
magic[0] =
'Y';
8473 header.
magic[1] =
'A';
8474 header.
magic[2] =
'R';
8475 header.
magic[3] =
'B';
8484 VALUE opt_str = opt;
8502 static const ibf_offset_t *
8517 load->
iseq = prev_src_iseq;
8532 int iseq_index = (int)(
VALUE)index_iseq;
8534 if (iseq_index == -1) {
8540 if (iseqv !=
Qnil) {
8582 if (strncmp(load->
header->
magic,
"YARB", 4) != 0) {
8620 return sizeof(
struct ibf_load) + load->header->id_list_size *
sizeof(
ID);
NOINLINE(static compile_error_func prepare_compile_error(rb_iseq_t *iseq))
#define RBASIC_CLEAR_CLASS(obj)
#define RUBY_EVENT_B_RETURN
#define VM_CALL_ARGS_BLOCKARG
static void ibf_loader_mark(void *ptr)
union iseq_inline_storage_entry * is_entries
rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(const rb_thread_t *th, const rb_control_frame_t *cfp)
VALUE iseq_ibf_load_extra_data(VALUE str)
int rb_enc_get_index(VALUE obj)
static int iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
static VALUE make_name_for_block(const rb_iseq_t *orig_iseq)
VALUE rb_ary_entry(VALUE ary, long offset)
struct iseq_link_element * next
static int static_literal_node_p(NODE *node)
void rb_bug(const char *fmt,...)
VALUE rb_ary_new_capa(long capa)
void ibf_load_iseq_complete(rb_iseq_t *iseq)
#define OPERAND_AT(insn, idx)
static ADJUST * compile_data_alloc_adjust(rb_iseq_t *iseq)
#define RUBY_TYPED_FREE_IMMEDIATELY
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE exception, VALUE body)
#define ADD_INSN2(seq, line, insn, op1, op2)
static VALUE * ibf_dump_param_opt_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
static void ibf_dump_object_regexp(struct ibf_dump *dump, VALUE obj)
static void ibf_dump_object_hash(struct ibf_dump *dump, VALUE obj)
static const struct rb_iseq_param_keyword * iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
static VALUE ibf_load_object_unsupported(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
static struct iseq_line_info_entry * ibf_load_line_info_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
#define va_init_list(a, b)
size_t strlen(const char *)
VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline)
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
static int ibf_table_index(struct st_table *table, st_data_t key)
#define RUBY_EVENT_RETURN
void rb_iseq_make_compile_option(rb_compile_option_t *option, VALUE opt)
static int insn_data_length(INSN *iobj)
#define INSERT_BEFORE_INSN(prev, line, insn)
VALUE rb_range_new(VALUE, VALUE, int)
static VALUE ibf_load_object_bignum(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
static void ibf_dump_object_float(struct ibf_dump *dump, VALUE obj)
static void push_ensure_entry(rb_iseq_t *iseq, struct iseq_compile_data_ensure_node_stack *enl, struct ensure_range *er, NODE *node)
static int max(int a, int b)
static unsigned int hash(str, len) register const char *str
#define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag)
#define CPDEBUG
debug function(macro) interface depend on CPDEBUG if it is less than 0, runtime option is in effect...
struct ensure_range * next
static VALUE compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node_root, enum compile_array_type_t type)
static VALUE ibf_dump_object(struct ibf_dump *dump, VALUE obj)
static void adjust_stack(rb_iseq_t *iseq, LINK_ANCHOR *const ret, int line, int rlen, int llen)
static struct rb_call_info * ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq)
static void dump_object(VALUE obj, struct dump_config *dc)
VALUE rb_iseqw_new(const rb_iseq_t *)
VALUE rb_fstring_cstr(const char *str)
static void compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
VALUE rb_str_cat(VALUE, const char *, long)
#define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block)
static ID * ibf_load_local_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
#define IBF_R(val, type, n)
static VALUE ibf_load_object_symbol(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
static const rb_iseq_t * rb_iseq_check(const rb_iseq_t *iseq)
#define ISEQ_MAJOR_VERSION
static ibf_offset_t lbf_dump_object_object(struct ibf_dump *dump, VALUE obj)
static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, NODE *n, int)
compile each node
VALUE(* ibf_load_object_function)(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t)
static void unref_destination(INSN *iobj, int pos)
VALUE rb_insns_name_array(void)
const char * rb_builtin_type_name(int t)
#define ZALLOC_N(type, n)
static VALUE static_literal_value(NODE *node)
rb_encoding * rb_to_encoding(VALUE enc)
int rb_is_const_id(ID id)
struct rb_iseq_constant_body::@196::@197 flags
static void ibf_dump_overwrite(struct ibf_dump *dump, void *buff, unsigned int size, long offset)
#define ADD_INSN(seq, line, insn)
VALUE rb_enc_from_encoding(rb_encoding *encoding)
#define IBF_OBJHEADER(offset)
static INSN * compile_data_alloc_insn(rb_iseq_t *iseq)
static VALUE * ISEQ_ORIGINAL_ISEQ(const rb_iseq_t *iseq)
static LABEL * compile_data_alloc_label(rb_iseq_t *iseq)
static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
rb_iseq_t * rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, const rb_iseq_t *parent, enum iseq_type type, const rb_compile_option_t *option)
union rb_iseq_struct::@198 aux
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
VALUE rb_ary_push(VALUE ary, VALUE item)
SSL_METHOD *(* func)(void)
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
if(len<=MAX_WORD_LENGTH &&len >=MIN_WORD_LENGTH)
VALUE rb_str_concat(VALUE, VALUE)
static void validate_labels(rb_iseq_t *iseq, st_table *labels_table)
#define debugi(header, id)
static int get_lvar_level(const rb_iseq_t *iseq)
static int iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table, VALUE exception)
struct st_table * rb_hash_tbl_raw(VALUE hash)
VALUE rb_ary_tmp_new(long capa)
VALUE rb_iseq_defined_string(enum defined_type type)
#define ADD_GETLOCAL(seq, line, idx, level)
struct rb_iseq_constant_body * body
int rb_local_defined(ID id, const struct rb_block *base_block)
static int validate_label(st_data_t name, st_data_t label, st_data_t arg)
static ibf_offset_t ibf_dump_pos(struct ibf_dump *dump)
struct rb_call_info_kw_arg * kw_arg
static VALUE for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *const ret, VALUE a)
static VALUE ibf_load_object_class(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
int rb_reg_options(VALUE)
void rb_raise(VALUE exc, const char *fmt,...)
static ibf_offset_t ibf_dump_write(struct ibf_dump *dump, const void *buff, unsigned long size)
VALUE rb_ary_clear(VALUE ary)
struct iseq_compile_data_storage * next
static ibf_load_object_function load_object_functions[RUBY_T_MASK+1]
VALUE rb_convert_type(VALUE, int, const char *, const char *)
static void compile_bug(rb_iseq_t *iseq, int line, const char *fmt,...)
struct rb_iseq_constant_body::@196 param
parameter information
VALUE rb_obj_is_kind_of(VALUE, VALUE)
const void ** rb_vm_get_insns_address_table(void)
static VALUE ibf_dump_gentry(struct ibf_dump *dump, const struct rb_global_entry *entry)
#define VM_CALL_ARGS_SPLAT
static ibf_dump_object_function dump_object_functions[RUBY_T_MASK+1]
#define ADD_ADJUST(seq, line, label)
st_index_t rb_str_hash(VALUE)
#define VM_DEFINECLASS_FLAG_SCOPED
void rb_gc_mark(VALUE ptr)
void(* ibf_dump_object_function)(struct ibf_dump *dump, VALUE obj)
static ID * ibf_dump_local_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
static struct rb_iseq_param_keyword * ibf_dump_param_keyword(struct ibf_dump *dump, const rb_iseq_t *iseq)
VALUE rb_hash_lookup(VALUE hash, VALUE key)
static VALUE ibf_dump_callinfo(struct ibf_dump *dump, const struct rb_call_info *ci)
#define UNKNOWN_NODE(prefix, node)
static ID ibf_load_id(const struct ibf_load *load, const ID id_index)
static void ibf_dump_mark(void *ptr)
static void INSERT_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2)
static VALUE build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *body)
void rb_obj_info_dump(VALUE obj)
#define debug_node_start(node)
#define COMPILE_POPPED(anchor, desc, node)
static int compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
VALUE rb_str_tmp_new(long)
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
static void REMOVE_ELEM(LINK_ELEMENT *elem)
VALUE rb_syntax_error_append(VALUE exc, VALUE file, int line, int column, rb_encoding *enc, const char *fmt, va_list args)
struct iseq_label_data LABEL
#define IBF_WP(b, type, n)
static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
ruby insn object list -> raw instruction sequence
static const unsigned char dv[]
static int when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals)
static struct rb_call_info * new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_call_info_kw_arg *kw_arg, int has_blockiseq)
struct iseq_link_element LINK_ELEMENT
static int caller_location(VALUE *path, VALUE *absolute_path)
static int insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
static void INSERT_ELEM_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
static int iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl)
VALUE iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
static int iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v)
static int iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v)
static const rb_data_type_t ibf_load_type
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
enum iseq_catch_table_entry::catch_type type
#define Data_Wrap_Struct(klass, mark, free, sval)
static size_t rb_call_info_kw_arg_bytes(int keyword_len)
const VALUE * iseq_encoded
rb_iseq_t * iseq_alloc(void)
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
#define ISEQ_MINOR_VERSION
#define ISEQ_NOT_LOADED_YET
static void ibf_load_setup(struct ibf_load *load, VALUE loader_obj, VALUE str)
static int ISEQ_FLIP_CNT_INCREMENT(const rb_iseq_t *iseq)
static const rb_data_type_t ibf_dump_type
#define ADD_SEQ(seq1, seq2)
#define RB_TYPE_P(obj, type)
#define COMPILE_RECV(anchor, desc, node)
static VALUE * ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size)
VALUE rb_hash_rehash(VALUE hash)
static void iseq_calc_param_size(rb_iseq_t *iseq)
static const ibf_offset_t * ibf_iseq_list(const struct ibf_load *load)
static int int_param(int *dst, VALUE param, VALUE sym)
static VALUE freeze_hide_obj(VALUE obj)
static int compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *lhsn)
#define RUBY_TYPED_WB_PROTECTED
#define EXPECT_NODE_NONULL(prefix, parent, ndtype)
static int compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
int rb_data_is_encoding(VALUE obj)
#define ADD_SETLOCAL(seq, line, idx, level)
#define rb_intern_str(string)
VALUE rb_dbl2big(double d)
#define ADD_TRACE(seq, line, event)
const char * rb_insns_name(int i)
void(* compile_error_func)(rb_iseq_t *, int, const char *,...)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
static int get_dyna_var_idx(const rb_iseq_t *iseq, ID id, int *level, int *ls)
unsigned int local_table_size
static VALUE ibf_load_object(const struct ibf_load *load, VALUE object_index)
#define ISEQ_TYPE_ONCE_GUARD
RUBY_EXTERN VALUE rb_cObject
static LABEL * new_label_body(rb_iseq_t *iseq, long line)
static void ibf_dump_object_string(struct ibf_dump *dump, VALUE obj)
size_t st_memsize(const st_table *tab)
static rb_iseq_t * ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq)
static void verify_list(ISEQ_ARG_DECLARE const char *info, LINK_ANCHOR *const anchor)
struct rb_call_info * ci_entries
static int compile_colon2(rb_iseq_t *iseq, NODE *node, LINK_ANCHOR *const pref, LINK_ANCHOR *const body)
#define INSERT_BEFORE_INSN1(prev, line, insn, op1)
VALUE rb_str_cat2(VALUE, const char *)
struct iseq_link_anchor LINK_ANCHOR
static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, NODE *node)
static ADJUST * new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
static int compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
#define SIZEOF_ISEQ_COMPILE_DATA_STORAGE
RUBY_EXTERN VALUE rb_cRange
#define VM_DEFINECLASS_FLAG_HAS_SUPERCLASS
static int cdhash_cmp(VALUE val, VALUE lit)
#define ADD_SEND(seq, line, id, argc)
const rb_iseq_t * rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
#define ADD_INSNL(seq, line, insn, label)
static VALUE enc_name(VALUE self)
struct rb_id_table * rb_id_table_create(size_t size)
#define VM_CALL_ARGS_SIMPLE
void rb_ary_store(VALUE ary, long idx, VALUE val)
static int iseq_set_exception_local_table(rb_iseq_t *iseq)
rb_atomic_t cnt[RUBY_NSIG]
static int ibf_dump_object_hash_i(st_data_t key, st_data_t val, st_data_t ptr)
#define ADD_CALL(seq, line, id, argc)
static int compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *cond, LABEL *then_label, LABEL *else_label)
#define INIT_ANCHOR(name)
static LINK_ELEMENT * get_destination_insn(INSN *iobj)
VALUE * rb_iseq_original_iseq(const rb_iseq_t *iseq)
static void APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2)
#define COMPILE_(anchor, desc, node, popped)
VALUE rb_rational_new(VALUE, VALUE)
#define ALLOCA_N(type, n)
static int compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int again, LABEL *then_label, LABEL *else_label)
static VALUE case_when_optimizable_literal(NODE *node)
#define range(low, item, hi)
static int compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node_root, enum compile_array_type_t type, struct rb_call_info_kw_arg **keywords_ptr, int popped)
#define MEMCPY(p1, p2, type, n)
#define COMPILE(anchor, desc, node)
VALUE rb_enc_associate_index(VALUE obj, int idx)
static struct iseq_catch_table * ibf_load_catch_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
static int iseq_set_optargs_table(rb_iseq_t *iseq)
struct ensure_range * erange
#define ADD_SEND_R(seq, line, id, argc, block, flag, keywords)
const struct rb_iseq_constant_body::@196::rb_iseq_param_keyword * keyword
int link(const char *, const char *)
static int get_local_var_idx(const rb_iseq_t *iseq, ID id)
struct iseq_compile_data_ensure_node_stack * prev
static int number_literal_p(NODE *n)
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
#define IS_TRACE_LINE(insn)
static VALUE get_ivar_ic_value(rb_iseq_t *iseq, ID id)
#define LABEL_UNREMOVABLE(label)
int rb_str_hash_cmp(VALUE, VALUE)
static VALUE r_value(VALUE value)
static void * ibf_load_alloc(const struct ibf_load *load, ibf_offset_t offset, int size)
struct rb_call_cache * cc_entries
#define ADD_LABEL(seq, label)
#define RARRAY_CONST_PTR(a)
static LINK_ELEMENT * LAST_ELEMENT(LINK_ANCHOR *const anchor)
#define REALLOC_N(var, type, n)
static void ibf_dump_object_list(struct ibf_dump *dump, struct ibf_header *header)
int rb_dvar_defined(ID id, const struct rb_block *base_block)
static void ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *elem)
static VALUE iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
VALUE rb_sprintf(const char *format,...)
static void ibf_dump_object_array(struct ibf_dump *dump, VALUE obj)
static void ibf_dump_object_bignum(struct ibf_dump *dump, VALUE obj)
struct iseq_insn_data INSN
#define IS_INSN_ID(iobj, insn)
static void ibf_dump_free(void *ptr)
static LINK_ELEMENT * get_next_insn(INSN *iobj)
static VALUE setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, NODE *argn, unsigned int *flag, struct rb_call_info_kw_arg **keywords)
#define private_recv_p(node)
const rb_iseq_t * rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func)
static const rb_iseq_t * vm_block_iseq(const struct rb_block *block)
static VALUE ibf_dump_id(struct ibf_dump *dump, ID id)
VALUE rb_ivar_set(VALUE, ID, VALUE)
static rb_iseq_t * ibf_dump_iseq(struct ibf_dump *dump, const rb_iseq_t *iseq)
static void ibf_dump_object_complex_rational(struct ibf_dump *dump, VALUE obj)
#define DECL_ANCHOR(name)
static size_t ibf_loader_memsize(const void *ptr)
static int iseq_catch_table_bytes(int n)
static VALUE ibf_load_object_float(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
#define ISEQ_COVERAGE(iseq)
void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args)
static LINK_ELEMENT * get_prev_insn(INSN *iobj)
static INSN * new_insn_core(rb_iseq_t *iseq, int line_no, int insn_id, int argc, VALUE *argv)
struct iseq_link_element * prev
static void * compile_data_alloc(rb_iseq_t *iseq, size_t size)
VALUE rb_obj_hide(VALUE obj)
VALUE rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node)
#define ADD_CALL_RECEIVER(seq, line)
static VALUE * ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
static VALUE * ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, const struct rb_iseq_constant_body *body)
#define VM_CHECKMATCH_ARRAY
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
static LABEL * register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj)
const char * rb_id2name(ID)
#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc)
VALUE rb_str_new_cstr(const char *)
static void ibf_dump_object_unsupported(struct ibf_dump *dump, VALUE obj)
#define INTEGER_PACK_LITTLE_ENDIAN
#define RARRAY_LENINT(ary)
RUBY_EXTERN VALUE rb_cNumeric
static INSN * new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int argc,...)
static VALUE ibf_load_object_hash(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
static const struct st_hash_type cdhash_type
VALUE rb_complex_new(VALUE x, VALUE y)
enum rb_iseq_constant_body::iseq_type type
static struct iseq_catch_table * ibf_dump_catch_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
static VALUE ibf_load_object_data(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
#define ADD_INSN3(seq, line, insn, op1, op2, op3)
register unsigned int len
#define StringValueCStr(v)
static int tailcallable_p(rb_iseq_t *iseq)
static VALUE get_exception_sym2type(VALUE sym)
void * ruby_xmalloc(size_t size)
static int calc_sp_depth(int depth, INSN *iobj)
static int cdhash_set_label_i(VALUE key, VALUE val, void *ptr)
static VALUE opobj_inspect(VALUE obj)
static VALUE ibf_load_object_struct(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
const rb_iseq_t * rb_iseqw_to_iseq(VALUE iseqw)
static int label_get_position(LABEL *lobj)
#define INTEGER_PACK_NEGATIVE
VALUE rb_iseq_disasm(const rb_iseq_t *iseq)
static VALUE iseq_mark_ary_create(int flip_cnt)
struct rb_iseq_struct::@198::@199 loader
static void ibf_dump_id_list(struct ibf_dump *dump, struct ibf_header *header)
static VALUE for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *const ret, VALUE a)
static size_t ibf_dump_memsize(const void *ptr)
static void add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange, LABEL *lstart, LABEL *lend)
static void APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *before, LINK_ELEMENT *elem)
static int label_get_sp(LABEL *lobj)
static const rb_iseq_t * method_for_self(VALUE name, VALUE arg, rb_insn_func_t func, VALUE(*build)(rb_iseq_t *, LINK_ANCHOR *const, VALUE))
#define IBF_OBJBODY(type, offset)
static ibf_offset_t ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
#define debugp_param(header, value)
const struct iseq_catch_table * catch_table
#define RARRAY_AREF(a, i)
static void ibf_dump_setup(struct ibf_dump *dump, VALUE dumper_obj)
static int compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *rhsn, NODE *orig_lhsn)
static void ibf_dump_iseq_list(struct ibf_dump *dump, struct ibf_header *header)
static int compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
static VALUE insn_data_to_s_detail(INSN *iobj)
static int compile_array_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const root_node, struct rb_call_info_kw_arg **const kw_arg_ptr)
static const rb_iseq_t * iseq_build_load_iseq(const rb_iseq_t *iseq, VALUE op)
static void ibf_dump_object_struct(struct ibf_dump *dump, VALUE obj)
static int iseq_set_exception_table(rb_iseq_t *iseq)
static int iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, VALUE body, VALUE labels_wrapper)
static int remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i)
#define RBASIC_CLASS(obj)
void rb_set_errinfo(VALUE err)
static rb_iseq_t * iseq_imemo_alloc(void)
static VALUE * ibf_load_param_opt_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
VALUE rb_hash_aref(VALUE hash, VALUE key)
struct rb_iseq_struct * local_iseq
unsigned int ibf_offset_t
const char * ruby_node_name(int node)
static void ibf_loader_free(void *ptr)
VALUE rb_str_catf(VALUE str, const char *format,...)
#define EXPECT_NODE(prefix, node, ndtype)
#define IBF_W(b, type, n)
#define ISEQ_FLIP_CNT(iseq)
void rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj)
void rb_compile_warning(const char *file, int line, const char *fmt,...)
rb_control_frame_t *FUNC_FASTCALL rb_insn_func_t(rb_thread_t *, rb_control_frame_t *)
static void ibf_dump_object_class(struct ibf_dump *dump, VALUE obj)
void rb_check_safe_obj(VALUE)
static void ibf_load_iseq_each(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
struct rb_encoding_entry * list
static rb_iseq_t * new_child_iseq(rb_iseq_t *iseq, NODE *node, VALUE name, const rb_iseq_t *parent, enum iseq_type type, int line_no)
#define ADD_ADJUST_RESTORE(seq, label)
struct iseq_inline_cache_entry * IC
static INSN * new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_call_info_kw_arg *keywords)
#define NEW_ISEQ(node, name, type, line_no)
static void append_compile_error(rb_iseq_t *iseq, int line, const char *fmt,...)
#define TypedData_Make_Struct(klass, type, data_type, sval)
VALUE rb_ary_dup(VALUE ary)
const struct st_hash_type * type
#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block)
static void iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const struct rb_args_info *args)
static compile_error_func prepare_compile_error(rb_iseq_t *iseq)
static const char * catch_type(int type)
const struct rb_iseq_struct * parent_iseq
#define NEW_CHILD_ISEQ(node, name, type, line_no)
static struct iseq_line_info_entry * ibf_dump_line_info_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
static st_index_t cdhash_hash(VALUE a)
static struct st_table * insn_make_insn_table(void)
static int ibf_table_lookup(struct st_table *table, st_data_t key)
const struct iseq_line_info_entry * line_info_table
long rb_str_strlen(VALUE)
static LINK_ELEMENT * FIRST_ELEMENT(LINK_ANCHOR *const anchor)
static int ibf_dump_id_list_i(st_data_t key, st_data_t val, st_data_t ptr)
int rb_is_attrset_id(ID id)
#define StringValuePtr(v)
VALUE() rb_ary_new_from_args(long n,...)
unsigned int line_info_size
static void replace_destination(INSN *dobj, INSN *nobj)
static void ibf_dump_object_data(struct ibf_dump *dump, VALUE obj)
static VALUE ibf_load_gentry(const struct ibf_load *load, const struct rb_global_entry *entry)
static int iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
#define RTYPEDDATA_DATA(v)
int rb_enc_find_index(const char *name)
#define RSTRING_LENINT(str)
static void INSERT_ELEM_PREV(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
static LINK_ELEMENT * POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor)
#define CONST_ID(var, str)
VALUE rb_obj_freeze(VALUE)
#define SPECIAL_CONST_P(x)
#define ISEQ_COMPILE_DATA(iseq)
enum iseq_link_element::@0 type
static int compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int *cntp)
static void ibf_dump_object_symbol(struct ibf_dump *dump, VALUE obj)
static void add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return)
static struct rb_call_info * ibf_load_ci_entries(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
static VALUE ibf_load_object_regexp(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
#define RB_INTEGER_TYPE_P(obj)
static const struct rb_iseq_param_keyword * ibf_load_param_keyword(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
struct rb_global_entry * rb_global_entry(ID)
#define APPEND_LABEL(seq, before, label)
const rb_iseq_t * iseq_ibf_load(VALUE str)
static VALUE ibf_load_object_complex_rational(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
struct iseq_adjust_data ADJUST
VALUE rb_str_append(VALUE, VALUE)
static int eq(VALUE x, VALUE y)
#define NEW_NODE(t, a0, a1, a2)
static VALUE compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, NODE *cpath)
static int LIST_SIZE_ZERO(LINK_ANCHOR *const anchor)
static VALUE ibf_load_object_array(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
static VALUE ibf_load_location_str(const struct ibf_load *load, VALUE str_index)
static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
rb_encoding * rb_enc_find(const char *name)
static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
const struct ibf_header * header
#define iseq_absolute_path(iseq)
static VALUE ibf_load_object_string(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
#define RB_OBJ_WRITE(a, slot, b)
#define RUBY_EVENT_B_CALL
enum ruby_vminsn_type insn_id
static Bigint * mult(Bigint *a, Bigint *b)
rb_iseq_location_t location
#define ADD_INSN1(seq, line, insn, op1)
static int get_dyna_var_idx_at_raw(const rb_iseq_t *iseq, ID id)
#define IFUNC_NEW(a, b, c)
rb_encoding * rb_enc_from_index(int index)
VALUE rb_str_new(const char *, long)
static void dump_disasm_list(LINK_ELEMENT *elem)