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);
593 if (storage->
pos + size > storage->
size) {
594 unsigned long alloc_size = storage->
size * 2;
597 if (alloc_size < size) {
607 storage->
size = alloc_size;
608 storage->
buff = (
char *)(&storage->
buff + 1);
611 ptr = (
void *)&storage->
buff[storage->
pos];
612 storage->
pos += size;
707 anchor->last = anchor->last->
prev;
708 anchor->last->
next = 0;
713 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor))
766 anc1->last = anc2->
last;
771 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
787 anc1->anchor.
next->
prev = &anc1->anchor;
793 anc1->last = anc2->
last;
800 #define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, (anc1), (anc2))
824 #define SWAP_LIST(anc1, anc2) SWAP_LIST(iseq, (anc1), (anc2))
831 first = &anc->anchor;
858 #define REVERSE_LIST(anc) REVERSE_LIST(iseq, (anc))
868 printf(
"anch: %p, frst: %p, last: %p\n", &anchor->anchor,
869 anchor->anchor.next, anchor->last);
871 printf(
"curr: %p, next: %p, prev: %p, type: %d\n", list, list->
next,
881 #define debug_list(anc) debug_list(iseq, (anc))
890 labelobj->
link.
type = ISEQ_ELEMENT_LABEL;
903 adjust->
link.
type = ISEQ_ELEMENT_ADJUST;
905 adjust->
label = label;
917 iobj->
link.
type = ISEQ_ELEMENT_INSN;
936 for (i = 0; i <
argc; i++) {
942 return new_insn_core(iseq, line_no, insn_id, argc, operands);
988 debugs(
"[new_child_iseq]> ---------------------------------------\n");
992 debugs(
"[new_child_iseq]< ---------------------------------------\n");
1005 debugs(
"[compile step 3.1 (iseq_optimize)]\n");
1012 debugs(
"[compile step 3.2 (iseq_insns_unification)]\n");
1019 debugs(
"[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
1025 debugs(
"[compile step 4.1 (iseq_set_sequence)]\n");
1030 debugs(
"[compile step 4.2 (iseq_set_exception_table)]\n");
1033 debugs(
"[compile step 4.3 (set_optargs_table)] \n");
1036 debugs(
"[compile step 5 (iseq_translate_threaded_code)] \n");
1044 debugs(
"[compile step: finish]\n");
1092 rb_bug(
"get_local_var_idx: %d", idx);
1101 int lv = 0, idx = -1;
1113 rb_bug(
"get_dyna_var_idx: -1");
1124 debugs(
"iseq_set_arguments: %s\n", node_args ?
"" :
"0");
1133 rb_bug(
"iseq_set_arguments: NODE_ARGS is expected, but %s",
1164 node = node->nd_next;
1177 for (j = 0; j < i; j++) {
1190 int i = 0, j, r = 0;
1195 VALUE list = keywords;
1196 if (node->nd_body->nd_value == (
NODE *)-1) {
1203 node = node->nd_next;
1212 keywords = required;
1214 for (j = 0; j < i; j++) {
1281 if (iseq->
type == ISEQ_TYPE_BLOCK) {
1284 if (iseq->
argc == 1 && last_comma == 0) {
1333 if (val == lit)
return 0;
1343 return !
rb_eql(lit, val);
1386 unsigned int last_line = 0;
1388 VALUE *generated_iseq;
1390 int k, pos, sp, stack_max = 0, line = 0;
1396 switch (list->
type) {
1397 case ISEQ_ELEMENT_INSN:
1399 iobj = (
INSN *)list;
1405 case ISEQ_ELEMENT_LABEL:
1407 lobj = (
LABEL *)list;
1412 case ISEQ_ELEMENT_NONE:
1417 case ISEQ_ELEMENT_ADJUST:
1430 "error: set_sequence");
1448 switch (list->
type) {
1449 case ISEQ_ELEMENT_INSN:
1455 iobj = (
INSN *)list;
1459 if (sp > stack_max) {
1466 generated_iseq[pos] = insn;
1467 types = insn_op_types(insn);
1468 len = insn_len(insn);
1475 "operand size miss! (%d for %d)",
1477 xfree(generated_iseq);
1478 xfree(line_info_table);
1482 for (j = 0; types[j]; j++) {
1483 char type = types[j];
1489 lobj = (
LABEL *)operands[j];
1494 if (lobj->
sp == -1) {
1497 generated_iseq[pos + 1 + j] = lobj->
position - (pos + len);
1502 VALUE map = operands[j];
1510 generated_iseq[pos + 1 + j] = map;
1515 generated_iseq[pos + 1 + j] =
FIX2INT(operands[j]);
1519 VALUE v = operands[j];
1524 generated_iseq[pos + 1 + j] = (
VALUE)block;
1529 VALUE v = operands[j];
1530 generated_iseq[pos + 1 + j] = v;
1537 int ic_index =
FIX2INT(operands[j]);
1540 rb_bug(
"iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->
is_size);
1542 generated_iseq[pos + 1 + j] = (
VALUE)ic;
1554 generated_iseq[pos + 1 + j] = (
VALUE)ci;
1558 generated_iseq[pos + 1 + j] =
SYM2ID(operands[j]);
1564 generated_iseq[pos + 1 + j] = (
VALUE)entry;
1569 "unknown operand type: %c", type);
1570 xfree(generated_iseq);
1571 xfree(line_info_table);
1575 if (last_line != iobj->
line_no) {
1583 case ISEQ_ELEMENT_LABEL:
1585 lobj = (
LABEL *)list;
1586 if (lobj->
sp == -1) {
1594 case ISEQ_ELEMENT_ADJUST:
1599 if (adjust->
label) {
1607 if (orig_sp - sp > 0) {
1608 if (last_line != (
unsigned int)adjust->
line_no) {
1613 generated_iseq[pos++] = BIN(adjuststack);
1614 generated_iseq[pos++] = orig_sp - sp;
1616 else if (orig_sp - sp == 0) {
1618 if (last_line != (
unsigned int)adjust->
line_no) {
1623 generated_iseq[pos++] = BIN(jump);
1624 generated_iseq[pos++] = 0;
1627 rb_bug(
"iseq_set_sequence: adjust bug");
1646 iseq->
iseq = (
void *)generated_iseq;
1672 const VALUE *tptr, *ptr;
1682 for (i = 0; i < tlen; i++) {
1688 entry->
iseq = ptr[3];
1691 if (entry->
iseq != 0) {
1732 for (i = 0; i < iseq->
arg_opts; i++) {
1748 if (list->
type == ISEQ_ELEMENT_INSN || list->
type == ISEQ_ELEMENT_ADJUST) {
1762 if (list->
type == ISEQ_ELEMENT_INSN || list->
type == ISEQ_ELEMENT_ADJUST) {
1776 if (list->
type == ISEQ_ELEMENT_INSN || list->
type == ISEQ_ELEMENT_ADJUST) {
1789 if (iobj->
insn_id == BIN(jump)) {
1790 INSN *niobj, *diobj, *piobj;
1804 if (diobj == niobj) {
1813 else if (iobj != diobj && diobj->
insn_id == BIN(jump)) {
1819 else if (diobj->
insn_id == BIN(leave)) {
1855 (piobj->
insn_id == BIN(branchif) ||
1856 piobj->
insn_id == BIN(branchunless))) {
1859 ? BIN(branchunless) : BIN(branchif);
1866 if (iobj->
insn_id == BIN(branchif) ||
1867 iobj->
insn_id == BIN(branchunless)) {
1877 if (nobj->
insn_id == BIN(jump)) {
1882 if (do_tailcallopt && iobj->
insn_id == BIN(leave)) {
1891 enum ruby_vminsn_type previ = piobj->
insn_id;
1893 if (previ == BIN(send) || previ == BIN(opt_send_simple) || previ == BIN(invokesuper)) {
1912 if (insn_id != BIN(opt_neq)) {
1913 rb_bug(
"insn_set_specialized_instruction: unknown insn: %d", insn_id);
1916 iobj->
operands[0] = old_operands[0];
1926 if (iobj->
insn_id == BIN(send)) {
1929 #define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
1966 iobj->
insn_id = BIN(opt_send_simple);
1985 if (list->
type == ISEQ_ELEMENT_INSN) {
1986 if (do_peepholeopt) {
1993 insn_operands_unification((
INSN *)list);
2001 #if OPT_INSTRUCTIONS_UNIFICATION
2009 VALUE *operands = 0, *ptr = 0;
2013 for (i = 0; i <
size; i++) {
2014 iobj = (
INSN *)list;
2026 for (i = 0; i <
size; i++) {
2027 iobj = (
INSN *)list;
2045 #if OPT_INSTRUCTIONS_UNIFICATION
2053 if (list->
type == ISEQ_ELEMENT_INSN) {
2054 iobj = (
INSN *)list;
2056 if (unified_insns_data[
id] != 0) {
2057 const int *
const *entry = unified_insns_data[
id];
2058 for (j = 1; j < (
intptr_t)entry[0]; j++) {
2059 const int *unified = entry[j];
2061 for (k = 2; k < unified[1]; k++) {
2062 if (li->
type != ISEQ_ELEMENT_INSN ||
2063 ((
INSN *)li)->insn_id != unified[k]) {
2070 new_unified_insn(iseq, unified[0], unified[1] - 1,
2093 #if OPT_STACK_CACHING
2095 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
2096 #define SC_NEXT(insn) sc_insn_next[(insn)]
2098 #include "opt_sc.inc"
2107 iobj->
insn_id = SC_INSN(insn_id, state);
2108 nstate = SC_NEXT(iobj->
insn_id);
2110 if (insn_id == BIN(jump) ||
2111 insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
2118 printf(
"\n-- %d, %d\n", lobj->
sc_state, nstate);
2120 "insn_set_sc_state error\n");
2127 if (insn_id == BIN(jump)) {
2131 else if (insn_id == BIN(leave)) {
2139 label_set_sc_state(
LABEL *lobj,
int state)
2159 #if OPT_STACK_CACHING
2171 switch (list->
type) {
2172 case ISEQ_ELEMENT_INSN:
2183 if (state != SCS_AX) {
2196 if (state == SCS_AB || state == SCS_BA) {
2197 state = (state == SCS_AB ? SCS_BA : SCS_AB);
2233 state = insn_set_sc_state(iseq, iobj, state);
2236 case ISEQ_ELEMENT_LABEL:
2239 lobj = (
LABEL *)list;
2241 state = label_set_sc_state(lobj, state);
2255 NODE *list = node->nd_next;
2256 VALUE lit = node->nd_lit;
2263 lit = node->nd_lit =
rb_fstring(node->nd_lit);
2268 node = list->nd_head;
2274 COMPILE(ret,
"each string", node);
2277 list = list->nd_next;
2339 COMPILE(ret,
"branch condition", cond);
2357 NODE *node = node_root;
2358 int line = (int)
nd_line(node);
2375 NODE *start_node = node, *end_node;
2377 const int max = 0x100;
2381 for (i=0; i<max && node; i++, len++, node = node->nd_next) {
2397 COMPILE_(anchor,
"array element", node->nd_head, poped);
2407 while (node != end_node) {
2409 node = node->nd_next;
2414 node = node->nd_next;
2416 node = node->nd_next;
2458 ADD_INSN(anchor, line, concatarray);
2479 if (i > 0 || !first)
ADD_INSN(ret, line, swap);
2480 COMPILE(ret,
"keyword splat", kw);
2512 VALUE v = node->nd_lit;
2524 return node->nd_lit =
rb_fstring(node->nd_lit);
2537 only_special_literals = 0;
2556 COMPILE(cond_seq,
"when cond", val);
2561 vals = vals->nd_next;
2563 return only_special_literals;
2625 int llen = 0, rlen = 0;
2627 NODE *lhsn = orig_lhsn;
2629 #define MEMORY(v) { \
2631 if (memindex == memsize) return 0; \
2632 for (i=0; i<memindex; i++) { \
2633 if (mem[i] == (v)) return 0; \
2635 mem[memindex++] = (v); \
2643 NODE *ln = lhsn->nd_head;
2658 lhsn = lhsn->nd_next;
2667 COMPILE(ret,
"masgn val", rhsn->nd_head);
2669 rhsn = rhsn->nd_next;
2674 for (i=0; i<llen-rlen; i++) {
2686 NODE *rhsn = node->nd_value;
2687 NODE *splatn = node->nd_args;
2688 NODE *lhsn = node->nd_head;
2689 int lhs_splat = (splatn && (
VALUE)splatn != (
VALUE)-1) ? 1 : 0;
2700 lhsn = lhsn->nd_next;
2703 COMPILE(ret,
"normal masgn rhs", rhsn);
2716 NODE *postn = splatn->nd_2nd;
2717 NODE *restn = splatn->nd_1st;
2718 int num = (int)postn->nd_alen;
2719 int flag = 0x02 | (((
VALUE)restn == (
VALUE)-1) ? 0x00 : 0x01);
2729 postn = postn->nd_next;
2747 debugi(
"compile_colon2 - colon", node->nd_vid);
2751 debugi(
"compile_colon2 - colon3", node->nd_mid);
2758 debugi(
"compile_colon2 - colon2", node->nd_mid);
2762 COMPILE(pref,
"const colon2 prefix", node);
2776 else if (cpath->nd_head) {
2778 COMPILE(ret,
"nd_else->nd_head", cpath->nd_head);
2789 #define defined_expr defined_expr0
2797 switch (type =
nd_type(node)) {
2823 }
while ((vals = vals->nd_next) !=
NULL);
2843 ID2SYM(node->nd_vid), needstr);
2849 ID2SYM(node->nd_entry->
id), needstr);
2855 ID2SYM(node->nd_vid), needstr);
2861 ID2SYM(node->nd_vid), needstr);
2871 COMPILE(ret,
"defined/colon2#nd_head", node->nd_head);
2873 ID2SYM(node->nd_mid), needstr);
2876 COMPILE(ret,
"defined/colon2#nd_head", node->nd_head);
2878 ID2SYM(node->nd_mid), needstr);
2896 if (node->nd_recv == (
NODE *)1)
break;
2906 if (node->nd_args) {
2913 COMPILE(ret,
"defined/recv", node->nd_recv);
2915 ID2SYM(node->nd_mid), needstr);
2920 ID2SYM(node->nd_mid), needstr);
2982 int done = defined_expr0(iseq, ret, node, lfinish, needstr);
2989 (
"defined guard in "),
2991 ISEQ_TYPE_DEFINED_GUARD, 0);
2999 #define BUFSIZE 0x100
3009 if (ip->
type == ISEQ_TYPE_BLOCK) {
3042 while (erange->
next != 0) {
3043 erange = erange->
next;
3048 erange->
end = lstart;
3099 COMPILE(arg_block,
"block", argn->nd_body);
3101 argn = argn->nd_head;
3108 COMPILE(args,
"args (splat)", argn->nd_head);
3120 COMPILE(tmp,
"args (cat: splat)", argn->nd_body);
3121 if (next_is_array && nsplat == 0) {
3136 if (next_is_array) {
3140 argn = argn->nd_head;
3157 for (i=1; i<nsplat; i++) {
3200 debugs(
"node: NODE_NIL(implicit)\n");
3213 saved_last_element = ret->
last;
3219 COMPILE_(ret,
"BLOCK body", node->nd_head,
3220 (node->nd_next == 0 && poped == 0) ? 0 : 1);
3221 node = node->nd_next;
3224 COMPILE_(ret,
"BLOCK next", node->nd_next, poped);
3232 LABEL *then_label, *else_label, *end_label;
3242 then_label, else_label);
3243 COMPILE_(then_seq,
"then", node->nd_body, poped);
3244 COMPILE_(else_seq,
"else", node->nd_else, poped);
3261 NODE *tempnode = node;
3262 LABEL *endlabel, *elselabel;
3266 int only_special_literals = 1;
3275 if (node->nd_head == 0) {
3276 COMPILE_(ret,
"when", node->nd_body, poped);
3281 node = node->nd_body;
3300 COMPILE_(body_seq,
"when body", node->nd_body, poped);
3301 ADD_INSNL(body_seq, line, jump, endlabel);
3303 vals = node->nd_head;
3307 only_special_literals =
when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
3312 only_special_literals = 0;
3314 COMPILE(cond_seq,
"when/cond splat", vals);
3319 rb_bug(
"NODE_CASE: unknown node (%s)",
3324 rb_bug(
"NODE_CASE: must be NODE_ARRAY, but 0");
3327 node = node->nd_next;
3338 COMPILE_(cond_seq,
"else", node, poped);
3339 ADD_INSNL(cond_seq, line, jump, endlabel);
3342 debugs(
"== else (implicit)\n");
3351 if (only_special_literals) {
3366 NODE *orig_node = node;
3376 COMPILE_(body_seq,
"when", node->nd_body, poped);
3377 ADD_INSNL(body_seq, line, jump, endlabel);
3379 vals = node->nd_head;
3381 rb_bug(
"NODE_WHEN: must be NODE_ARRAY, but 0");
3386 val = vals->nd_head;
3389 vals = vals->nd_next;
3396 COMPILE(ret,
"when2/cond splat", vals);
3401 rb_bug(
"NODE_WHEN: unknown node (%s)",
3404 node = node->nd_next;
3407 COMPILE_(ret,
"else", node, poped);
3436 if (type ==
NODE_OPT_N || node->nd_state == 1) {
3447 if (tmp_label)
ADD_LABEL(ret, tmp_label);
3455 redo_label, end_label);
3460 end_label, redo_label);
3465 ADD_INSNL(ret, line, branchif, redo_label);
3471 if (node->nd_state ==
Qundef) {
3473 rb_bug(
"unsupported: putundef");
3507 COMPILE(ret,
"iter caller (for)", node->nd_iter);
3511 ISEQ_TYPE_BLOCK, line);
3519 ISEQ_TYPE_BLOCK, line);
3520 COMPILE(ret,
"iter caller", node->nd_iter);
3530 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, 0, retry_end_l);
3535 unsigned long level = 0;
3551 else if (iseq->
type == ISEQ_TYPE_BLOCK) {
3554 COMPILE(ret,
"break val (block)", node->nd_stts);
3560 else if (iseq->
type == ISEQ_TYPE_EVAL) {
3581 else if (ip->
type == ISEQ_TYPE_BLOCK) {
3585 else if (ip->
type == ISEQ_TYPE_EVAL) {
3596 unsigned long level = 0;
3600 debugs(
"next in while loop\n");
3602 COMPILE(ret,
"next val/valid syntax?", node->nd_stts);
3613 debugs(
"next in block\n");
3616 COMPILE(ret,
"next val", node->nd_stts);
3625 else if (iseq->
type == ISEQ_TYPE_EVAL) {
3638 level = 0x8000 | 0x4000;
3643 else if (ip->
type == ISEQ_TYPE_BLOCK) {
3646 else if (ip->
type == ISEQ_TYPE_EVAL) {
3653 COMPILE(ret,
"next val", node->nd_stts);
3679 else if (iseq->
type == ISEQ_TYPE_EVAL) {
3699 unsigned long level;
3700 level = 0x8000 | 0x4000;
3711 else if (ip->
type == ISEQ_TYPE_BLOCK) {
3714 else if (ip->
type == ISEQ_TYPE_EVAL) {
3735 if (iseq->
type == ISEQ_TYPE_RESCUE) {
3749 COMPILE_(ret,
"NODE_BEGIN", node->nd_body, poped);
3759 ISEQ_TYPE_RESCUE, line);
3762 COMPILE(ret,
"rescue head", node->nd_head);
3764 if (node->nd_else) {
3766 COMPILE(ret,
"rescue else", node->nd_else);
3783 LABEL *label_miss, *label_hit;
3789 narg = resq->nd_args;
3795 COMPILE(ret,
"rescue arg", narg->nd_head);
3797 ADD_INSNL(ret, line, branchif, label_hit);
3798 narg = narg->nd_next;
3805 COMPILE(ret,
"rescue/cond splat", narg);
3807 ADD_INSNL(ret, line, branchif, label_hit);
3810 rb_bug(
"NODE_RESBODY: unknown node (%s)",
3818 ADD_INSNL(ret, line, branchif, label_hit);
3822 COMPILE(ret,
"resbody body", resq->nd_body);
3828 resq = resq->nd_head;
3838 ISEQ_TYPE_ENSURE, line);
3855 COMPILE_(ret,
"ensure head", node->nd_head, poped);
3857 if (ensr->anchor.next == 0) {
3869 erange = erange->
next;
3879 COMPILE(ret,
"nd_1st", node->nd_1st);
3884 ADD_INSNL(ret, line, branchunless, end_label);
3887 ADD_INSNL(ret, line, branchif, end_label);
3892 COMPILE_(ret,
"nd_2nd", node->nd_2nd, poped);
3903 ID id = node->nd_vid;
3907 COMPILE(ret,
"rvalue", node->nd_value);
3919 COMPILE(ret,
"dvalue", node->nd_value);
3936 COMPILE(ret,
"lvalue", node->nd_value);
3942 ((
VALUE)node->nd_entry | 1));
3947 COMPILE(ret,
"lvalue", node->nd_value);
3951 ADD_INSN2(ret, line, setinstancevariable,
3956 COMPILE(ret,
"lvalue", node->nd_value);
3974 COMPILE(ret,
"cvasgn val", node->nd_value);
3986 ID id = node->nd_mid;
4015 COMPILE(ret,
"NODE_OP_ASGN1 recv", node->nd_recv);
4016 switch (
nd_type(node->nd_args->nd_head)) {
4024 argc =
setup_args(iseq, args, node->nd_args->nd_head, &flag);
4030 if (
id == 0 ||
id == 1) {
4050 ADD_INSNL(ret, line, branchunless, label);
4054 COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body);
4090 COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body);
4123 ID atype = node->nd_next->nd_mid;
4168 COMPILE(ret,
"NODE_OP_ASGN2#recv", node->nd_recv);
4173 if (atype == 0 || atype == 1) {
4179 ADD_INSNL(ret, line, branchunless, lcfin);
4182 COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value);
4200 COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value);
4218 switch (
nd_type(node->nd_head)) {
4223 COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head);
4232 mid = node->nd_head->nd_mid;
4234 if (node->nd_aid == 0) {
4239 ADD_INSNL(ret, line, branchunless, lassign);
4244 if (node->nd_aid == 0 || node->nd_aid == 1) {
4246 if (!poped)
ADD_INSN(ret, line, dup);
4247 if (node->nd_aid == 0)
4250 ADD_INSNL(ret, line, branchunless, lfin);
4252 if (!poped)
ADD_INSN(ret, line, pop);
4254 COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value);
4264 if (!poped)
ADD_INSN(ret, line, swap);
4268 COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value);
4291 lassign = lfinish[1];
4295 ADD_INSNL(ret, line, branchunless, lassign);
4301 COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
4305 ADD_INSNL(ret, line, branchunless, lfin);
4313 COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_value", node->nd_value);
4324 node->nd_mid == idFreeze && node->nd_args ==
NULL)
4328 ADD_INSN1(ret, line, opt_str_freeze, str);
4343 ID mid = node->nd_mid;
4357 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
4359 if (mid == id_bitblt) {
4363 else if (mid == id_answer) {
4377 (mid == goto_id || mid == label_id)) {
4383 if (!labels_table) {
4388 SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
4390 label_name =
SYM2ID(node->nd_args->nd_head->nd_lit);
4397 label = (
LABEL *)data;
4405 if (mid == goto_id) {
4417 COMPILE(recv,
"recv", node->nd_recv);
4425 argc =
setup_args(iseq, args, node->nd_args, &flag);
4446 argc, parent_block,
LONG2FIX(flag));
4475 for (i = 0; i < liseq->
argc; i++) {
4484 for (j = 0; j < liseq->
arg_opts - 1; j++) {
4507 for (j=0; j<post_len; j++) {
4508 int idx = liseq->
local_size - (post_start + j);
4512 ADD_INSN (args, line, concatarray);
4517 for (j=0; j<post_len; j++) {
4518 int idx = liseq->
local_size - (post_start + j);
4521 argc = post_len + post_start;
4541 ADD_INSN (args, line, concatarray);
4572 COMPILE(ret,
"values item", n->nd_head);
4609 if (is->
type == ISEQ_TYPE_TOP) {
4615 if (is->
type == ISEQ_TYPE_METHOD) {
4621 COMPILE(ret,
"return nd_stts (return val)", node->nd_stts);
4623 if (is->
type == ISEQ_TYPE_METHOD) {
4649 if (iseq->
type == ISEQ_TYPE_TOP) {
4653 if (node->nd_head) {
4654 argc =
setup_args(iseq, args, node->nd_head, &flag);
4670 ID id = node->nd_vid;
4680 debugi(
"nd_vid", node->nd_vid);
4692 ((
VALUE)node->nd_entry | 1));
4699 debugi(
"nd_vid", node->nd_vid);
4701 ADD_INSN2(ret, line, getinstancevariable,
4707 debugi(
"nd_vid", node->nd_vid);
4711 int ic_index = iseq->
is_size++;
4745 INT2FIX(0x01 | (node->nd_nth << 1)));
4759 ADD_INSN1(recv, line, putobject, node->nd_lit);
4764 COMPILE(recv,
"receiver", node->nd_recv);
4768 COMPILE(recv,
"receiver", node->nd_value);
4775 if (recv->last == recv->anchor.next &&
4776 INSN_OF(recv->last) == BIN(putobject) &&
4802 ADD_INSN1(ret, line, putobject, node->nd_lit);
4810 ADD_INSN1(ret, line, putstring, node->nd_lit);
4825 ADD_INSN1(ret, line, putobject, node->nd_lit);
4844 COMPILE(ret,
"nd_body", node->nd_body);
4863 int ic_index = iseq->
is_size++;
4877 COMPILE(ret,
"argscat head", node->nd_head);
4880 COMPILE(ret,
"argscat body", node->nd_body);
4885 COMPILE(ret,
"argscat head", node->nd_head);
4886 COMPILE(ret,
"argscat body", node->nd_body);
4893 COMPILE(ret,
"arsgpush head", node->nd_head);
4896 COMPILE_(ret,
"argspush body", node->nd_body, poped);
4899 COMPILE(ret,
"arsgpush head", node->nd_head);
4900 COMPILE_(ret,
"argspush body", node->nd_body, poped);
4907 COMPILE(ret,
"splat", node->nd_head);
4918 ISEQ_TYPE_METHOD, line);
4938 ISEQ_TYPE_METHOD, line);
4943 COMPILE(ret,
"defs: recv", node->nd_recv);
4992 ISEQ_TYPE_CLASS, line);
4997 COMPILE(ret,
"super", node->nd_super);
5010 ISEQ_TYPE_CLASS, line);
5027 ISEQ_TYPE_CLASS, line);
5029 COMPILE(ret,
"sclass#recv", node->nd_recv);
5031 CONST_ID(singletonclass,
"singletonclass");
5033 ID2SYM(singletonclass), iseqval,
5045 int ic_index = iseq->
is_size++;
5076 COMPILE(ret,
"colon2#nd_head", node->nd_head);
5087 int ic_index = iseq->
is_size++;
5089 debugi(
"colon3#nd_mid", node->nd_mid);
5140 COMPILE(ret,
"flip2 beg", node->nd_beg);
5142 ADD_INSNL(ret, line, branchunless, lfin);
5154 COMPILE(ret,
"flip2 end", node->nd_end);
5155 ADD_INSNL(ret, line, branchunless, ltrue);
5191 if (iseq->
type == ISEQ_TYPE_RESCUE) {
5198 if (ip->
type == ISEQ_TYPE_RESCUE) {
5216 if (!node->nd_head) {
5239 int is_index = iseq->
is_size++;
5253 LABEL *end_label = 0;
5255 ID id = node->nd_body->nd_vid;
5260 ADD_INSNL(ret, line, branchunless, default_label);
5264 switch (
nd_type(node->nd_body)) {
5277 if (node->nd_body->nd_value != (
NODE *)-1) {
5282 if (node->nd_body->nd_value != (
NODE *)-1) {
5283 COMPILE_POPED(ret,
"keyword default argument", node->nd_body);
5306 argc =
setup_args(iseq, args, node->nd_args, &flag);
5308 if (node->nd_recv == (
NODE *) 1) {
5313 COMPILE(recv,
"recv", node->nd_recv);
5355 COMPILE_(ret,
"body", node->nd_body, poped);
5376 if (saved_last_element && ret &&
5377 ret->
last == saved_last_element &&
5378 ((
INSN *)saved_last_element)->insn_id == BIN(trace)) {
5393 return insn_len(iobj->
insn_id);
5427 const char *types = insn_op_types(iobj->
insn_id);
5430 for (j = 0; types[j]; j++) {
5431 char type = types[j];
5501 printf(
"-- raw disasm--------\n");
5504 switch (link->
type) {
5505 case ISEQ_ELEMENT_INSN:
5507 iobj = (
INSN *)link;
5513 case ISEQ_ELEMENT_LABEL:
5515 lobj = (
LABEL *)link;
5516 printf(
"<L%03d>\n", lobj->
label_no);
5519 case ISEQ_ELEMENT_NONE:
5524 case ISEQ_ELEMENT_ADJUST:
5536 printf(
"---------------------\n");
5542 return insn_name_info[i];
5550 for (i = 0; i <
numberof(insn_name_info); i++) {
5563 if (
st_lookup(labels_table, obj, &tmp) == 0) {
5568 label = (
LABEL *)tmp;
5577 #define rb_intern(str) rb_intern_const(str)
5579 static VALUE symRescue, symEnsure, symRetry;
5580 static VALUE symBreak, symRedo, symNext;
5582 if (symRescue == 0) {
5591 if (sym == symRescue)
return CATCH_TYPE_RESCUE;
5592 if (sym == symEnsure)
return CATCH_TYPE_ENSURE;
5593 if (sym == symRetry)
return CATCH_TYPE_RETRY;
5594 if (sym == symBreak)
return CATCH_TYPE_BREAK;
5595 if (sym == symRedo)
return CATCH_TYPE_REDO;
5596 if (sym == symNext)
return CATCH_TYPE_NEXT;
5612 LABEL *lstart, *lend, *lcont;
5622 if (ptr[1] ==
Qnil) {
5648 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
5685 static struct st_table *insn_table;
5687 if (insn_table == 0) {
5691 for (i=0; i<len; i++) {
5715 if (argc != insn_len((
VALUE)insn_id)-1) {
5717 "operand size mismatch");
5722 for (j=0; j<
argc; j++) {
5724 switch (insn_op_type((
VALUE)insn_id, j)) {
5727 argv[j] = (
VALUE)label;
5764 unsigned long flag = 0;
5774 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
5782 "Symbol",
"to_sym");
5806 (
enum ruby_vminsn_type)insn_id, argc, argv));
5818 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary")
5819 #define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str")
5820 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym")
5878 for (i=0; i<
RARRAY_LEN(arg_opt_labels); i++) {
5903 while (iseq->
type == ISEQ_TYPE_BLOCK ||
5904 iseq->
type == ISEQ_TYPE_RESCUE ||
5905 iseq->
type == ISEQ_TYPE_ENSURE ||
5906 iseq->
type == ISEQ_TYPE_EVAL ||
5907 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)
VALUE(* call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci)
static int validate_label(st_data_t name, st_data_t label, st_data_t arg)
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
int peephole_optimization
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)
const VALUE catch_table_ary
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)
if((ID)(DISPID) nameid!=nameid)
#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
struct iseq_catch_table_entry * catch_table
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)
#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)