16 #define USE_INSN_STACK_INCREASE 1 20 #include "insns_info.inc" 22 #define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG)) 23 #define FIXNUM_OR(n, i) ((n)|INT2FIX(i)) 95 #define compile_debug CPDEBUG 97 #define compile_debug iseq->compile_data->option->debug_level 102 #define compile_debug_print_indent(level) \ 103 ruby_debug_print_indent((level), compile_debug, gl_node_level * 2) 105 #define debugp(header, value) (void) \ 106 (compile_debug_print_indent(1) && \ 107 ruby_debug_print_value(1, compile_debug, (header), (value))) 109 #define debugi(header, id) (void) \ 110 (compile_debug_print_indent(1) && \ 111 ruby_debug_print_id(1, compile_debug, (header), (id))) 113 #define debugp_param(header, value) (void) \ 114 (compile_debug_print_indent(1) && \ 115 ruby_debug_print_value(1, compile_debug, (header), (value))) 117 #define debugp_verbose(header, value) (void) \ 118 (compile_debug_print_indent(2) && \ 119 ruby_debug_print_value(2, compile_debug, (header), (value))) 121 #define debugp_verbose_node(header, value) (void) \ 122 (compile_debug_print_indent(10) && \ 123 ruby_debug_print_value(10, compile_debug, (header), (value))) 125 #define debug_node_start(node) ((void) \ 126 (compile_debug_print_indent(1) && \ 127 (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)(node)), gl_node_level)), \ 130 #define debug_node_end() gl_node_level -- 146 #define debugi(header, id) r_id(id) 147 #define debugp(header, value) r_value(value) 148 #define debugp_verbose(header, value) r_value(value) 149 #define debugp_verbose_node(header, value) r_value(value) 150 #define debugp_param(header, value) r_value(value) 151 #define debug_node_start(node) ((void)0) 152 #define debug_node_end() ((void)0) 155 #if CPDEBUG > 1 || CPDEBUG < 0 156 #define debugs if (compile_debug_print_indent(1)) ruby_debug_printf 157 #define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v)) 159 #define debugs if(0)printf 160 #define debug_compile(msg, v) (v) 165 #define NEW_LABEL(l) new_label_body(iseq, (l)) 167 #define iseq_path(iseq) \ 168 (((rb_iseq_t*)DATA_PTR(iseq))->location.path) 170 #define iseq_absolute_path(iseq) \ 171 (((rb_iseq_t*)DATA_PTR(iseq))->location.absolute_path) 173 #define NEW_ISEQVAL(node, name, type, line_no) \ 174 new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no)) 176 #define NEW_CHILD_ISEQVAL(node, name, type, line_no) \ 177 new_child_iseq(iseq, (node), rb_fstring(name), iseq->self, (type), (line_no)) 180 #define ADD_SEQ(seq1, seq2) \ 181 APPEND_LIST((seq1), (seq2)) 184 #define ADD_INSN(seq, line, insn) \ 185 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0)) 188 #define ADD_INSN1(seq, line, insn, op1) \ 189 ADD_ELEM((seq), (LINK_ELEMENT *) \ 190 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1))) 193 #define ADD_INSNL(seq, line, insn, label) ADD_INSN1(seq, line, insn, label) 195 #define ADD_INSN2(seq, line, insn, op1, op2) \ 196 ADD_ELEM((seq), (LINK_ELEMENT *) \ 197 new_insn_body(iseq, (line), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2))) 199 #define ADD_INSN3(seq, line, insn, op1, op2, op3) \ 200 ADD_ELEM((seq), (LINK_ELEMENT *) \ 201 new_insn_body(iseq, (line), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3))) 204 #define ADD_SEND(seq, line, id, argc) \ 205 ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)INT2FIX(0)) 207 #define ADD_CALL_RECEIVER(seq, line) \ 208 ADD_INSN((seq), (line), putself) 210 #define ADD_CALL(seq, line, id, argc) \ 211 ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL)) 213 #define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \ 214 ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL)) 216 #define ADD_SEND_R(seq, line, id, argc, block, flag) \ 217 ADD_ELEM((seq), (LINK_ELEMENT *) \ 218 new_insn_send(iseq, (line), \ 219 (VALUE)(id), (VALUE)(argc), (VALUE)(block), (VALUE)(flag))) 221 #define ADD_TRACE(seq, line, event) \ 223 if ((event) == RUBY_EVENT_LINE && iseq->coverage && \ 224 (line) != iseq->compile_data->last_coverable_line) { \ 225 RARRAY_ASET(iseq->coverage, (line) - 1, INT2FIX(0)); \ 226 iseq->compile_data->last_coverable_line = (line); \ 227 ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \ 229 if (iseq->compile_data->option->trace_instruction) { \ 230 ADD_INSN1((seq), (line), trace, INT2FIX(event)); \ 235 #define ADD_LABEL(seq, label) \ 236 ADD_ELEM((seq), (LINK_ELEMENT *) (label)) 238 #define APPEND_LABEL(seq, before, label) \ 239 APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label)) 241 #define ADD_ADJUST(seq, line, label) \ 242 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), (line))) 244 #define ADD_ADJUST_RESTORE(seq, label) \ 245 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1)) 247 #define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \ 248 (rb_ary_push(iseq->compile_data->catch_table_ary, \ 249 rb_ary_new3(5, (type), \ 250 (VALUE)(ls) | 1, (VALUE)(le) | 1, \ 251 (VALUE)(iseqv), (VALUE)(lc) | 1))) 254 #define COMPILE(anchor, desc, node) \ 255 (debug_compile("== " desc "\n", \ 256 iseq_compile_each(iseq, (anchor), (node), 0))) 259 #define COMPILE_POPED(anchor, desc, node) \ 260 (debug_compile("== " desc "\n", \ 261 iseq_compile_each(iseq, (anchor), (node), 1))) 264 #define COMPILE_(anchor, desc, node, poped) \ 265 (debug_compile("== " desc "\n", \ 266 iseq_compile_each(iseq, (anchor), (node), (poped)))) 268 #define OPERAND_AT(insn, idx) \ 269 (((INSN*)(insn))->operands[(idx)]) 271 #define INSN_OF(insn) \ 272 (((INSN*)(insn))->insn_id) 275 #define COMPILE_ERROR(strs) \ 277 VALUE tmp = GET_THREAD()->errinfo; \ 278 if (compile_debug) rb_compile_bug strs; \ 279 GET_THREAD()->errinfo = iseq->compile_data->err_info; \ 280 rb_compile_error strs; \ 281 RB_OBJ_WRITE(iseq->self, &iseq->compile_data->err_info, GET_THREAD()->errinfo); \ 282 GET_THREAD()->errinfo = tmp; \ 287 #define ERROR_ARGS ruby_sourcefile, nd_line(node), 296 #define DECL_ANCHOR(name) \ 297 LINK_ANCHOR *name, name##_body__ = {{0,},} 298 #define INIT_ANCHOR(name) \ 299 (name##_body__.last = &name##_body__.anchor, name = &name##_body__) 301 #define hide_obj(obj) do {OBJ_FREEZE(obj); RBASIC_CLEAR_CLASS(obj);} while (0) 303 #include "optinsn.inc" 304 #if OPT_INSTRUCTIONS_UNIFICATION 305 #include "optunifs.inc" 310 #define ISEQ_ARG iseq, 311 #define ISEQ_ARG_DECLARE rb_iseq_t *iseq, 314 #define ISEQ_ARG_DECLARE 318 #define gl_node_level iseq->compile_data->node_level 363 if (plist !=
list->prev) {
370 if (anchor->
last != plist && anchor->
last != 0) {
375 rb_bug(
"list verify error: %08x (%s)", flag, info);
380 #define verify_list(info, anchor) verify_list(iseq, (info), (anchor)) 389 elem->
prev = anchor->last;
390 anchor->last->
next = elem;
405 if (before == anchor->last) anchor->last = elem;
409 #define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem)) 410 #define APPEND_ELEM(anchor, before, elem) ADD_ELEM(iseq, (anchor), (before), (elem)) 422 #define ruby_sourcefile RSTRING_PTR(iseq->location.path) 453 if (!
NIL_P(iseq->compile_data->err_info)) {
475 switch (iseq->
type) {
476 case ISEQ_TYPE_BLOCK:
483 COMPILE(ret,
"block body", node->nd_body);
492 case ISEQ_TYPE_CLASS:
495 COMPILE(ret,
"scoped node", node->nd_body);
499 case ISEQ_TYPE_METHOD:
502 COMPILE(ret,
"scoped node", node->nd_body);
507 COMPILE(ret,
"scoped node", node->nd_body);
514 (*node->nd_cfnc)(iseq, ret, node->nd_tval);
517 switch (iseq->
type) {
518 case ISEQ_TYPE_METHOD:
519 case ISEQ_TYPE_CLASS:
520 case ISEQ_TYPE_BLOCK:
527 case ISEQ_TYPE_RESCUE:
531 case ISEQ_TYPE_ENSURE:
535 case ISEQ_TYPE_DEFINED_GUARD:
537 COMPILE(ret,
"defined guard", node);
544 if (iseq->
type == ISEQ_TYPE_RESCUE || iseq->
type == ISEQ_TYPE_ENSURE) {
563 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE 572 int len = insn_len(insn);
592 #if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__) 593 #define STRICT_ALIGNMENT 596 #ifdef STRICT_ALIGNMENT 597 #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE 598 #define ALIGNMENT_SIZE SIZEOF_LONG_LONG 600 #define ALIGNMENT_SIZE SIZEOF_VALUE 602 #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1)) 603 #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX 606 #define PADDING_SIZE_MAX 0 609 #ifdef STRICT_ALIGNMENT 612 calc_padding(
void *ptr,
size_t size)
617 mis = (size_t)ptr & ALIGNMENT_SIZE_MASK;
619 padding = ALIGNMENT_SIZE - mis;
625 #if ALIGNMENT_SIZE > SIZEOF_VALUE 641 #ifdef STRICT_ALIGNMENT 642 size_t padding = calc_padding((
void *)&storage->
buff[storage->
pos],
size);
644 const size_t padding = 0;
647 if (storage->
pos +
size + padding > storage->
size) {
648 unsigned long alloc_size = storage->
size * 2;
661 storage->
size = alloc_size;
662 storage->
buff = (
char *)(&storage->
buff + 1);
663 #ifdef STRICT_ALIGNMENT 664 padding = calc_padding((
void *)&storage->
buff[storage->
pos],
size);
668 #ifdef STRICT_ALIGNMENT 669 storage->
pos += (int)padding;
672 ptr = (
void *)&storage->
buff[storage->
pos];
768 anchor->last = anchor->last->
prev;
769 anchor->last->
next = 0;
774 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor)) 827 anc1->last = anc2->
last;
832 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2)) 848 anc1->anchor.
next->
prev = &anc1->anchor;
854 anc1->last = anc2->
last;
861 #define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, (anc1), (anc2)) 885 #define SWAP_LIST(anc1, anc2) SWAP_LIST(iseq, (anc1), (anc2)) 892 first = &anc->anchor;
897 anc->anchor.next =
last;
919 #define REVERSE_LIST(anc) REVERSE_LIST(iseq, (anc)) 929 printf(
"anch: %p, frst: %p, last: %p\n", &anchor->anchor,
930 anchor->anchor.next, anchor->last);
932 printf(
"curr: %p, next: %p, prev: %p, type: %d\n",
list,
list->next,
942 #define debug_list(anc) debug_list(iseq, (anc)) 951 labelobj->
link.
type = ISEQ_ELEMENT_LABEL;
964 adjust->
link.
type = ISEQ_ELEMENT_ADJUST;
966 adjust->
label = label;
978 iobj->
link.
type = ISEQ_ELEMENT_INSN;
997 for (i = 0; i <
argc; i++) {
1040 return new_insn_core(iseq, line_no, BIN(send), 1, operands);
1049 debugs(
"[new_child_iseq]> ---------------------------------------\n");
1053 debugs(
"[new_child_iseq]< ---------------------------------------\n");
1066 debugs(
"[compile step 3.1 (iseq_optimize)]\n");
1073 debugs(
"[compile step 3.2 (iseq_insns_unification)]\n");
1080 debugs(
"[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
1086 debugs(
"[compile step 4.1 (iseq_set_sequence)]\n");
1091 debugs(
"[compile step 4.2 (iseq_set_exception_table)]\n");
1094 debugs(
"[compile step 4.3 (set_optargs_table)] \n");
1097 debugs(
"[compile step 5 (iseq_translate_threaded_code)] \n");
1105 debugs(
"[compile step: finish]\n");
1153 rb_bug(
"get_local_var_idx: %d", idx);
1162 int lv = 0, idx = -1;
1174 rb_bug(
"get_dyna_var_idx: -1");
1185 debugs(
"iseq_set_arguments: %s\n", node_args ?
"" :
"0");
1194 rb_bug(
"iseq_set_arguments: NODE_ARGS is expected, but %s",
1225 node = node->nd_next;
1238 for (j = 0; j < i; j++) {
1251 int i = 0, j, r = 0;
1257 if (node->nd_body->nd_value == (
NODE *)-1) {
1264 node = node->nd_next;
1273 keywords = required;
1275 for (j = 0; j < i; j++) {
1342 if (iseq->
type == ISEQ_TYPE_BLOCK) {
1345 if (iseq->
argc == 1 && last_comma == 0) {
1394 if (
val == lit)
return 0;
1447 unsigned int last_line = 0;
1449 VALUE *generated_iseq;
1451 int k, pos, sp, stack_max = 0, line = 0;
1457 switch (
list->type) {
1458 case ISEQ_ELEMENT_INSN:
1466 case ISEQ_ELEMENT_LABEL:
1473 case ISEQ_ELEMENT_NONE:
1478 case ISEQ_ELEMENT_ADJUST:
1491 "error: set_sequence");
1509 switch (
list->type) {
1510 case ISEQ_ELEMENT_INSN:
1520 if (sp > stack_max) {
1527 generated_iseq[pos] = insn;
1528 types = insn_op_types(insn);
1529 len = insn_len(insn);
1536 "operand size miss! (%d for %d)",
1538 xfree(generated_iseq);
1539 xfree(line_info_table);
1543 for (j = 0; types[j]; j++) {
1544 char type = types[j];
1550 lobj = (
LABEL *)operands[j];
1555 if (lobj->
sp == -1) {
1558 generated_iseq[pos + 1 + j] = lobj->
position - (pos + len);
1563 VALUE map = operands[j];
1571 generated_iseq[
pos + 1 + j] = map;
1576 generated_iseq[
pos + 1 + j] =
FIX2INT(operands[j]);
1580 VALUE v = operands[j];
1585 generated_iseq[
pos + 1 + j] = (
VALUE)block;
1590 VALUE v = operands[j];
1591 generated_iseq[
pos + 1 + j] = v;
1598 int ic_index =
FIX2INT(operands[j]);
1601 rb_bug(
"iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->
is_size);
1603 generated_iseq[
pos + 1 + j] = (
VALUE)ic;
1615 generated_iseq[
pos + 1 + j] = (
VALUE)ci;
1619 generated_iseq[
pos + 1 + j] =
SYM2ID(operands[j]);
1625 generated_iseq[pos + 1 + j] = (
VALUE)entry;
1630 "unknown operand type: %c",
type);
1631 xfree(generated_iseq);
1632 xfree(line_info_table);
1636 if (last_line != iobj->
line_no) {
1644 case ISEQ_ELEMENT_LABEL:
1647 if (lobj->
sp == -1) {
1655 case ISEQ_ELEMENT_ADJUST:
1660 if (adjust->
label) {
1668 if (orig_sp - sp > 0) {
1669 if (last_line != (
unsigned int)adjust->
line_no) {
1674 generated_iseq[pos++] = BIN(adjuststack);
1675 generated_iseq[pos++] = orig_sp - sp;
1677 else if (orig_sp - sp == 0) {
1679 if (last_line != (
unsigned int)adjust->
line_no) {
1684 generated_iseq[pos++] = BIN(jump);
1685 generated_iseq[pos++] = 0;
1688 rb_bug(
"iseq_set_sequence: adjust bug");
1707 iseq->
iseq = (
void *)generated_iseq;
1733 const VALUE *tptr, *ptr;
1741 iseq->catch_table_size = tlen;
1743 for (i = 0; i < tlen; i++) {
1745 entry = &
iseq->catch_table[i];
1749 entry->
iseq = ptr[3];
1752 if (entry->
iseq != 0) {
1792 if (
iseq->arg_opts != 0) {
1793 for (i = 0; i <
iseq->arg_opts; i++) {
1794 iseq->arg_opt_table[i] =
1809 if (
list->type == ISEQ_ELEMENT_INSN ||
list->type == ISEQ_ELEMENT_ADJUST) {
1823 if (
list->type == ISEQ_ELEMENT_INSN ||
list->type == ISEQ_ELEMENT_ADJUST) {
1837 if (
list->type == ISEQ_ELEMENT_INSN ||
list->type == ISEQ_ELEMENT_ADJUST) {
1850 if (iobj->
insn_id == BIN(jump)) {
1851 INSN *niobj, *diobj, *piobj;
1865 if (diobj == niobj) {
1874 else if (iobj != diobj && diobj->
insn_id == BIN(jump)) {
1880 else if (diobj->
insn_id == BIN(leave)) {
1916 (piobj->
insn_id == BIN(branchif) ||
1917 piobj->
insn_id == BIN(branchunless))) {
1920 ? BIN(branchunless) : BIN(branchif);
1927 if (iobj->
insn_id == BIN(branchif) ||
1928 iobj->
insn_id == BIN(branchunless)) {
1938 if (nobj->
insn_id == BIN(jump)) {
1943 if (do_tailcallopt && iobj->
insn_id == BIN(leave)) {
1952 enum ruby_vminsn_type previ = piobj->
insn_id;
1954 if (previ == BIN(send) || previ == BIN(opt_send_simple) || previ == BIN(invokesuper)) {
1973 if (insn_id != BIN(opt_neq)) {
1974 rb_bug(
"insn_set_specialized_instruction: unknown insn: %d", insn_id);
1977 iobj->
operands[0] = old_operands[0];
1987 if (iobj->
insn_id == BIN(send)) {
1990 #define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt)) 2027 iobj->
insn_id = BIN(opt_send_simple);
2039 const int do_peepholeopt =
iseq->compile_data->option->peephole_optimization;
2040 const int do_tailcallopt =
iseq->compile_data->option->tailcall_optimization;
2041 const int do_si =
iseq->compile_data->option->specialized_instruction;
2042 const int do_ou =
iseq->compile_data->option->operands_unification;
2046 if (
list->type == ISEQ_ELEMENT_INSN) {
2047 if (do_peepholeopt) {
2054 insn_operands_unification((
INSN *)
list);
2062 #if OPT_INSTRUCTIONS_UNIFICATION 2070 VALUE *operands = 0, *ptr = 0;
2074 for (i = 0; i <
size; i++) {
2087 for (i = 0; i <
size; i++) {
2106 #if OPT_INSTRUCTIONS_UNIFICATION 2114 if (
list->type == ISEQ_ELEMENT_INSN) {
2117 if (unified_insns_data[
id] != 0) {
2118 const int *
const *entry = unified_insns_data[
id];
2119 for (j = 1; j < (
intptr_t)entry[0]; j++) {
2120 const int *unified = entry[j];
2122 for (k = 2; k < unified[1]; k++) {
2123 if (li->
type != ISEQ_ELEMENT_INSN ||
2124 ((
INSN *)li)->insn_id != unified[k]) {
2131 new_unified_insn(
iseq, unified[0], unified[1] - 1,
2154 #if OPT_STACK_CACHING 2156 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)] 2157 #define SC_NEXT(insn) sc_insn_next[(insn)] 2159 #include "opt_sc.inc" 2168 iobj->
insn_id = SC_INSN(insn_id, state);
2169 nstate = SC_NEXT(iobj->
insn_id);
2171 if (insn_id == BIN(jump) ||
2172 insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
2179 printf(
"\n-- %d, %d\n", lobj->
sc_state, nstate);
2181 "insn_set_sc_state error\n");
2188 if (insn_id == BIN(jump)) {
2192 else if (insn_id == BIN(leave)) {
2200 label_set_sc_state(
LABEL *lobj,
int state)
2220 #if OPT_STACK_CACHING 2232 switch (
list->type) {
2233 case ISEQ_ELEMENT_INSN:
2244 if (state != SCS_AX) {
2257 if (state == SCS_AB || state == SCS_BA) {
2258 state = (state == SCS_AB ? SCS_BA : SCS_AB);
2294 state = insn_set_sc_state(
iseq, iobj, state);
2297 case ISEQ_ELEMENT_LABEL:
2302 state = label_set_sc_state(lobj, state);
2317 VALUE lit = node->nd_lit;
2324 lit = node->nd_lit =
rb_fstring(node->nd_lit);
2329 node =
list->nd_head;
2335 COMPILE(ret,
"each string", node);
2418 NODE *node = node_root;
2419 int line = (int)
nd_line(node);
2436 NODE *start_node = node, *end_node;
2438 const int max = 0x100;
2442 for (i=0; i<
max && node; i++, len++, node = node->nd_next) {
2458 COMPILE_(anchor,
"array element", node->nd_head, poped);
2468 while (node != end_node) {
2470 node = node->nd_next;
2475 node = node->nd_next;
2477 node = node->nd_next;
2519 ADD_INSN(anchor, line, concatarray);
2540 if (i > 0 || !first)
ADD_INSN(ret, line, swap);
2541 COMPILE(ret,
"keyword splat", kw);
2573 VALUE v = node->nd_lit;
2585 return node->nd_lit =
rb_fstring(node->nd_lit);
2598 only_special_literals = 0;
2622 vals = vals->nd_next;
2624 return only_special_literals;
2686 int llen = 0, rlen = 0;
2688 NODE *lhsn = orig_lhsn;
2690 #define MEMORY(v) { \ 2692 if (memindex == memsize) return 0; \ 2693 for (i=0; i<memindex; i++) { \ 2694 if (mem[i] == (v)) return 0; \ 2696 mem[memindex++] = (v); \ 2704 NODE *ln = lhsn->nd_head;
2719 lhsn = lhsn->nd_next;
2728 COMPILE(ret,
"masgn val", rhsn->nd_head);
2730 rhsn = rhsn->nd_next;
2735 for (i=0; i<llen-rlen; i++) {
2747 NODE *rhsn = node->nd_value;
2748 NODE *splatn = node->nd_args;
2749 NODE *lhsn = node->nd_head;
2750 int lhs_splat = (splatn && (
VALUE)splatn != (
VALUE)-1) ? 1 : 0;
2761 lhsn = lhsn->nd_next;
2764 COMPILE(ret,
"normal masgn rhs", rhsn);
2777 NODE *postn = splatn->nd_2nd;
2778 NODE *restn = splatn->nd_1st;
2779 int num = (int)postn->nd_alen;
2780 int flag = 0x02 | (((
VALUE)restn == (
VALUE)-1) ? 0x00 : 0x01);
2790 postn = postn->nd_next;
2808 debugi(
"compile_colon2 - colon", node->nd_vid);
2812 debugi(
"compile_colon2 - colon3", node->nd_mid);
2819 debugi(
"compile_colon2 - colon2", node->nd_mid);
2823 COMPILE(pref,
"const colon2 prefix", node);
2837 else if (cpath->nd_head) {
2839 COMPILE(ret,
"nd_else->nd_head", cpath->nd_head);
2850 #define defined_expr defined_expr0 2884 }
while ((vals = vals->nd_next) !=
NULL);
2904 ID2SYM(node->nd_vid), needstr);
2910 ID2SYM(node->nd_entry->
id), needstr);
2916 ID2SYM(node->nd_vid), needstr);
2922 ID2SYM(node->nd_vid), needstr);
2932 COMPILE(ret,
"defined/colon2#nd_head", node->nd_head);
2934 ID2SYM(node->nd_mid), needstr);
2937 COMPILE(ret,
"defined/colon2#nd_head", node->nd_head);
2939 ID2SYM(node->nd_mid), needstr);
2957 if (node->nd_recv == (
NODE *)1)
break;
2967 if (node->nd_args) {
2974 COMPILE(ret,
"defined/recv", node->nd_recv);
2976 ID2SYM(node->nd_mid), needstr);
2981 ID2SYM(node->nd_mid), needstr);
3043 int done = defined_expr0(
iseq, ret, node, lfinish, needstr);
3050 (
"defined guard in "),
3051 iseq->location.label),
3052 ISEQ_TYPE_DEFINED_GUARD, 0);
3060 #define BUFSIZE 0x100 3068 if (
iseq->parent_iseq != 0) {
3070 if (ip->
type == ISEQ_TYPE_BLOCK) {
3091 enl->
prev =
iseq->compile_data->ensure_node_stack;
3093 iseq->compile_data->ensure_node_stack = enl;
3103 while (erange->
next != 0) {
3104 erange = erange->
next;
3108 ne->end = erange->
end;
3109 erange->
end = lstart;
3160 COMPILE(arg_block,
"block", argn->nd_body);
3162 argn = argn->nd_head;
3169 COMPILE(args,
"args (splat)", argn->nd_head);
3181 COMPILE(tmp,
"args (cat: splat)", argn->nd_body);
3182 if (next_is_array && nsplat == 0) {
3197 if (next_is_array) {
3201 argn = argn->nd_head;
3218 for (i=1; i<nsplat; i++) {
3261 debugs(
"node: NODE_NIL(implicit)\n");
3276 saved_last_element = ret->
last;
3287 COMPILE_(ret,
"BLOCK body", node->nd_head,
3288 (node->nd_next == 0 && poped == 0) ? 0 : 1);
3289 node = node->nd_next;
3292 COMPILE_(ret,
"BLOCK next", node->nd_next, poped);
3300 LABEL *then_label, *else_label, *end_label;
3310 then_label, else_label);
3311 COMPILE_(then_seq,
"then", node->nd_body, poped);
3312 COMPILE_(else_seq,
"else", node->nd_else, poped);
3329 NODE *tempnode = node;
3330 LABEL *endlabel, *elselabel;
3334 int only_special_literals = 1;
3343 if (node->nd_head == 0) {
3344 COMPILE_(ret,
"when", node->nd_body, poped);
3349 node = node->nd_body;
3368 COMPILE_(body_seq,
"when body", node->nd_body, poped);
3369 ADD_INSNL(body_seq, line, jump, endlabel);
3371 vals = node->nd_head;
3375 only_special_literals =
when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
3380 only_special_literals = 0;
3382 COMPILE(cond_seq,
"when/cond splat", vals);
3387 rb_bug(
"NODE_CASE: unknown node (%s)",
3392 rb_bug(
"NODE_CASE: must be NODE_ARRAY, but 0");
3395 node = node->nd_next;
3406 COMPILE_(cond_seq,
"else", node, poped);
3407 ADD_INSNL(cond_seq, line, jump, endlabel);
3410 debugs(
"== else (implicit)\n");
3419 if (only_special_literals) {
3434 NODE *orig_node = node;
3444 COMPILE_(body_seq,
"when", node->nd_body, poped);
3445 ADD_INSNL(body_seq, line, jump, endlabel);
3447 vals = node->nd_head;
3449 rb_bug(
"NODE_WHEN: must be NODE_ARRAY, but 0");
3454 val = vals->nd_head;
3457 vals = vals->nd_next;
3464 COMPILE(ret,
"when2/cond splat", vals);
3469 rb_bug(
"NODE_WHEN: unknown node (%s)",
3472 node = node->nd_next;
3475 COMPILE_(ret,
"else", node, poped);
3515 if (tmp_label)
ADD_LABEL(ret, tmp_label);
3523 redo_label, end_label);
3528 end_label, redo_label);
3533 ADD_INSNL(ret, line, branchif, redo_label);
3539 if (node->nd_state ==
Qundef) {
3541 rb_bug(
"unsupported: putundef");
3575 COMPILE(ret,
"iter caller (for)", node->nd_iter);
3579 ISEQ_TYPE_BLOCK, line);
3587 ISEQ_TYPE_BLOCK, line);
3588 COMPILE(ret,
"iter caller", node->nd_iter);
3598 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, 0, retry_end_l);
3603 unsigned long level = 0;
3619 else if (iseq->
type == ISEQ_TYPE_BLOCK) {
3622 COMPILE(ret,
"break val (block)", node->nd_stts);
3628 else if (iseq->
type == ISEQ_TYPE_EVAL) {
3649 else if (ip->
type == ISEQ_TYPE_BLOCK) {
3653 else if (ip->
type == ISEQ_TYPE_EVAL) {
3664 unsigned long level = 0;
3668 debugs(
"next in while loop\n");
3670 COMPILE(ret,
"next val/valid syntax?", node->nd_stts);
3681 debugs(
"next in block\n");
3684 COMPILE(ret,
"next val", node->nd_stts);
3693 else if (iseq->
type == ISEQ_TYPE_EVAL) {
3706 level = 0x8000 | 0x4000;
3711 else if (ip->
type == ISEQ_TYPE_BLOCK) {
3714 else if (ip->
type == ISEQ_TYPE_EVAL) {
3721 COMPILE(ret,
"next val", node->nd_stts);
3747 else if (iseq->
type == ISEQ_TYPE_EVAL) {
3767 unsigned long level;
3768 level = 0x8000 | 0x4000;
3779 else if (ip->
type == ISEQ_TYPE_BLOCK) {
3782 else if (ip->
type == ISEQ_TYPE_EVAL) {
3803 if (iseq->
type == ISEQ_TYPE_RESCUE) {
3817 COMPILE_(ret,
"NODE_BEGIN", node->nd_body, poped);
3827 ISEQ_TYPE_RESCUE, line);
3830 COMPILE(ret,
"rescue head", node->nd_head);
3832 if (node->nd_else) {
3834 COMPILE(ret,
"rescue else", node->nd_else);
3851 LABEL *label_miss, *label_hit;
3857 narg = resq->nd_args;
3863 COMPILE(ret,
"rescue arg", narg->nd_head);
3865 ADD_INSNL(ret, line, branchif, label_hit);
3866 narg = narg->nd_next;
3873 COMPILE(ret,
"rescue/cond splat", narg);
3875 ADD_INSNL(ret, line, branchif, label_hit);
3878 rb_bug(
"NODE_RESBODY: unknown node (%s)",
3886 ADD_INSNL(ret, line, branchif, label_hit);
3890 COMPILE(ret,
"resbody body", resq->nd_body);
3896 resq = resq->nd_head;
3906 ISEQ_TYPE_ENSURE, line);
3923 COMPILE_(ret,
"ensure head", node->nd_head, poped);
3925 if (ensr->anchor.next == 0) {
3937 erange = erange->
next;
3947 COMPILE(ret,
"nd_1st", node->nd_1st);
3952 ADD_INSNL(ret, line, branchunless, end_label);
3955 ADD_INSNL(ret, line, branchif, end_label);
3960 COMPILE_(ret,
"nd_2nd", node->nd_2nd, poped);
3971 ID id = node->nd_vid;
3975 COMPILE(ret,
"rvalue", node->nd_value);
3987 COMPILE(ret,
"dvalue", node->nd_value);
4004 COMPILE(ret,
"lvalue", node->nd_value);
4010 ((
VALUE)node->nd_entry | 1));
4015 COMPILE(ret,
"lvalue", node->nd_value);
4019 ADD_INSN2(ret, line, setinstancevariable,
4024 COMPILE(ret,
"lvalue", node->nd_value);
4042 COMPILE(ret,
"cvasgn val", node->nd_value);
4054 ID id = node->nd_mid;
4083 COMPILE(ret,
"NODE_OP_ASGN1 recv", node->nd_recv);
4084 switch (
nd_type(node->nd_args->nd_head)) {
4098 if (
id == 0 ||
id == 1) {
4118 ADD_INSNL(ret, line, branchunless, label);
4122 COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body);
4158 COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body);
4191 ID atype = node->nd_next->nd_mid;
4236 COMPILE(ret,
"NODE_OP_ASGN2#recv", node->nd_recv);
4241 if (atype == 0 || atype == 1) {
4247 ADD_INSNL(ret, line, branchunless, lcfin);
4250 COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value);
4268 COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value);
4286 switch (
nd_type(node->nd_head)) {
4291 COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head);
4300 mid = node->nd_head->nd_mid;
4302 if (node->nd_aid == 0) {
4307 ADD_INSNL(ret, line, branchunless, lassign);
4312 if (node->nd_aid == 0 || node->nd_aid == 1) {
4314 if (!poped)
ADD_INSN(ret, line, dup);
4315 if (node->nd_aid == 0)
4318 ADD_INSNL(ret, line, branchunless, lfin);
4320 if (!poped)
ADD_INSN(ret, line, pop);
4322 COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value);
4332 if (!poped)
ADD_INSN(ret, line, swap);
4336 COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value);
4359 lassign = lfinish[1];
4363 ADD_INSNL(ret, line, branchunless, lassign);
4369 COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
4373 ADD_INSNL(ret, line, branchunless, lfin);
4381 COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_value", node->nd_value);
4392 node->nd_mid == idFreeze && node->nd_args ==
NULL)
4396 ADD_INSN1(ret, line, opt_str_freeze, str);
4411 ID mid = node->nd_mid;
4425 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
4427 if (mid == id_bitblt) {
4431 else if (mid == id_answer) {
4445 (mid == goto_id || mid == label_id)) {
4451 if (!labels_table) {
4456 SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
4458 label_name =
SYM2ID(node->nd_args->nd_head->nd_lit);
4465 label = (
LABEL *)data;
4473 if (mid == goto_id) {
4485 COMPILE(recv,
"recv", node->nd_recv);
4543 for (i = 0; i < liseq->
argc; i++) {
4552 for (j = 0; j < liseq->
arg_opts - 1; j++) {
4575 for (j=0; j<post_len; j++) {
4576 int idx = liseq->
local_size - (post_start + j);
4580 ADD_INSN (args, line, concatarray);
4585 for (j=0; j<post_len; j++) {
4586 int idx = liseq->
local_size - (post_start + j);
4589 argc = post_len + post_start;
4609 ADD_INSN (args, line, concatarray);
4640 COMPILE(ret,
"values item", n->nd_head);
4677 if (is->
type == ISEQ_TYPE_TOP) {
4683 if (is->
type == ISEQ_TYPE_METHOD) {
4689 COMPILE(ret,
"return nd_stts (return val)", node->nd_stts);
4691 if (is->
type == ISEQ_TYPE_METHOD) {
4717 if (iseq->
type == ISEQ_TYPE_TOP) {
4721 if (node->nd_head) {
4738 ID id = node->nd_vid;
4748 debugi(
"nd_vid", node->nd_vid);
4760 ((
VALUE)node->nd_entry | 1));
4767 debugi(
"nd_vid", node->nd_vid);
4769 ADD_INSN2(ret, line, getinstancevariable,
4775 debugi(
"nd_vid", node->nd_vid);
4779 int ic_index = iseq->
is_size++;
4805 if (!node->nd_nth) {
4817 INT2FIX(0x01 | (node->nd_nth << 1)));
4831 ADD_INSN1(recv, line, putobject, node->nd_lit);
4836 COMPILE(recv,
"receiver", node->nd_recv);
4840 COMPILE(recv,
"receiver", node->nd_value);
4847 if (recv->last == recv->anchor.next &&
4848 INSN_OF(recv->last) == BIN(putobject) &&
4874 ADD_INSN1(ret, line, putobject, node->nd_lit);
4882 ADD_INSN1(ret, line, putstring, node->nd_lit);
4897 ADD_INSN1(ret, line, putobject, node->nd_lit);
4916 COMPILE(ret,
"nd_body", node->nd_body);
4935 int ic_index = iseq->
is_size++;
4949 COMPILE(ret,
"argscat head", node->nd_head);
4952 COMPILE(ret,
"argscat body", node->nd_body);
4957 COMPILE(ret,
"argscat head", node->nd_head);
4958 COMPILE(ret,
"argscat body", node->nd_body);
4965 COMPILE(ret,
"arsgpush head", node->nd_head);
4968 COMPILE_(ret,
"argspush body", node->nd_body, poped);
4971 COMPILE(ret,
"arsgpush head", node->nd_head);
4972 COMPILE_(ret,
"argspush body", node->nd_body, poped);
4979 COMPILE(ret,
"splat", node->nd_head);
4990 ISEQ_TYPE_METHOD, line);
5010 ISEQ_TYPE_METHOD, line);
5015 COMPILE(ret,
"defs: recv", node->nd_recv);
5064 ISEQ_TYPE_CLASS, line);
5069 COMPILE(ret,
"super", node->nd_super);
5082 ISEQ_TYPE_CLASS, line);
5099 ISEQ_TYPE_CLASS, line);
5101 COMPILE(ret,
"sclass#recv", node->nd_recv);
5103 CONST_ID(singletonclass,
"singletonclass");
5105 ID2SYM(singletonclass), iseqval,
5117 int ic_index = iseq->
is_size++;
5148 COMPILE(ret,
"colon2#nd_head", node->nd_head);
5159 int ic_index = iseq->
is_size++;
5161 debugi(
"colon3#nd_mid", node->nd_mid);
5212 COMPILE(ret,
"flip2 beg", node->nd_beg);
5214 ADD_INSNL(ret, line, branchunless, lfin);
5226 COMPILE(ret,
"flip2 end", node->nd_end);
5227 ADD_INSNL(ret, line, branchunless, ltrue);
5263 if (iseq->
type == ISEQ_TYPE_RESCUE) {
5270 if (ip->
type == ISEQ_TYPE_RESCUE) {
5288 if (!node->nd_head) {
5311 int is_index = iseq->
is_size++;
5325 LABEL *end_label = 0;
5327 ID id = node->nd_body->nd_vid;
5332 ADD_INSNL(ret, line, branchunless, default_label);
5336 switch (
nd_type(node->nd_body)) {
5349 if (node->nd_body->nd_value != (
NODE *)-1) {
5354 if (node->nd_body->nd_value != (
NODE *)-1) {
5355 COMPILE_POPED(ret,
"keyword default argument", node->nd_body);
5380 if (node->nd_recv == (
NODE *) 1) {
5385 COMPILE(recv,
"recv", node->nd_recv);
5427 COMPILE_(ret,
"body", node->nd_body, poped);
5448 if (saved_last_element && ret &&
5449 ret->
last == saved_last_element &&
5450 ((
INSN *)saved_last_element)->insn_id == BIN(trace)) {
5465 return insn_len(iobj->
insn_id);
5499 const char *types = insn_op_types(iobj->
insn_id);
5502 for (j = 0; types[j]; j++) {
5503 char type = types[j];
5573 printf(
"-- raw disasm--------\n");
5576 switch (
link->type) {
5577 case ISEQ_ELEMENT_INSN:
5585 case ISEQ_ELEMENT_LABEL:
5588 printf(
"<L%03d>\n", lobj->
label_no);
5591 case ISEQ_ELEMENT_NONE:
5596 case ISEQ_ELEMENT_ADJUST:
5608 printf(
"---------------------\n");
5614 return insn_name_info[i];
5622 for (i = 0; i <
numberof(insn_name_info); i++) {
5635 if (
st_lookup(labels_table, obj, &tmp) == 0) {
5640 label = (
LABEL *)tmp;
5649 #define rb_intern(str) rb_intern_const(str) 5651 static VALUE symRescue, symEnsure, symRetry;
5652 static VALUE symBreak, symRedo, symNext;
5654 if (symRescue == 0) {
5663 if (
sym == symRescue)
return CATCH_TYPE_RESCUE;
5664 if (
sym == symEnsure)
return CATCH_TYPE_ENSURE;
5665 if (
sym == symRetry)
return CATCH_TYPE_RETRY;
5666 if (
sym == symBreak)
return CATCH_TYPE_BREAK;
5667 if (
sym == symRedo)
return CATCH_TYPE_REDO;
5668 if (
sym == symNext)
return CATCH_TYPE_NEXT;
5684 LABEL *lstart, *lend, *lcont;
5694 if (ptr[1] ==
Qnil) {
5720 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
5757 static struct st_table *insn_table;
5759 if (insn_table == 0) {
5763 for (i=0; i<len; i++) {
5787 if (
argc != insn_len((
VALUE)insn_id)-1) {
5789 "operand size mismatch");
5794 for (j=0; j<
argc; j++) {
5796 switch (insn_op_type((
VALUE)insn_id, j)) {
5836 unsigned long flag = 0;
5846 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
5854 "Symbol",
"to_sym");
5878 (
enum ruby_vminsn_type)insn_id,
argc,
argv));
5890 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary") 5891 #define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str") 5892 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym") 5950 for (i=0; i<
RARRAY_LEN(arg_opt_labels); i++) {
5975 while (iseq->
type == ISEQ_TYPE_BLOCK ||
5976 iseq->
type == ISEQ_TYPE_RESCUE ||
5977 iseq->
type == ISEQ_TYPE_ENSURE ||
5978 iseq->
type == ISEQ_TYPE_EVAL ||
5979 iseq->
type == ISEQ_TYPE_MAIN
#define RUBY_EVENT_B_RETURN
#define VM_CALL_ARGS_BLOCKARG
#define DEFAULT_SPECIAL_VAR_COUNT
struct rb_block_struct * blockptr
static int iseq_add_mark_object(rb_iseq_t *iseq, VALUE v)
static int iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
struct rb_global_entry * rb_global_entry(ID)
static VALUE compile_array(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node_root, enum compile_array_type_t type)
VALUE rb_ary_entry(VALUE ary, long offset)
struct iseq_link_element * next
void rb_bug(const char *fmt,...)
static void verify_list(ISEQ_ARG_DECLARE const char *info, LINK_ANCHOR *anchor)
void rb_compile_error(const char *file, int line, const char *fmt,...)
enum iseq_link_element::@1 type
#define OPERAND_AT(insn, idx)
static ADJUST * compile_data_alloc_adjust(rb_iseq_t *iseq)
#define ADD_INSN2(seq, line, insn, op1, op2)
#define RUBY_EVENT_RETURN
static int compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
static int insn_data_length(INSN *iobj)
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)
#define CPDEBUG
debug function(macro) interface depend on CPDEBUG if it is less than 0, runtime option is in effect...
struct ensure_range * next
int st_insert(st_table *, st_data_t, st_data_t)
struct iseq_compile_data * compile_data
VALUE rb_insns_name_array(void)
rb_call_info_t * callinfo_entries
#define ADD_INSN(seq, line, insn)
static INSN * compile_data_alloc_insn(rb_iseq_t *iseq)
static int compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
static LABEL * compile_data_alloc_label(rb_iseq_t *iseq)
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
static INSN * new_insn_send(rb_iseq_t *iseq, int line_no, VALUE id, VALUE argc, VALUE block, VALUE flag)
VALUE rb_ary_push(VALUE ary, VALUE item)
static int compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node_root, enum compile_array_type_t type, int poped)
void st_free_table(st_table *)
VALUE rb_str_concat(VALUE, VALUE)
static void validate_labels(rb_iseq_t *iseq, st_table *labels_table)
#define debugi(header, id)
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)
static int validate_label(st_data_t name, st_data_t label, st_data_t arg)
if((ID)(DISPID) nameid !=nameid)
struct rb_iseq_struct * local_iseq
void rb_raise(VALUE exc, const char *fmt,...)
struct iseq_label_data * start_label
VALUE rb_ary_clear(VALUE ary)
struct iseq_compile_data_storage * next
static int compile_colon2(rb_iseq_t *iseq, NODE *node, LINK_ANCHOR *pref, LINK_ANCHOR *body)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
const void ** rb_vm_get_insns_address_table(void)
static LINK_ELEMENT * POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor)
#define VM_CALL_ARGS_SPLAT
#define ADD_ADJUST(seq, line, label)
st_index_t rb_str_hash(VALUE)
#define VM_DEFINECLASS_FLAG_SCOPED
static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
VALUE rb_iseq_compile_node(VALUE self, NODE *node)
struct iseq_compile_data_ensure_node_stack * ensure_node_stack
static void APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2)
#define debug_node_start(node)
static void REMOVE_ELEM(LINK_ELEMENT *elem)
static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
static int get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls)
struct iseq_label_data LABEL
struct iseq_link_element LINK_ELEMENT
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)
const rb_compile_option_t * option
int tailcall_optimization
static int iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, VALUE body, struct st_table *labels_table)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
enum iseq_catch_table_entry::catch_type type
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
void rb_exc_raise(VALUE mesg)
static VALUE sym_inspect(VALUE sym)
int rb_is_const_id(ID id)
#define ADD_SEQ(seq1, seq2)
#define RB_TYPE_P(obj, type)
enum rb_iseq_struct::iseq_type type
static VALUE iseq_build_load_iseq(rb_iseq_t *iseq, VALUE op)
int st_lookup(st_table *, st_data_t, st_data_t *)
static int iseq_set_local_table(rb_iseq_t *iseq, ID *tbl)
#define MEMZERO(p, type, n)
static void ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *elem)
static INSN * new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc,...)
int specialized_instruction
static int compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *rhsn, NODE *orig_lhsn)
VALUE rb_dbl2big(double d)
#define ADD_TRACE(seq, line, event)
const char * rb_insns_name(int i)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
static VALUE CHECK_INTEGER(VALUE v)
#define VM_CALL_ARGS_SKIP_SETUP
int instructions_unification
RUBY_EXTERN VALUE rb_cObject
static LABEL * new_label_body(rb_iseq_t *iseq, long line)
#define NEW_ISEQVAL(node, name, type, line_no)
VALUE rb_str_cat2(VALUE, const char *)
struct iseq_link_anchor LINK_ANCHOR
static ADJUST * new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
int argc
argument information
static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
#define VM_DEFINECLASS_FLAG_HAS_SUPERCLASS
static int cdhash_cmp(VALUE val, VALUE lit)
#define ADD_SEND(seq, line, id, argc)
#define ADD_INSNL(seq, line, insn, label)
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]
#define ADD_CALL(seq, line, id, argc)
#define INIT_ANCHOR(name)
static LINK_ELEMENT * get_destination_insn(INSN *iobj)
static VALUE case_when_optimizable_literal(NODE *node)
#define MEMCPY(p1, p2, type, n)
#define COMPILE(anchor, desc, node)
static int get_dyna_var_idx_at_raw(rb_iseq_t *iseq, ID id)
int rb_parse_in_main(void)
static int iseq_set_optargs_table(rb_iseq_t *iseq)
struct ensure_range * erange
int link(const char *, const char *)
struct iseq_compile_data_ensure_node_stack * prev
union rb_call_info_struct::@166 aux
static int get_lvar_level(rb_iseq_t *iseq)
static int LIST_SIZE_ZERO(LINK_ANCHOR *anchor)
int rb_str_hash_cmp(VALUE, VALUE)
static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
ruby insn object list -> raw instruction sequence
static VALUE r_value(VALUE value)
int rb_dvar_defined(ID id)
#define ADD_SEND_R(seq, line, id, argc, block, flag)
#define ADD_LABEL(seq, label)
static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE *node)
#define RARRAY_CONST_PTR(a)
VALUE rb_sprintf(const char *format,...)
static int compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
struct iseq_insn_data INSN
static void REPLACE_ELEM(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
static VALUE build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *body)
static LINK_ELEMENT * get_next_insn(INSN *iobj)
VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, VALUE exception, VALUE body)
struct rb_iseq_struct * parent_iseq
struct iseq_label_data * redo_label
#define DECL_ANCHOR(name)
#define NEW_CHILD_ISEQVAL(node, name, type, line_no)
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)
static VALUE new_child_iseq(rb_iseq_t *iseq, NODE *node, VALUE name, VALUE parent, enum iseq_type type, int line_no)
#define ADD_CALL_RECEIVER(seq, line)
#define VM_CHECKMATCH_ARRAY
rb_iseq_location_t location
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)
#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc)
VALUE rb_str_new_cstr(const char *)
void * ruby_xrealloc(void *ptr, size_t new_size)
static int compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *cond, LABEL *then_label, LABEL *else_label)
#define RARRAY_LENINT(ary)
RUBY_EXTERN VALUE rb_cNumeric
st_table * st_init_numtable(void)
static const struct st_hash_type cdhash_type
static VALUE compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
#define ADD_INSN3(seq, line, insn, op1, op2, op3)
#define StringValueCStr(v)
static VALUE get_exception_sym2type(VALUE sym)
void rb_iseq_add_mark_object(rb_iseq_t *iseq, VALUE obj)
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)
#define va_init_list(a, b)
static int label_get_position(LABEL *lobj)
static void add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange, LABEL *lstart, LABEL *lend)
static int label_get_sp(LABEL *lobj)
#define COMPILE_POPED(anchor, desc, node)
static int compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
#define debugp_param(header, value)
#define RARRAY_AREF(a, i)
static VALUE insn_data_to_s_detail(INSN *iobj)
static int iseq_set_exception_table(rb_iseq_t *iseq)
VALUE rb_hash_aref(VALUE hash, VALUE key)
const char * ruby_node_name(int node)
VALUE rb_str_catf(VALUE str, const char *format,...)
struct iseq_compile_data_storage * storage_current
void rb_compile_warning(const char *file, int line, const char *fmt,...)
struct rb_encoding_entry * list
#define ADD_ADJUST_RESTORE(seq, label)
struct iseq_inline_cache_entry * IC
struct iseq_line_info_entry * line_info_table
VALUE rb_ary_dup(VALUE ary)
const struct st_hash_type * type
#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block)
VALUE rb_ary_concat(VALUE x, VALUE y)
static VALUE setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, VALUE *flag)
static rb_call_info_t * new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned long flag)
static const char * catch_type(int type)
static st_index_t cdhash_hash(VALUE a)
static struct st_table * insn_make_insn_table(void)
static void add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq, int is_return)
#define GetISeqPtr(obj, ptr)
#define COMPILE_ERROR(strs)
const char * rb_id2name(ID id)
struct iseq_label_data * end_label
#define StringValuePtr(v)
static void INSERT_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2)
#define COMPILE_(anchor, desc, node, poped)
static VALUE make_name_for_block(rb_iseq_t *iseq)
static int iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
static void APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *before, LINK_ELEMENT *elem)
#define CONST_ID(var, str)
VALUE rb_obj_freeze(VALUE)
VALUE(* call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci)
#define SPECIAL_CONST_P(x)
static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
int rb_parse_in_eval(void)
static int when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals)
#define APPEND_LABEL(seq, before, label)
static LINK_ELEMENT * FIRST_ELEMENT(LINK_ANCHOR *anchor)
static int get_local_var_idx(rb_iseq_t *iseq, ID id)
static int iseq_add_mark_object_compile_time(rb_iseq_t *iseq, VALUE v)
int rb_local_defined(ID id)
static rb_thread_t * GET_THREAD(void)
struct iseq_adjust_data ADJUST
static int eq(VALUE x, VALUE y)
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
#define NEW_NODE(t, a0, a1, a2)
VALUE rb_iseq_disasm(VALUE self)
static int compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int *cntp)
static void compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *lhsn)
#define iseq_absolute_path(iseq)
VALUE rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, VALUE parent, enum iseq_type type, const rb_compile_option_t *option)
#define RB_OBJ_WRITE(a, slot, b)
static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE *n, int)
compile each node
#define RUBY_EVENT_B_CALL
enum ruby_vminsn_type insn_id
static Bigint * mult(Bigint *a, Bigint *b)
int parse_in_eval
Thread-local state of evaluation context.
#define ADD_INSN1(seq, line, insn, op1)
union iseq_inline_storage_entry * is_entries
static void dump_disasm_list(LINK_ELEMENT *elem)