12#include "ruby/internal/config.h"
22#include "internal/array.h"
23#include "internal/compile.h"
24#include "internal/complex.h"
25#include "internal/encoding.h"
26#include "internal/error.h"
27#include "internal/gc.h"
28#include "internal/hash.h"
29#include "internal/numeric.h"
30#include "internal/object.h"
31#include "internal/rational.h"
32#include "internal/re.h"
33#include "internal/symbol.h"
34#include "internal/thread.h"
35#include "internal/variable.h"
40#include "vm_callinfo.h"
46#include "insns_info.inc"
48#undef RUBY_UNTYPED_DATA_WARNING
49#define RUBY_UNTYPED_DATA_WARNING 0
51#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
52#define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
86 unsigned int rescued: 2;
87 unsigned int unremovable: 1;
92 enum ruby_vminsn_type insn_id;
122 const void *ensure_node;
127const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO};
147#define compile_debug CPDEBUG
149#define compile_debug ISEQ_COMPILE_DATA(iseq)->option->debug_level
154#define compile_debug_print_indent(level) \
155 ruby_debug_print_indent((level), compile_debug, gl_node_level * 2)
157#define debugp(header, value) (void) \
158 (compile_debug_print_indent(1) && \
159 ruby_debug_print_value(1, compile_debug, (header), (value)))
161#define debugi(header, id) (void) \
162 (compile_debug_print_indent(1) && \
163 ruby_debug_print_id(1, compile_debug, (header), (id)))
165#define debugp_param(header, value) (void) \
166 (compile_debug_print_indent(1) && \
167 ruby_debug_print_value(1, compile_debug, (header), (value)))
169#define debugp_verbose(header, value) (void) \
170 (compile_debug_print_indent(2) && \
171 ruby_debug_print_value(2, compile_debug, (header), (value)))
173#define debugp_verbose_node(header, value) (void) \
174 (compile_debug_print_indent(10) && \
175 ruby_debug_print_value(10, compile_debug, (header), (value)))
177#define debug_node_start(node) ((void) \
178 (compile_debug_print_indent(1) && \
179 (ruby_debug_print_node(1, CPDEBUG, "", (const NODE *)(node)), gl_node_level)), \
182#define debug_node_end() gl_node_level --
186#define debugi(header, id) ((void)0)
187#define debugp(header, value) ((void)0)
188#define debugp_verbose(header, value) ((void)0)
189#define debugp_verbose_node(header, value) ((void)0)
190#define debugp_param(header, value) ((void)0)
191#define debug_node_start(node) ((void)0)
192#define debug_node_end() ((void)0)
195#if CPDEBUG > 1 || CPDEBUG < 0
197#define printf ruby_debug_printf
198#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
199#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v))
201#define debugs if(0)printf
202#define debug_compile(msg, v) (v)
205#define LVAR_ERRINFO (1)
208#define NEW_LABEL(l) new_label_body(iseq, (l))
209#define LABEL_FORMAT "<L%03d>"
211#define NEW_ISEQ(node, name, type, line_no) \
212 new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no))
214#define NEW_CHILD_ISEQ(node, name, type, line_no) \
215 new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no))
218#define ADD_SEQ(seq1, seq2) \
219 APPEND_LIST((seq1), (seq2))
222#define ADD_INSN(seq, line_node, insn) \
223 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
226#define INSERT_BEFORE_INSN(next, line_node, insn) \
227 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
230#define INSERT_AFTER_INSN(prev, line_node, insn) \
231 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
234#define ADD_INSN1(seq, line_node, insn, op1) \
235 ADD_ELEM((seq), (LINK_ELEMENT *) \
236 new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
239#define INSERT_BEFORE_INSN1(next, line_node, insn, op1) \
240 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) \
241 new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
244#define INSERT_AFTER_INSN1(prev, line_node, insn, op1) \
245 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) \
246 new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
248#define LABEL_REF(label) ((label)->refcnt++)
251#define ADD_INSNL(seq, line_node, insn, label) (ADD_INSN1(seq, line_node, insn, label), LABEL_REF(label))
253#define ADD_INSN2(seq, line_node, insn, op1, op2) \
254 ADD_ELEM((seq), (LINK_ELEMENT *) \
255 new_insn_body(iseq, (line_node), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
257#define ADD_INSN3(seq, line_node, insn, op1, op2, op3) \
258 ADD_ELEM((seq), (LINK_ELEMENT *) \
259 new_insn_body(iseq, (line_node), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
262#define ADD_SEND(seq, line_node, id, argc) \
263 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL)
265#define ADD_SEND_WITH_FLAG(seq, line_node, id, argc, flag) \
266 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)(flag), NULL)
268#define ADD_SEND_WITH_BLOCK(seq, line_node, id, argc, block) \
269 ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(0), NULL)
271#define ADD_CALL_RECEIVER(seq, line_node) \
272 ADD_INSN((seq), (line_node), putself)
274#define ADD_CALL(seq, line_node, id, argc) \
275 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
277#define ADD_CALL_WITH_BLOCK(seq, line_node, id, argc, block) \
278 ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
280#define ADD_SEND_R(seq, line_node, id, argc, block, flag, keywords) \
281 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line_node), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
283#define ADD_TRACE(seq, event) \
284 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), 0))
285#define ADD_TRACE_WITH_DATA(seq, event, data) \
286 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), (data)))
288static void iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *
const seq,
const NODE *
const line_node,
int idx,
int level);
289static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *
const seq,
const NODE *
const line_node,
int idx,
int level);
291#define ADD_GETLOCAL(seq, line_node, idx, level) iseq_add_getlocal(iseq, (seq), (line_node), (idx), (level))
292#define ADD_SETLOCAL(seq, line_node, idx, level) iseq_add_setlocal(iseq, (seq), (line_node), (idx), (level))
295#define ADD_LABEL(seq, label) \
296 ADD_ELEM((seq), (LINK_ELEMENT *) (label))
298#define APPEND_LABEL(seq, before, label) \
299 APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label))
301#define ADD_ADJUST(seq, line_node, label) \
302 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), nd_line(line_node)))
304#define ADD_ADJUST_RESTORE(seq, label) \
305 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1))
307#define LABEL_UNREMOVABLE(label) \
308 ((label) ? (LABEL_REF(label), (label)->unremovable=1) : 0)
309#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \
310 VALUE _e = rb_ary_new3(5, (type), \
311 (VALUE)(ls) | 1, (VALUE)(le) | 1, \
312 (VALUE)(iseqv), (VALUE)(lc) | 1); \
313 LABEL_UNREMOVABLE(ls); \
316 if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) \
317 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, rb_ary_hidden_new(3)); \
318 rb_ary_push(ISEQ_COMPILE_DATA(iseq)->catch_table_ary, freeze_hide_obj(_e)); \
322#define COMPILE(anchor, desc, node) \
323 (debug_compile("== " desc "\n", \
324 iseq_compile_each(iseq, (anchor), (node), 0)))
327#define COMPILE_POPPED(anchor, desc, node) \
328 (debug_compile("== " desc "\n", \
329 iseq_compile_each(iseq, (anchor), (node), 1)))
332#define COMPILE_(anchor, desc, node, popped) \
333 (debug_compile("== " desc "\n", \
334 iseq_compile_each(iseq, (anchor), (node), (popped))))
336#define COMPILE_RECV(anchor, desc, node, recv) \
337 (private_recv_p(node) ? \
338 (ADD_INSN(anchor, node, putself), VM_CALL_FCALL) : \
339 COMPILE(anchor, desc, recv) ? 0 : -1)
341#define OPERAND_AT(insn, idx) \
342 (((INSN*)(insn))->operands[(idx)])
344#define INSN_OF(insn) \
345 (((INSN*)(insn))->insn_id)
347#define IS_INSN(link) ((link)->type == ISEQ_ELEMENT_INSN)
348#define IS_LABEL(link) ((link)->type == ISEQ_ELEMENT_LABEL)
349#define IS_ADJUST(link) ((link)->type == ISEQ_ELEMENT_ADJUST)
350#define IS_TRACE(link) ((link)->type == ISEQ_ELEMENT_TRACE)
351#define IS_INSN_ID(iobj, insn) (INSN_OF(iobj) == BIN(insn))
352#define IS_NEXT_INSN_ID(link, insn) \
353 ((link)->next && IS_INSN((link)->next) && IS_INSN_ID((link)->next, insn))
361append_compile_error(const rb_iseq_t *iseq,
int line, const
char *fmt, ...)
363 VALUE err_info = ISEQ_COMPILE_DATA(iseq)->err_info;
364 VALUE file = rb_iseq_path(iseq);
369 err = rb_syntax_error_append(err, file, line, -1, NULL, fmt, args);
371 if (
NIL_P(err_info)) {
372 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err);
375 else if (!err_info) {
386compile_bug(rb_iseq_t *iseq,
int line,
const char *fmt, ...)
390 rb_report_bug_valist(rb_iseq_path(iseq), line, fmt, args);
396#define COMPILE_ERROR append_compile_error
398#define ERROR_ARGS_AT(n) iseq, nd_line(n),
399#define ERROR_ARGS ERROR_ARGS_AT(node)
401#define EXPECT_NODE(prefix, node, ndtype, errval) \
403 const NODE *error_node = (node); \
404 enum node_type error_type = nd_type(error_node); \
405 if (error_type != (ndtype)) { \
406 COMPILE_ERROR(ERROR_ARGS_AT(error_node) \
407 prefix ": " #ndtype " is expected, but %s", \
408 ruby_node_name(error_type)); \
413#define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval) \
415 COMPILE_ERROR(ERROR_ARGS_AT(parent) \
416 prefix ": must be " #ndtype ", but 0"); \
420#define UNKNOWN_NODE(prefix, node, errval) \
422 const NODE *error_node = (node); \
423 COMPILE_ERROR(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \
424 ruby_node_name(nd_type(error_node))); \
431#define CHECK(sub) if (!(sub)) {BEFORE_RETURN;return COMPILE_NG;}
432#define NO_CHECK(sub) (void)(sub)
437#define DECL_ANCHOR(name) \
438 LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},}}
439#define INIT_ANCHOR(name) \
440 (name->last = &name->anchor)
443freeze_hide_obj(
VALUE obj)
446 RBASIC_CLEAR_CLASS(obj);
450#include "optinsn.inc"
451#if OPT_INSTRUCTIONS_UNIFICATION
452#include "optunifs.inc"
457#define ISEQ_ARG iseq,
458#define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
461#define ISEQ_ARG_DECLARE
465#define gl_node_level ISEQ_COMPILE_DATA(iseq)->node_level
468static void dump_disasm_list_with_cursor(
const LINK_ELEMENT *link,
const LINK_ELEMENT *curr,
const LABEL *dest);
469static void dump_disasm_list(
const LINK_ELEMENT *elem);
471static int insn_data_length(INSN *iobj);
472static int calc_sp_depth(
int depth, INSN *iobj);
474static INSN *new_insn_body(rb_iseq_t *iseq,
const NODE *
const line_node,
enum ruby_vminsn_type insn_id,
int argc, ...);
475static LABEL *new_label_body(rb_iseq_t *iseq,
long line);
476static ADJUST *new_adjust_body(rb_iseq_t *iseq, LABEL *label,
int line);
477static TRACE *new_trace_body(rb_iseq_t *iseq,
rb_event_flag_t event,
long data);
480static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
const NODE *n,
int);
481static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor);
482static int iseq_setup_insn(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor);
483static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor);
484static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor);
486static int iseq_set_local_table(rb_iseq_t *iseq,
const rb_ast_id_table_t *tbl);
487static int iseq_set_exception_local_table(rb_iseq_t *iseq);
488static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor,
const NODE *
const node);
490static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor);
491static int iseq_set_exception_table(rb_iseq_t *iseq);
492static int iseq_set_optargs_table(rb_iseq_t *iseq);
494static int compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
VALUE needstr);
495static int compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *node,
int method_call_keywords,
int popped);
502verify_list(ISEQ_ARG_DECLARE
const char *info, LINK_ANCHOR *
const anchor)
506 LINK_ELEMENT *list, *plist;
508 if (!compile_debug)
return;
510 list = anchor->anchor.next;
511 plist = &anchor->anchor;
513 if (plist != list->prev) {
520 if (anchor->last != plist && anchor->last != 0) {
525 rb_bug(
"list verify error: %08x (%s)", flag, info);
530#define verify_list(info, anchor) verify_list(iseq, (info), (anchor))
534verify_call_cache(rb_iseq_t *iseq)
537 VALUE *original = rb_iseq_original_iseq(iseq);
539 while (i < ISEQ_BODY(iseq)->iseq_size) {
540 VALUE insn = original[i];
541 const char *types = insn_op_types(insn);
543 for (
int j=0; types[j]; j++) {
544 if (types[j] == TS_CALLDATA) {
548 if (cc != vm_cc_empty()) {
550 rb_bug(
"call cache is not initialized by vm_cc_empty()");
557 for (
unsigned int i=0; i<ISEQ_BODY(iseq)->ci_size; i++) {
558 struct rb_call_data *cd = &ISEQ_BODY(iseq)->call_data[i];
561 if (cc != NULL && cc != vm_cc_empty()) {
563 rb_bug(
"call cache is not initialized by vm_cc_empty()");
573ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *
const anchor, LINK_ELEMENT *elem)
575 elem->prev = anchor->last;
576 anchor->last->next = elem;
578 verify_list(
"add", anchor);
585APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *
const anchor, LINK_ELEMENT *before, LINK_ELEMENT *elem)
588 elem->next = before->next;
589 elem->next->prev = elem;
591 if (before == anchor->last) anchor->last = elem;
592 verify_list(
"add", anchor);
595#define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem))
596#define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem))
600branch_coverage_valid_p(rb_iseq_t *iseq,
int first_line)
602 if (!ISEQ_COVERAGE(iseq))
return 0;
603 if (!ISEQ_BRANCH_COVERAGE(iseq))
return 0;
604 if (first_line <= 0)
return 0;
609decl_branch_base(rb_iseq_t *iseq,
const NODE *node,
const char *
type)
611 const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
612 const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
614 if (!branch_coverage_valid_p(iseq, first_lineno))
return Qundef;
626 VALUE branch_base = rb_hash_aref(structure, key);
629 if (
NIL_P(branch_base)) {
630 branch_base = rb_ary_hidden_new(6);
631 rb_hash_aset(structure, key, branch_base);
632 rb_ary_push(branch_base,
ID2SYM(rb_intern(
type)));
633 rb_ary_push(branch_base,
INT2FIX(first_lineno));
634 rb_ary_push(branch_base,
INT2FIX(first_column));
635 rb_ary_push(branch_base,
INT2FIX(last_lineno));
636 rb_ary_push(branch_base,
INT2FIX(last_column));
637 branches = rb_hash_new();
638 rb_obj_hide(branches);
639 rb_ary_push(branch_base, branches);
649generate_dummy_line_node(
int lineno,
int node_id)
652 nd_set_line(&dummy, lineno);
653 nd_set_node_id(&dummy, node_id);
658add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *
const seq,
const NODE *node,
int branch_id,
const char *
type,
VALUE branches)
660 const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
661 const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
663 if (!branch_coverage_valid_p(iseq, first_lineno))
return;
674 VALUE branch = rb_hash_aref(branches, key);
678 branch = rb_ary_hidden_new(6);
679 rb_hash_aset(branches, key, branch);
681 rb_ary_push(branch,
INT2FIX(first_lineno));
682 rb_ary_push(branch,
INT2FIX(first_column));
683 rb_ary_push(branch,
INT2FIX(last_lineno));
684 rb_ary_push(branch,
INT2FIX(last_column));
687 rb_ary_push(branch,
LONG2FIX(counter_idx));
688 rb_ary_push(counters,
INT2FIX(0));
694 ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx);
696 NODE dummy_line_node = generate_dummy_line_node(last_lineno, nd_node_id(node));
697 ADD_INSN(seq, &dummy_line_node, nop);
700#define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line)
703validate_label(st_data_t name, st_data_t label, st_data_t arg)
705 rb_iseq_t *iseq = (rb_iseq_t *)arg;
706 LABEL *lobj = (LABEL *)label;
707 if (!lobj->link.next) {
709 COMPILE_ERROR(iseq, lobj->position,
710 "%"PRIsVALUE
": undefined label",
718validate_labels(rb_iseq_t *iseq, st_table *labels_table)
720 st_foreach(labels_table, validate_label, (st_data_t)iseq);
721 st_free_table(labels_table);
725get_nd_recv(
const NODE *node)
727 switch (nd_type(node)) {
729 return RNODE_CALL(node)->nd_recv;
731 return RNODE_OPCALL(node)->nd_recv;
735 return RNODE_QCALL(node)->nd_recv;
739 return RNODE_ATTRASGN(node)->nd_recv;
741 return RNODE_OP_ASGN1(node)->nd_recv;
743 return RNODE_OP_ASGN2(node)->nd_recv;
745 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
750get_node_call_nd_mid(
const NODE *node)
752 switch (nd_type(node)) {
754 return RNODE_CALL(node)->nd_mid;
756 return RNODE_OPCALL(node)->nd_mid;
758 return RNODE_FCALL(node)->nd_mid;
760 return RNODE_QCALL(node)->nd_mid;
762 return RNODE_VCALL(node)->nd_mid;
764 return RNODE_ATTRASGN(node)->nd_mid;
766 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
771get_nd_args(
const NODE *node)
773 switch (nd_type(node)) {
775 return RNODE_CALL(node)->nd_args;
777 return RNODE_OPCALL(node)->nd_args;
779 return RNODE_FCALL(node)->nd_args;
781 return RNODE_QCALL(node)->nd_args;
785 return RNODE_ATTRASGN(node)->nd_args;
787 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
792get_node_colon_nd_mid(
const NODE *node)
794 switch (nd_type(node)) {
796 return RNODE_COLON2(node)->nd_mid;
798 return RNODE_COLON3(node)->nd_mid;
800 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
805get_nd_vid(
const NODE *node)
807 switch (nd_type(node)) {
809 return RNODE_LASGN(node)->nd_vid;
811 return RNODE_DASGN(node)->nd_vid;
813 return RNODE_IASGN(node)->nd_vid;
815 return RNODE_CVASGN(node)->nd_vid;
817 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
823get_nd_value(
const NODE *node)
825 switch (nd_type(node)) {
827 return RNODE_LASGN(node)->nd_value;
829 return RNODE_DASGN(node)->nd_value;
831 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
841 (*ifunc->func)(iseq, ret, ifunc->data);
843 NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1);
844 ADD_INSN(ret, &dummy_line_node, leave);
846 CHECK(iseq_setup_insn(iseq, ret));
847 return iseq_setup(iseq, ret);
851rb_iseq_compile_node(rb_iseq_t *iseq,
const NODE *node)
856 if (IMEMO_TYPE_P(node, imemo_ifunc)) {
857 rb_raise(rb_eArgError,
"unexpected imemo_ifunc");
861 NO_CHECK(COMPILE(ret,
"nil", node));
862 iseq_set_local_table(iseq, 0);
865 else if (nd_type_p(node, NODE_SCOPE)) {
867 iseq_set_local_table(iseq, RNODE_SCOPE(node)->nd_tbl);
868 iseq_set_arguments(iseq, ret, (NODE *)RNODE_SCOPE(node)->nd_args);
870 switch (ISEQ_BODY(iseq)->
type) {
871 case ISEQ_TYPE_BLOCK:
873 LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(0);
874 LABEL *end = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(0);
876 start->rescued = LABEL_RESCUE_BEG;
877 end->rescued = LABEL_RESCUE_END;
880 NODE dummy_line_node = generate_dummy_line_node(ISEQ_BODY(iseq)->location.first_lineno, -1);
881 ADD_INSN (ret, &dummy_line_node, nop);
882 ADD_LABEL(ret, start);
883 CHECK(COMPILE(ret,
"block body", RNODE_SCOPE(node)->nd_body));
886 ISEQ_COMPILE_DATA(iseq)->last_line = ISEQ_BODY(iseq)->location.code_location.end_pos.lineno;
889 ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
890 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
893 case ISEQ_TYPE_CLASS:
896 CHECK(COMPILE(ret,
"scoped node", RNODE_SCOPE(node)->nd_body));
898 ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
901 case ISEQ_TYPE_METHOD:
903 ISEQ_COMPILE_DATA(iseq)->root_node = RNODE_SCOPE(node)->nd_body;
905 CHECK(COMPILE(ret,
"scoped node", RNODE_SCOPE(node)->nd_body));
906 ISEQ_COMPILE_DATA(iseq)->root_node = RNODE_SCOPE(node)->nd_body;
908 ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
912 CHECK(COMPILE(ret,
"scoped node", RNODE_SCOPE(node)->nd_body));
919#define INVALID_ISEQ_TYPE(type) \
920 ISEQ_TYPE_##type: m = #type; goto invalid_iseq_type
921 switch (ISEQ_BODY(iseq)->
type) {
922 case INVALID_ISEQ_TYPE(
METHOD);
923 case INVALID_ISEQ_TYPE(CLASS);
924 case INVALID_ISEQ_TYPE(BLOCK);
925 case INVALID_ISEQ_TYPE(EVAL);
926 case INVALID_ISEQ_TYPE(MAIN);
927 case INVALID_ISEQ_TYPE(TOP);
928#undef INVALID_ISEQ_TYPE
929 case ISEQ_TYPE_RESCUE:
930 iseq_set_exception_local_table(iseq);
931 CHECK(COMPILE(ret,
"rescue", node));
933 case ISEQ_TYPE_ENSURE:
934 iseq_set_exception_local_table(iseq);
935 CHECK(COMPILE_POPPED(ret,
"ensure", node));
937 case ISEQ_TYPE_PLAIN:
938 CHECK(COMPILE(ret,
"ensure", node));
941 COMPILE_ERROR(ERROR_ARGS
"unknown scope: %d", ISEQ_BODY(iseq)->
type);
944 COMPILE_ERROR(ERROR_ARGS
"compile/ISEQ_TYPE_%s should not be reached", m);
949 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE || ISEQ_BODY(iseq)->
type == ISEQ_TYPE_ENSURE) {
950 NODE dummy_line_node = generate_dummy_line_node(0, -1);
951 ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
952 ADD_INSN1(ret, &dummy_line_node,
throw,
INT2FIX(0) );
955 NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1);
956 ADD_INSN(ret, &dummy_line_node, leave);
960 if (ISEQ_COMPILE_DATA(iseq)->labels_table) {
961 st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
962 ISEQ_COMPILE_DATA(iseq)->labels_table = 0;
963 validate_labels(iseq, labels_table);
966 CHECK(iseq_setup_insn(iseq, ret));
967 return iseq_setup(iseq, ret);
970static VALUE rb_translate_prism(
pm_parser_t *parser, rb_iseq_t *iseq, pm_scope_node_t *scope_node, LINK_ANCHOR *
const ret);
973rb_iseq_compile_prism_node(rb_iseq_t * iseq, pm_scope_node_t *scope_node,
pm_parser_t *parser)
978 CHECK(rb_translate_prism(parser, iseq, scope_node, ret));
980 CHECK(iseq_setup_insn(iseq, ret));
981 return iseq_setup(iseq, ret);
985rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
987#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
988 const void *
const *table = rb_vm_get_insns_address_table();
990 VALUE *encoded = (
VALUE *)ISEQ_BODY(iseq)->iseq_encoded;
992 for (i = 0; i < ISEQ_BODY(iseq)->iseq_size; ) {
993 int insn = (int)ISEQ_BODY(iseq)->iseq_encoded[i];
994 int len = insn_len(insn);
995 encoded[i] = (
VALUE)table[insn];
1002 rb_yjit_live_iseq_count++;
1009rb_iseq_original_iseq(
const rb_iseq_t *iseq)
1011 VALUE *original_code;
1013 if (ISEQ_ORIGINAL_ISEQ(iseq))
return ISEQ_ORIGINAL_ISEQ(iseq);
1014 original_code = ISEQ_ORIGINAL_ISEQ_ALLOC(iseq, ISEQ_BODY(iseq)->iseq_size);
1015 MEMCPY(original_code, ISEQ_BODY(iseq)->iseq_encoded,
VALUE, ISEQ_BODY(iseq)->iseq_size);
1017#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
1021 for (i = 0; i < ISEQ_BODY(iseq)->iseq_size; ) {
1022 const void *addr = (
const void *)original_code[i];
1023 const int insn = rb_vm_insn_addr2insn(addr);
1025 original_code[i] = insn;
1026 i += insn_len(insn);
1030 return original_code;
1043#if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__)
1044 #define STRICT_ALIGNMENT
1050#if defined(__OpenBSD__)
1051 #include <sys/endian.h>
1052 #ifdef __STRICT_ALIGNMENT
1053 #define STRICT_ALIGNMENT
1057#ifdef STRICT_ALIGNMENT
1058 #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE
1059 #define ALIGNMENT_SIZE SIZEOF_LONG_LONG
1061 #define ALIGNMENT_SIZE SIZEOF_VALUE
1063 #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1))
1064 #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX
1067 #define PADDING_SIZE_MAX 0
1070#ifdef STRICT_ALIGNMENT
1073calc_padding(
void *ptr,
size_t size)
1078 mis = (size_t)ptr & ALIGNMENT_SIZE_MASK;
1080 padding = ALIGNMENT_SIZE - mis;
1086#if ALIGNMENT_SIZE > SIZEOF_VALUE
1087 if (size ==
sizeof(
VALUE) && padding ==
sizeof(
VALUE)) {
1101#ifdef STRICT_ALIGNMENT
1102 size_t padding = calc_padding((
void *)&storage->buff[storage->pos], size);
1104 const size_t padding = 0;
1107 if (size >= INT_MAX - padding) rb_memerror();
1108 if (storage->pos + size + padding > storage->size) {
1109 unsigned int alloc_size = storage->size;
1111 while (alloc_size < size + PADDING_SIZE_MAX) {
1112 if (alloc_size >= INT_MAX / 2) rb_memerror();
1115 storage->next = (
void *)
ALLOC_N(
char, alloc_size +
1117 storage = *arena = storage->next;
1120 storage->size = alloc_size;
1121#ifdef STRICT_ALIGNMENT
1122 padding = calc_padding((
void *)&storage->buff[storage->pos], size);
1126#ifdef STRICT_ALIGNMENT
1127 storage->pos += (int)padding;
1130 ptr = (
void *)&storage->buff[storage->pos];
1131 storage->pos += (int)size;
1136compile_data_alloc(rb_iseq_t *iseq,
size_t size)
1139 return compile_data_alloc_with_arena(arena, size);
1143compile_data_alloc2(rb_iseq_t *iseq,
size_t x,
size_t y)
1146 return compile_data_alloc(iseq, size);
1150compile_data_calloc2(rb_iseq_t *iseq,
size_t x,
size_t y)
1153 void *p = compile_data_alloc(iseq, size);
1159compile_data_alloc_insn(rb_iseq_t *iseq)
1162 return (INSN *)compile_data_alloc_with_arena(arena,
sizeof(INSN));
1166compile_data_alloc_label(rb_iseq_t *iseq)
1168 return (LABEL *)compile_data_alloc(iseq,
sizeof(LABEL));
1172compile_data_alloc_adjust(rb_iseq_t *iseq)
1174 return (ADJUST *)compile_data_alloc(iseq,
sizeof(ADJUST));
1178compile_data_alloc_trace(rb_iseq_t *iseq)
1180 return (TRACE *)compile_data_alloc(iseq,
sizeof(TRACE));
1187ELEM_INSERT_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
1189 elem2->next = elem1->next;
1190 elem2->prev = elem1;
1191 elem1->next = elem2;
1193 elem2->next->prev = elem2;
1201ELEM_INSERT_PREV(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
1203 elem2->prev = elem1->prev;
1204 elem2->next = elem1;
1205 elem1->prev = elem2;
1207 elem2->prev->next = elem2;
1215ELEM_REPLACE(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
1217 elem2->prev = elem1->prev;
1218 elem2->next = elem1->next;
1220 elem1->prev->next = elem2;
1223 elem1->next->prev = elem2;
1228ELEM_REMOVE(LINK_ELEMENT *elem)
1230 elem->prev->next = elem->next;
1232 elem->next->prev = elem->prev;
1236static LINK_ELEMENT *
1237FIRST_ELEMENT(
const LINK_ANCHOR *
const anchor)
1239 return anchor->anchor.next;
1242static LINK_ELEMENT *
1243LAST_ELEMENT(LINK_ANCHOR *
const anchor)
1245 return anchor->last;
1248static LINK_ELEMENT *
1249ELEM_FIRST_INSN(LINK_ELEMENT *elem)
1252 switch (elem->type) {
1253 case ISEQ_ELEMENT_INSN:
1254 case ISEQ_ELEMENT_ADJUST:
1264LIST_INSN_SIZE_ONE(
const LINK_ANCHOR *
const anchor)
1266 LINK_ELEMENT *first_insn = ELEM_FIRST_INSN(FIRST_ELEMENT(anchor));
1267 if (first_insn != NULL &&
1268 ELEM_FIRST_INSN(first_insn->next) == NULL) {
1277LIST_INSN_SIZE_ZERO(
const LINK_ANCHOR *
const anchor)
1279 if (ELEM_FIRST_INSN(FIRST_ELEMENT(anchor)) == NULL) {
1295APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *
const anc1, LINK_ANCHOR *
const anc2)
1297 if (anc2->anchor.next) {
1298 anc1->last->next = anc2->anchor.next;
1299 anc2->anchor.next->prev = anc1->last;
1300 anc1->last = anc2->last;
1302 verify_list(
"append", anc1);
1305#define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
1310debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *
const anchor, LINK_ELEMENT *cur)
1312 LINK_ELEMENT *list = FIRST_ELEMENT(anchor);
1314 printf(
"anch: %p, frst: %p, last: %p\n", (
void *)&anchor->anchor,
1315 (
void *)anchor->anchor.next, (
void *)anchor->last);
1317 printf(
"curr: %p, next: %p, prev: %p, type: %d\n", (
void *)list, (
void *)list->next,
1318 (
void *)list->prev, (
int)list->type);
1323 dump_disasm_list_with_cursor(anchor->anchor.next, cur, 0);
1324 verify_list(
"debug list", anchor);
1327#define debug_list(anc, cur) debug_list(iseq, (anc), (cur))
1330#define debug_list(anc, cur) ((void)0)
1336 TRACE *trace = compile_data_alloc_trace(iseq);
1338 trace->link.type = ISEQ_ELEMENT_TRACE;
1339 trace->link.next = NULL;
1340 trace->event = event;
1347new_label_body(rb_iseq_t *iseq,
long line)
1349 LABEL *labelobj = compile_data_alloc_label(iseq);
1351 labelobj->link.type = ISEQ_ELEMENT_LABEL;
1352 labelobj->link.next = 0;
1354 labelobj->label_no = ISEQ_COMPILE_DATA(iseq)->label_no++;
1355 labelobj->sc_state = 0;
1357 labelobj->refcnt = 0;
1359 labelobj->rescued = LABEL_RESCUE_NONE;
1360 labelobj->unremovable = 0;
1365new_adjust_body(rb_iseq_t *iseq, LABEL *label,
int line)
1367 ADJUST *adjust = compile_data_alloc_adjust(iseq);
1368 adjust->link.type = ISEQ_ELEMENT_ADJUST;
1369 adjust->link.next = 0;
1370 adjust->label = label;
1371 adjust->line_no = line;
1372 LABEL_UNREMOVABLE(label);
1377iseq_insn_each_markable_object(INSN *insn,
void (*func)(
VALUE,
VALUE),
VALUE data)
1379 const char *types = insn_op_types(insn->insn_id);
1380 for (
int j = 0; types[j]; j++) {
1381 char type = types[j];
1388 func(OPERAND_AT(insn, j), data);
1397iseq_insn_each_object_write_barrier(
VALUE obj,
VALUE iseq)
1403new_insn_core(rb_iseq_t *iseq,
const NODE *line_node,
1404 int insn_id,
int argc,
VALUE *argv)
1406 INSN *iobj = compile_data_alloc_insn(iseq);
1410 iobj->link.type = ISEQ_ELEMENT_INSN;
1411 iobj->link.next = 0;
1412 iobj->insn_id = insn_id;
1413 iobj->insn_info.line_no = nd_line(line_node);
1414 iobj->insn_info.node_id = nd_node_id(line_node);
1415 iobj->insn_info.events = 0;
1416 iobj->operands = argv;
1417 iobj->operand_size = argc;
1420 iseq_insn_each_markable_object(iobj, iseq_insn_each_object_write_barrier, (
VALUE)iseq);
1426new_insn_body(rb_iseq_t *iseq,
const NODE *
const line_node,
enum ruby_vminsn_type insn_id,
int argc, ...)
1428 VALUE *operands = 0;
1432 va_start(argv, argc);
1433 operands = compile_data_alloc2(iseq,
sizeof(
VALUE), argc);
1434 for (i = 0; i < argc; i++) {
1440 return new_insn_core(iseq, line_node, insn_id, argc, operands);
1444new_callinfo(rb_iseq_t *iseq,
ID mid,
int argc,
unsigned int flag,
struct rb_callinfo_kwarg *kw_arg,
int has_blockiseq)
1446 VM_ASSERT(argc >= 0);
1448 if (!(flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) &&
1449 kw_arg == NULL && !has_blockiseq) {
1450 flag |= VM_CALL_ARGS_SIMPLE;
1454 flag |= VM_CALL_KWARG;
1455 argc += kw_arg->keyword_len;
1458 ISEQ_BODY(iseq)->ci_size++;
1459 const struct rb_callinfo *ci = vm_ci_new(mid, flag, argc, kw_arg);
1465new_insn_send(rb_iseq_t *iseq,
const NODE *
const line_node,
ID id,
VALUE argc,
const rb_iseq_t *blockiseq,
VALUE flag,
struct rb_callinfo_kwarg *keywords)
1467 VALUE *operands = compile_data_calloc2(iseq,
sizeof(
VALUE), 2);
1470 operands[1] = (
VALUE)blockiseq;
1474 INSN *insn = new_insn_core(iseq, line_node, BIN(send), 2, operands);
1481new_child_iseq(rb_iseq_t *iseq,
const NODE *
const node,
1482 VALUE name,
const rb_iseq_t *parent,
enum rb_iseq_type
type,
int line_no)
1484 rb_iseq_t *ret_iseq;
1488 ast.frozen_string_literal = -1;
1489 ast.coverage_enabled = -1;
1490 ast.script_lines = ISEQ_BODY(iseq)->variable.script_lines;
1492 debugs(
"[new_child_iseq]> ---------------------------------------\n");
1493 int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
1494 ret_iseq = rb_iseq_new_with_opt(&ast, name,
1495 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
1497 isolated_depth ? isolated_depth + 1 : 0,
1498 type, ISEQ_COMPILE_DATA(iseq)->option);
1499 debugs(
"[new_child_iseq]< ---------------------------------------\n");
1505 VALUE name,
const rb_iseq_t *parent,
enum rb_iseq_type
type,
int line_no)
1507 rb_iseq_t *ret_iseq;
1509 debugs(
"[new_child_iseq_with_callback]> ---------------------------------------\n");
1510 ret_iseq = rb_iseq_new_with_callback(ifunc, name,
1511 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
1512 line_no, parent,
type, ISEQ_COMPILE_DATA(iseq)->option);
1513 debugs(
"[new_child_iseq_with_callback]< ---------------------------------------\n");
1518set_catch_except_p(rb_iseq_t *iseq)
1521 ISEQ_COMPILE_DATA(iseq)->catch_except_p =
true;
1522 if (ISEQ_BODY(iseq)->parent_iseq != NULL) {
1523 if (ISEQ_COMPILE_DATA(ISEQ_BODY(iseq)->parent_iseq)) {
1524 set_catch_except_p((rb_iseq_t *) ISEQ_BODY(iseq)->parent_iseq);
1547 while (pos < body->iseq_size) {
1548 insn = rb_vm_insn_decode(body->iseq_encoded[pos]);
1549 if (insn == BIN(
throw)) {
1550 set_catch_except_p(iseq);
1553 pos += insn_len(insn);
1559 for (i = 0; i < ct->size; i++) {
1561 UNALIGNED_MEMBER_PTR(ct, entries[i]);
1562 if (entry->type != CATCH_TYPE_BREAK
1563 && entry->type != CATCH_TYPE_NEXT
1564 && entry->type != CATCH_TYPE_REDO) {
1566 ISEQ_COMPILE_DATA(iseq)->catch_except_p =
true;
1573iseq_insert_nop_between_end_and_cont(rb_iseq_t *iseq)
1575 VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
1576 if (
NIL_P(catch_table_ary))
return;
1577 unsigned int i, tlen = (
unsigned int)
RARRAY_LEN(catch_table_ary);
1579 for (i = 0; i < tlen; i++) {
1581 LINK_ELEMENT *end = (LINK_ELEMENT *)(ptr[2] & ~1);
1582 LINK_ELEMENT *cont = (LINK_ELEMENT *)(ptr[4] & ~1);
1585 enum rb_catch_type ct = (
enum rb_catch_type)(ptr[0] & 0xffff);
1587 if (ct != CATCH_TYPE_BREAK
1588 && ct != CATCH_TYPE_NEXT
1589 && ct != CATCH_TYPE_REDO) {
1591 for (e = end; e && (IS_LABEL(e) || IS_TRACE(e)); e = e->next) {
1593 NODE dummy_line_node = generate_dummy_line_node(0, -1);
1594 INSN *nop = new_insn_core(iseq, &dummy_line_node, BIN(nop), 0, 0);
1595 ELEM_INSERT_NEXT(end, &nop->link);
1604iseq_setup_insn(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor)
1606 if (
RTEST(ISEQ_COMPILE_DATA(iseq)->err_info))
1611 if (compile_debug > 5)
1612 dump_disasm_list(FIRST_ELEMENT(anchor));
1614 debugs(
"[compile step 3.1 (iseq_optimize)]\n");
1615 iseq_optimize(iseq, anchor);
1617 if (compile_debug > 5)
1618 dump_disasm_list(FIRST_ELEMENT(anchor));
1620 if (ISEQ_COMPILE_DATA(iseq)->option->instructions_unification) {
1621 debugs(
"[compile step 3.2 (iseq_insns_unification)]\n");
1622 iseq_insns_unification(iseq, anchor);
1623 if (compile_debug > 5)
1624 dump_disasm_list(FIRST_ELEMENT(anchor));
1627 debugs(
"[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n");
1628 iseq_insert_nop_between_end_and_cont(iseq);
1629 if (compile_debug > 5)
1630 dump_disasm_list(FIRST_ELEMENT(anchor));
1636iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor)
1638 if (
RTEST(ISEQ_COMPILE_DATA(iseq)->err_info))
1641 debugs(
"[compile step 4.1 (iseq_set_sequence)]\n");
1642 if (!iseq_set_sequence(iseq, anchor))
return COMPILE_NG;
1643 if (compile_debug > 5)
1644 dump_disasm_list(FIRST_ELEMENT(anchor));
1646 debugs(
"[compile step 4.2 (iseq_set_exception_table)]\n");
1647 if (!iseq_set_exception_table(iseq))
return COMPILE_NG;
1649 debugs(
"[compile step 4.3 (set_optargs_table)] \n");
1650 if (!iseq_set_optargs_table(iseq))
return COMPILE_NG;
1652 debugs(
"[compile step 5 (iseq_translate_threaded_code)] \n");
1653 if (!rb_iseq_translate_threaded_code(iseq))
return COMPILE_NG;
1655 debugs(
"[compile step 6 (update_catch_except_flags)] \n");
1657 update_catch_except_flags(iseq, ISEQ_BODY(iseq));
1659 debugs(
"[compile step 6.1 (remove unused catch tables)] \n");
1661 if (!ISEQ_COMPILE_DATA(iseq)->catch_except_p && ISEQ_BODY(iseq)->catch_table) {
1662 xfree(ISEQ_BODY(iseq)->catch_table);
1663 ISEQ_BODY(iseq)->catch_table = NULL;
1666#if VM_INSN_INFO_TABLE_IMPL == 2
1667 if (ISEQ_BODY(iseq)->insns_info.succ_index_table == NULL) {
1668 debugs(
"[compile step 7 (rb_iseq_insns_info_encode_positions)] \n");
1669 rb_iseq_insns_info_encode_positions(iseq);
1673 if (compile_debug > 1) {
1674 VALUE str = rb_iseq_disasm(iseq);
1677 verify_call_cache(iseq);
1678 debugs(
"[compile step: finish]\n");
1684iseq_set_exception_local_table(rb_iseq_t *iseq)
1686 ISEQ_BODY(iseq)->local_table_size = numberof(rb_iseq_shared_exc_local_tbl);
1687 ISEQ_BODY(iseq)->local_table = rb_iseq_shared_exc_local_tbl;
1692get_lvar_level(
const rb_iseq_t *iseq)
1695 while (iseq != ISEQ_BODY(iseq)->local_iseq) {
1697 iseq = ISEQ_BODY(iseq)->parent_iseq;
1703get_dyna_var_idx_at_raw(
const rb_iseq_t *iseq,
ID id)
1707 for (i = 0; i < ISEQ_BODY(iseq)->local_table_size; i++) {
1708 if (ISEQ_BODY(iseq)->local_table[i] ==
id) {
1716get_local_var_idx(
const rb_iseq_t *iseq,
ID id)
1718 int idx = get_dyna_var_idx_at_raw(ISEQ_BODY(iseq)->local_iseq,
id);
1721 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
1722 "get_local_var_idx: %d", idx);
1729get_dyna_var_idx(
const rb_iseq_t *iseq,
ID id,
int *level,
int *ls)
1731 int lv = 0, idx = -1;
1732 const rb_iseq_t *
const topmost_iseq = iseq;
1735 idx = get_dyna_var_idx_at_raw(iseq,
id);
1739 iseq = ISEQ_BODY(iseq)->parent_iseq;
1744 COMPILE_ERROR(topmost_iseq, ISEQ_LAST_LINE(topmost_iseq),
1745 "get_dyna_var_idx: -1");
1749 *ls = ISEQ_BODY(iseq)->local_table_size;
1754iseq_local_block_param_p(
const rb_iseq_t *iseq,
unsigned int idx,
unsigned int level)
1758 iseq = ISEQ_BODY(iseq)->parent_iseq;
1761 body = ISEQ_BODY(iseq);
1762 if (body->local_iseq == iseq &&
1763 body->
param.flags.has_block &&
1764 body->local_table_size - body->
param.block_start == idx) {
1773iseq_block_param_id_p(
const rb_iseq_t *iseq,
ID id,
int *pidx,
int *plevel)
1776 int idx = get_dyna_var_idx(iseq,
id, &level, &ls);
1777 if (iseq_local_block_param_p(iseq, ls - idx, level)) {
1788access_outer_variables(
const rb_iseq_t *iseq,
int level,
ID id,
bool write)
1790 int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
1792 if (isolated_depth && level >= isolated_depth) {
1793 if (
id == rb_intern(
"yield")) {
1794 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
"can not yield from isolated Proc");
1797 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
"can not access variable `%s' from isolated Proc", rb_id2name(
id));
1801 for (
int i=0; i<level; i++) {
1803 struct rb_id_table *ovs = ISEQ_BODY(iseq)->outer_variables;
1806 ovs = ISEQ_BODY(iseq)->outer_variables = rb_id_table_create(8);
1809 if (rb_id_table_lookup(ISEQ_BODY(iseq)->outer_variables,
id, &val)) {
1810 if (write && !val) {
1811 rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables,
id,
Qtrue);
1815 rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables,
id, RBOOL(write));
1818 iseq = ISEQ_BODY(iseq)->parent_iseq;
1823iseq_lvar_id(
const rb_iseq_t *iseq,
int idx,
int level)
1825 for (
int i=0; i<level; i++) {
1826 iseq = ISEQ_BODY(iseq)->parent_iseq;
1829 ID id = ISEQ_BODY(iseq)->local_table[ISEQ_BODY(iseq)->local_table_size - idx];
1835iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *
const seq,
const NODE *
const line_node,
int idx,
int level)
1837 if (iseq_local_block_param_p(iseq, idx, level)) {
1838 ADD_INSN2(seq, line_node, getblockparam,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1841 ADD_INSN2(seq, line_node, getlocal,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1843 if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level),
Qfalse);
1847iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *
const seq,
const NODE *
const line_node,
int idx,
int level)
1849 if (iseq_local_block_param_p(iseq, idx, level)) {
1850 ADD_INSN2(seq, line_node, setblockparam,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1853 ADD_INSN2(seq, line_node, setlocal,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1855 if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level),
Qtrue);
1861iseq_calc_param_size(rb_iseq_t *iseq)
1864 if (body->
param.flags.has_opt ||
1865 body->
param.flags.has_post ||
1866 body->
param.flags.has_rest ||
1867 body->
param.flags.has_block ||
1868 body->
param.flags.has_kw ||
1869 body->
param.flags.has_kwrest) {
1871 if (body->
param.flags.has_block) {
1872 body->
param.size = body->
param.block_start + 1;
1874 else if (body->
param.flags.has_kwrest) {
1875 body->
param.size = body->
param.keyword->rest_start + 1;
1877 else if (body->
param.flags.has_kw) {
1878 body->
param.size = body->
param.keyword->bits_start + 1;
1880 else if (body->
param.flags.has_post) {
1883 else if (body->
param.flags.has_rest) {
1884 body->
param.size = body->
param.rest_start + 1;
1886 else if (body->
param.flags.has_opt) {
1899iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *
const optargs,
1902 const rb_node_kw_arg_t *node = args->kw_args;
1904 struct rb_iseq_param_keyword *keyword;
1905 const VALUE default_values = rb_ary_hidden_new(1);
1907 int kw = 0, rkw = 0, di = 0, i;
1909 body->
param.flags.has_kw = TRUE;
1910 body->
param.keyword = keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
1914 node = node->nd_next;
1917 keyword->bits_start = arg_size++;
1919 node = args->kw_args;
1921 const NODE *val_node = get_nd_value(node->nd_body);
1924 if (val_node == NODE_SPECIAL_REQUIRED_KEYWORD) {
1928 switch (nd_type(val_node)) {
1930 dv = RNODE_LIT(val_node)->nd_lit;
1942 NO_CHECK(COMPILE_POPPED(optargs,
"kwarg", RNODE(node)));
1946 keyword->num = ++di;
1947 rb_ary_push(default_values, dv);
1950 node = node->nd_next;
1955 if (RNODE_DVAR(args->kw_rest_arg)->nd_vid != 0) {
1956 keyword->rest_start = arg_size++;
1957 body->
param.flags.has_kwrest = TRUE;
1959 keyword->required_num = rkw;
1960 keyword->table = &body->local_table[keyword->bits_start - keyword->num];
1965 for (i = 0; i <
RARRAY_LEN(default_values); i++) {
1967 if (dv == complex_mark) dv =
Qundef;
1974 keyword->default_values = dvs;
1980iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *
const optargs,
const NODE *
const node_args)
1982 debugs(
"iseq_set_arguments: %s\n", node_args ?
"" :
"0");
1986 struct rb_args_info *args = &RNODE_ARGS(node_args)->nd_ainfo;
1992 EXPECT_NODE(
"iseq_set_arguments", node_args, NODE_ARGS, COMPILE_NG);
1994 body->
param.flags.ruby2_keywords = args->ruby2_keywords;
1995 body->
param.lead_num = arg_size = (int)args->pre_args_num;
1996 if (body->
param.lead_num > 0) body->
param.flags.has_lead = TRUE;
1997 debugs(
" - argc: %d\n", body->
param.lead_num);
1999 rest_id = args->rest_arg;
2000 if (rest_id == NODE_SPECIAL_EXCESSIVE_COMMA) {
2004 block_id = args->block_arg;
2006 if (args->opt_args) {
2007 const rb_node_opt_arg_t *node = args->opt_args;
2009 VALUE labels = rb_ary_hidden_new(1);
2014 label = NEW_LABEL(nd_line(RNODE(node)));
2015 rb_ary_push(labels, (
VALUE)label | 1);
2016 ADD_LABEL(optargs, label);
2017 NO_CHECK(COMPILE_POPPED(optargs,
"optarg", node->nd_body));
2018 node = node->nd_next;
2023 label = NEW_LABEL(nd_line(node_args));
2024 rb_ary_push(labels, (
VALUE)label | 1);
2025 ADD_LABEL(optargs, label);
2030 for (j = 0; j < i+1; j++) {
2033 rb_ary_clear(labels);
2035 body->
param.flags.has_opt = TRUE;
2036 body->
param.opt_num = i;
2037 body->
param.opt_table = opt_table;
2042 body->
param.rest_start = arg_size++;
2043 body->
param.flags.has_rest = TRUE;
2044 assert(body->
param.rest_start != -1);
2047 if (args->first_post_arg) {
2048 body->
param.post_start = arg_size;
2049 body->
param.post_num = args->post_args_num;
2050 body->
param.flags.has_post = TRUE;
2051 arg_size += args->post_args_num;
2053 if (body->
param.flags.has_rest) {
2054 body->
param.post_start = body->
param.rest_start + 1;
2058 if (args->kw_args) {
2059 arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size);
2061 else if (args->kw_rest_arg) {
2062 struct rb_iseq_param_keyword *keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
2063 keyword->rest_start = arg_size++;
2064 body->
param.keyword = keyword;
2065 body->
param.flags.has_kwrest = TRUE;
2067 else if (args->no_kwarg) {
2068 body->
param.flags.accepts_no_kwarg = TRUE;
2072 body->
param.block_start = arg_size++;
2073 body->
param.flags.has_block = TRUE;
2076 iseq_calc_param_size(iseq);
2077 body->
param.size = arg_size;
2079 if (args->pre_init) {
2080 NO_CHECK(COMPILE_POPPED(optargs,
"init arguments (m)", args->pre_init));
2082 if (args->post_init) {
2083 NO_CHECK(COMPILE_POPPED(optargs,
"init arguments (p)", args->post_init));
2086 if (body->type == ISEQ_TYPE_BLOCK) {
2087 if (body->
param.flags.has_opt == FALSE &&
2088 body->
param.flags.has_post == FALSE &&
2089 body->
param.flags.has_rest == FALSE &&
2090 body->
param.flags.has_kw == FALSE &&
2091 body->
param.flags.has_kwrest == FALSE) {
2093 if (body->
param.lead_num == 1 && last_comma == 0) {
2095 body->
param.flags.ambiguous_param0 = TRUE;
2105iseq_set_local_table(rb_iseq_t *iseq,
const rb_ast_id_table_t *tbl)
2107 unsigned int size = tbl ? tbl->size : 0;
2112 ISEQ_BODY(iseq)->local_table = ids;
2114 ISEQ_BODY(iseq)->local_table_size = size;
2116 debugs(
"iseq_set_local_table: %u\n", ISEQ_BODY(iseq)->local_table_size);
2128 else if ((tlit = OBJ_BUILTIN_TYPE(lit)) == -1) {
2131 else if ((tval = OBJ_BUILTIN_TYPE(val)) == -1) {
2134 else if (tlit != tval) {
2144 long x =
FIX2LONG(rb_big_cmp(lit, val));
2152 return rb_float_cmp(lit, val);
2155 const struct RRational *rat1 = RRATIONAL(val);
2156 const struct RRational *rat2 = RRATIONAL(lit);
2157 return rb_iseq_cdhash_cmp(rat1->num, rat2->num) || rb_iseq_cdhash_cmp(rat1->den, rat2->den);
2160 const struct RComplex *comp1 = RCOMPLEX(val);
2161 const struct RComplex *comp2 = RCOMPLEX(lit);
2162 return rb_iseq_cdhash_cmp(comp1->real, comp2->real) || rb_iseq_cdhash_cmp(comp1->imag, comp2->imag);
2165 return rb_reg_equal(val, lit) ? 0 : -1;
2173rb_iseq_cdhash_hash(
VALUE a)
2175 switch (OBJ_BUILTIN_TYPE(a)) {
2178 return (st_index_t)a;
2186 return rb_rational_hash(a);
2188 return rb_complex_hash(a);
2196static const struct st_hash_type cdhash_type = {
2198 rb_iseq_cdhash_hash,
2211 LABEL *lobj = (LABEL *)(val & ~1);
2212 rb_hash_aset(data->hash, key,
INT2FIX(lobj->position - (data->pos+data->len)));
2218get_ivar_ic_value(rb_iseq_t *iseq,
ID id)
2220 return INT2FIX(ISEQ_BODY(iseq)->ivc_size++);
2224get_cvar_ic_value(rb_iseq_t *iseq,
ID id)
2227 struct rb_id_table *tbl = ISEQ_COMPILE_DATA(iseq)->ivar_cache_table;
2229 if (rb_id_table_lookup(tbl,
id,&val)) {
2234 tbl = rb_id_table_create(1);
2235 ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
2237 val =
INT2FIX(ISEQ_BODY(iseq)->icvarc_size++);
2238 rb_id_table_insert(tbl,
id,val);
2242#define BADINSN_DUMP(anchor, list, dest) \
2243 dump_disasm_list_with_cursor(FIRST_ELEMENT(anchor), list, dest)
2245#define BADINSN_ERROR \
2246 (xfree(generated_iseq), \
2247 xfree(insns_info), \
2248 BADINSN_DUMP(anchor, list, NULL), \
2252fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor)
2254 int stack_max = 0, sp = 0, line = 0;
2257 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2258 if (IS_LABEL(list)) {
2259 LABEL *lobj = (LABEL *)list;
2264 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2265 switch (list->type) {
2266 case ISEQ_ELEMENT_INSN:
2271 INSN *iobj = (INSN *)list;
2274 sp = calc_sp_depth(sp, iobj);
2276 BADINSN_DUMP(anchor, list, NULL);
2277 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2278 "argument stack underflow (%d)", sp);
2281 if (sp > stack_max) {
2285 line = iobj->insn_info.line_no;
2287 operands = iobj->operands;
2288 insn = iobj->insn_id;
2289 types = insn_op_types(insn);
2290 len = insn_len(insn);
2293 if (iobj->operand_size !=
len - 1) {
2295 BADINSN_DUMP(anchor, list, NULL);
2296 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2297 "operand size miss! (%d for %d)",
2298 iobj->operand_size,
len - 1);
2302 for (j = 0; types[j]; j++) {
2303 if (types[j] == TS_OFFSET) {
2305 LABEL *lobj = (LABEL *)operands[j];
2307 BADINSN_DUMP(anchor, list, NULL);
2308 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2309 "unknown label: "LABEL_FORMAT, lobj->label_no);
2312 if (lobj->sp == -1) {
2315 else if (lobj->sp != sp) {
2316 debugs(
"%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2317 RSTRING_PTR(rb_iseq_path(iseq)), line,
2318 lobj->label_no, lobj->sp, sp);
2324 case ISEQ_ELEMENT_LABEL:
2326 LABEL *lobj = (LABEL *)list;
2327 if (lobj->sp == -1) {
2331 if (lobj->sp != sp) {
2332 debugs(
"%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2333 RSTRING_PTR(rb_iseq_path(iseq)), line,
2334 lobj->label_no, lobj->sp, sp);
2340 case ISEQ_ELEMENT_TRACE:
2345 case ISEQ_ELEMENT_ADJUST:
2347 ADJUST *adjust = (ADJUST *)list;
2350 sp = adjust->label ? adjust->label->sp : 0;
2351 if (adjust->line_no != -1 && orig_sp - sp < 0) {
2352 BADINSN_DUMP(anchor, list, NULL);
2353 COMPILE_ERROR(iseq, adjust->line_no,
2354 "iseq_set_sequence: adjust bug %d < %d",
2361 BADINSN_DUMP(anchor, list, NULL);
2362 COMPILE_ERROR(iseq, line,
"unknown list type: %d", list->type);
2371 int insns_info_index,
int code_index,
const INSN *iobj)
2373 if (insns_info_index == 0 ||
2374 insns_info[insns_info_index-1].line_no != iobj->insn_info.line_no ||
2375#ifdef USE_ISEQ_NODE_ID
2376 insns_info[insns_info_index-1].node_id != iobj->insn_info.node_id ||
2378 insns_info[insns_info_index-1].events != iobj->insn_info.events) {
2379 insns_info[insns_info_index].line_no = iobj->insn_info.line_no;
2380#ifdef USE_ISEQ_NODE_ID
2381 insns_info[insns_info_index].node_id = iobj->insn_info.node_id;
2383 insns_info[insns_info_index].events = iobj->insn_info.events;
2384 positions[insns_info_index] = code_index;
2392 int insns_info_index,
int code_index,
const ADJUST *adjust)
2394 insns_info[insns_info_index].line_no = adjust->line_no;
2395 insns_info[insns_info_index].events = 0;
2396 positions[insns_info_index] = code_index;
2401array_to_idlist(
VALUE arr)
2406 for (
int i = 0; i < size; i++) {
2415idlist_to_array(
const ID *ids)
2417 VALUE arr = rb_ary_new();
2419 rb_ary_push(arr,
ID2SYM(*ids++));
2428iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor)
2432 unsigned int *positions;
2434 VALUE *generated_iseq;
2438 int insn_num, code_index, insns_info_index, sp = 0;
2439 int stack_max = fix_sp_depth(iseq, anchor);
2441 if (stack_max < 0)
return COMPILE_NG;
2444 insn_num = code_index = 0;
2445 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2446 switch (list->type) {
2447 case ISEQ_ELEMENT_INSN:
2449 INSN *iobj = (INSN *)list;
2451 sp = calc_sp_depth(sp, iobj);
2453 events = iobj->insn_info.events |= events;
2454 if (ISEQ_COVERAGE(iseq)) {
2455 if (ISEQ_LINE_COVERAGE(iseq) && (events & RUBY_EVENT_COVERAGE_LINE) &&
2456 !(rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES)) {
2457 int line = iobj->insn_info.line_no - 1;
2458 if (line >= 0 && line <
RARRAY_LEN(ISEQ_LINE_COVERAGE(iseq))) {
2462 if (ISEQ_BRANCH_COVERAGE(iseq) && (events & RUBY_EVENT_COVERAGE_BRANCH)) {
2463 while (
RARRAY_LEN(ISEQ_PC2BRANCHINDEX(iseq)) <= code_index) {
2464 rb_ary_push(ISEQ_PC2BRANCHINDEX(iseq),
Qnil);
2469 code_index += insn_data_length(iobj);
2474 case ISEQ_ELEMENT_LABEL:
2476 LABEL *lobj = (LABEL *)list;
2477 lobj->position = code_index;
2478 if (lobj->sp != sp) {
2479 debugs(
"%s: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2480 RSTRING_PTR(rb_iseq_path(iseq)),
2481 lobj->label_no, lobj->sp, sp);
2486 case ISEQ_ELEMENT_TRACE:
2488 TRACE *trace = (TRACE *)list;
2489 events |= trace->event;
2490 if (trace->event & RUBY_EVENT_COVERAGE_BRANCH) data = trace->data;
2493 case ISEQ_ELEMENT_ADJUST:
2495 ADJUST *adjust = (ADJUST *)list;
2496 if (adjust->line_no != -1) {
2498 sp = adjust->label ? adjust->label->sp : 0;
2499 if (orig_sp - sp > 0) {
2500 if (orig_sp - sp > 1) code_index++;
2514 positions =
ALLOC_N(
unsigned int, insn_num);
2515 if (ISEQ_IS_SIZE(body)) {
2519 body->is_entries = NULL;
2522 ISEQ_COMPILE_DATA(iseq)->ci_index = 0;
2529 iseq_bits_t * mark_offset_bits;
2530 int code_size = code_index;
2532 iseq_bits_t tmp[1] = {0};
2533 bool needs_bitmap =
false;
2535 if (ISEQ_MBITS_BUFLEN(code_index) == 1) {
2536 mark_offset_bits = tmp;
2539 mark_offset_bits =
ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(code_index));
2542 list = FIRST_ELEMENT(anchor);
2543 insns_info_index = code_index = sp = 0;
2546 switch (list->type) {
2547 case ISEQ_ELEMENT_INSN:
2552 INSN *iobj = (INSN *)list;
2555 sp = calc_sp_depth(sp, iobj);
2557 operands = iobj->operands;
2558 insn = iobj->insn_id;
2559 generated_iseq[code_index] = insn;
2560 types = insn_op_types(insn);
2561 len = insn_len(insn);
2563 for (j = 0; types[j]; j++) {
2564 char type = types[j];
2571 LABEL *lobj = (LABEL *)operands[j];
2572 generated_iseq[code_index + 1 + j] = lobj->position - (code_index +
len);
2577 VALUE map = operands[j];
2580 data.pos = code_index;
2584 rb_hash_rehash(map);
2585 freeze_hide_obj(map);
2586 generated_iseq[code_index + 1 + j] = map;
2587 ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
2589 needs_bitmap =
true;
2594 generated_iseq[code_index + 1 + j] =
FIX2INT(operands[j]);
2599 VALUE v = operands[j];
2600 generated_iseq[code_index + 1 + j] = v;
2604 ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
2605 needs_bitmap =
true;
2612 unsigned int ic_index = ISEQ_COMPILE_DATA(iseq)->ic_index++;
2613 IC ic = &ISEQ_IS_ENTRY_START(body,
type)[ic_index].ic_cache;
2614 if (UNLIKELY(ic_index >= body->ic_size)) {
2615 BADINSN_DUMP(anchor, &iobj->link, 0);
2616 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2617 "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
2618 ic_index, ISEQ_IS_SIZE(body));
2621 ic->
segments = array_to_idlist(operands[j]);
2623 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
2628 unsigned int ic_index =
FIX2UINT(operands[j]);
2630 IVC cache = ((IVC)&body->is_entries[ic_index]);
2632 if (insn == BIN(setinstancevariable)) {
2633 cache->iv_set_name =
SYM2ID(operands[j - 1]);
2636 cache->iv_set_name = 0;
2639 vm_ic_attr_index_initialize(cache, INVALID_SHAPE_ID);
2644 unsigned int ic_index =
FIX2UINT(operands[j]);
2645 IC ic = &ISEQ_IS_ENTRY_START(body,
type)[ic_index].ic_cache;
2646 if (UNLIKELY(ic_index >= ISEQ_IS_SIZE(body))) {
2647 BADINSN_DUMP(anchor, &iobj->link, 0);
2648 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2649 "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
2650 ic_index, ISEQ_IS_SIZE(body));
2652 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
2659 assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size);
2660 struct rb_call_data *cd = &body->call_data[ISEQ_COMPILE_DATA(iseq)->ci_index++];
2662 cd->cc = vm_cc_empty();
2663 generated_iseq[code_index + 1 + j] = (
VALUE)cd;
2667 generated_iseq[code_index + 1 + j] =
SYM2ID(operands[j]);
2670 generated_iseq[code_index + 1 + j] = operands[j];
2673 generated_iseq[code_index + 1 + j] = operands[j];
2676 BADINSN_ERROR(iseq, iobj->insn_info.line_no,
2677 "unknown operand type: %c",
type);
2681 if (add_insn_info(insns_info, positions, insns_info_index, code_index, iobj)) insns_info_index++;
2685 case ISEQ_ELEMENT_LABEL:
2687 LABEL *lobj = (LABEL *)list;
2688 if (lobj->sp != sp) {
2689 debugs(
"%s: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2690 RSTRING_PTR(rb_iseq_path(iseq)),
2691 lobj->label_no, lobj->sp, sp);
2696 case ISEQ_ELEMENT_ADJUST:
2698 ADJUST *adjust = (ADJUST *)list;
2701 if (adjust->label) {
2702 sp = adjust->label->sp;
2708 if (adjust->line_no != -1) {
2709 const int diff = orig_sp - sp;
2711 if (insns_info_index == 0) {
2712 COMPILE_ERROR(iseq, adjust->line_no,
2713 "iseq_set_sequence: adjust bug (ISEQ_ELEMENT_ADJUST must not be the first in iseq)");
2715 if (add_adjust_info(insns_info, positions, insns_info_index, code_index, adjust)) insns_info_index++;
2718 generated_iseq[code_index++] = BIN(adjuststack);
2719 generated_iseq[code_index++] = orig_sp - sp;
2721 else if (diff == 1) {
2722 generated_iseq[code_index++] = BIN(pop);
2724 else if (diff < 0) {
2725 int label_no = adjust->label ? adjust->label->label_no : -1;
2726 xfree(generated_iseq);
2729 if (ISEQ_MBITS_BUFLEN(code_size) > 1) {
2730 xfree(mark_offset_bits);
2732 debug_list(anchor, list);
2733 COMPILE_ERROR(iseq, adjust->line_no,
2734 "iseq_set_sequence: adjust bug to %d %d < %d",
2735 label_no, orig_sp, sp);
2748 body->iseq_encoded = (
void *)generated_iseq;
2749 body->iseq_size = code_index;
2750 body->stack_max = stack_max;
2752 if (ISEQ_MBITS_BUFLEN(body->iseq_size) == 1) {
2753 body->mark_bits.single = mark_offset_bits[0];
2757 body->mark_bits.list = mark_offset_bits;
2760 body->mark_bits.list = 0;
2761 ruby_xfree(mark_offset_bits);
2766 body->insns_info.body = insns_info;
2767 body->insns_info.positions = positions;
2770 body->insns_info.body = insns_info;
2771 REALLOC_N(positions,
unsigned int, insns_info_index);
2772 body->insns_info.positions = positions;
2773 body->insns_info.size = insns_info_index;
2779label_get_position(LABEL *lobj)
2781 return lobj->position;
2785label_get_sp(LABEL *lobj)
2791iseq_set_exception_table(rb_iseq_t *iseq)
2793 const VALUE *tptr, *ptr;
2794 unsigned int tlen, i;
2797 ISEQ_BODY(iseq)->catch_table = NULL;
2799 VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
2800 if (
NIL_P(catch_table_ary))
return COMPILE_OK;
2808 for (i = 0; i < table->size; i++) {
2810 entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
2811 entry->type = (
enum rb_catch_type)(ptr[0] & 0xffff);
2812 entry->start = label_get_position((LABEL *)(ptr[1] & ~1));
2813 entry->end = label_get_position((LABEL *)(ptr[2] & ~1));
2814 entry->iseq = (rb_iseq_t *)ptr[3];
2819 LABEL *lobj = (LABEL *)(ptr[4] & ~1);
2820 entry->cont = label_get_position(lobj);
2821 entry->sp = label_get_sp(lobj);
2824 if (entry->type == CATCH_TYPE_RESCUE ||
2825 entry->type == CATCH_TYPE_BREAK ||
2826 entry->type == CATCH_TYPE_NEXT) {
2834 ISEQ_BODY(iseq)->catch_table = table;
2835 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0);
2853iseq_set_optargs_table(rb_iseq_t *iseq)
2856 VALUE *opt_table = (
VALUE *)ISEQ_BODY(iseq)->param.opt_table;
2858 if (ISEQ_BODY(iseq)->param.flags.has_opt) {
2859 for (i = 0; i < ISEQ_BODY(iseq)->param.opt_num + 1; i++) {
2860 opt_table[i] = label_get_position((LABEL *)opt_table[i]);
2866static LINK_ELEMENT *
2867get_destination_insn(INSN *iobj)
2869 LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0);
2873 list = lobj->link.next;
2875 switch (list->type) {
2876 case ISEQ_ELEMENT_INSN:
2877 case ISEQ_ELEMENT_ADJUST:
2879 case ISEQ_ELEMENT_LABEL:
2882 case ISEQ_ELEMENT_TRACE:
2884 TRACE *trace = (TRACE *)list;
2885 events |= trace->event;
2893 if (list && IS_INSN(list)) {
2894 INSN *iobj = (INSN *)list;
2895 iobj->insn_info.events |= events;
2900static LINK_ELEMENT *
2901get_next_insn(INSN *iobj)
2903 LINK_ELEMENT *list = iobj->link.next;
2906 if (IS_INSN(list) || IS_ADJUST(list)) {
2914static LINK_ELEMENT *
2915get_prev_insn(INSN *iobj)
2917 LINK_ELEMENT *list = iobj->link.prev;
2920 if (IS_INSN(list) || IS_ADJUST(list)) {
2929unref_destination(INSN *iobj,
int pos)
2931 LABEL *lobj = (LABEL *)OPERAND_AT(iobj, pos);
2933 if (!lobj->refcnt) ELEM_REMOVE(&lobj->link);
2937replace_destination(INSN *dobj, INSN *nobj)
2939 VALUE n = OPERAND_AT(nobj, 0);
2940 LABEL *dl = (LABEL *)OPERAND_AT(dobj, 0);
2941 LABEL *nl = (LABEL *)n;
2944 OPERAND_AT(dobj, 0) = n;
2945 if (!dl->refcnt) ELEM_REMOVE(&dl->link);
2949find_destination(INSN *i)
2951 int pos,
len = insn_len(i->insn_id);
2952 for (pos = 0; pos <
len; ++pos) {
2953 if (insn_op_types(i->insn_id)[pos] == TS_OFFSET) {
2954 return (LABEL *)OPERAND_AT(i, pos);
2961remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i)
2963 LINK_ELEMENT *first = i, *end;
2964 int *unref_counts = 0, nlabels = ISEQ_COMPILE_DATA(iseq)->label_no;
2967 unref_counts =
ALLOCA_N(
int, nlabels);
2968 MEMZERO(unref_counts,
int, nlabels);
2973 if (IS_INSN_ID(i, leave)) {
2977 else if ((lab = find_destination((INSN *)i)) != 0) {
2978 unref_counts[lab->label_no]++;
2981 else if (IS_LABEL(i)) {
2983 if (lab->unremovable)
return 0;
2984 if (lab->refcnt > unref_counts[lab->label_no]) {
2985 if (i == first)
return 0;
2990 else if (IS_TRACE(i)) {
2993 else if (IS_ADJUST(i)) {
2997 }
while ((i = i->next) != 0);
3002 VALUE insn = INSN_OF(i);
3003 int pos,
len = insn_len(insn);
3004 for (pos = 0; pos <
len; ++pos) {
3005 switch (insn_op_types(insn)[pos]) {
3007 unref_destination((INSN *)i, pos);
3016 }
while ((i != end) && (i = i->next) != 0);
3021iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj)
3023 switch (OPERAND_AT(iobj, 0)) {
3025 ELEM_REMOVE(&iobj->link);
3028 ELEM_REMOVE(&iobj->link);
3031 iobj->insn_id = BIN(adjuststack);
3037is_frozen_putstring(INSN *insn,
VALUE *op)
3039 if (IS_INSN_ID(insn, putstring)) {
3040 *op = OPERAND_AT(insn, 0);
3043 else if (IS_INSN_ID(insn, putobject)) {
3044 *op = OPERAND_AT(insn, 0);
3051optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
3075 INSN *niobj, *ciobj, *dup = 0;
3079 switch (INSN_OF(iobj)) {
3080 case BIN(putstring):
3086 case BIN(putobject):
3089 default:
return FALSE;
3092 ciobj = (INSN *)get_next_insn(iobj);
3093 if (IS_INSN_ID(ciobj, jump)) {
3094 ciobj = (INSN *)get_next_insn((INSN*)OPERAND_AT(ciobj, 0));
3096 if (IS_INSN_ID(ciobj, dup)) {
3097 ciobj = (INSN *)get_next_insn(dup = ciobj);
3099 if (!ciobj || !IS_INSN_ID(ciobj, checktype))
return FALSE;
3100 niobj = (INSN *)get_next_insn(ciobj);
3105 switch (INSN_OF(niobj)) {
3107 if (OPERAND_AT(ciobj, 0) ==
type) {
3108 dest = (LABEL *)OPERAND_AT(niobj, 0);
3111 case BIN(branchunless):
3112 if (OPERAND_AT(ciobj, 0) !=
type) {
3113 dest = (LABEL *)OPERAND_AT(niobj, 0);
3119 line = ciobj->insn_info.line_no;
3120 node_id = ciobj->insn_info.node_id;
3121 NODE dummy_line_node = generate_dummy_line_node(line, node_id);
3123 if (niobj->link.next && IS_LABEL(niobj->link.next)) {
3124 dest = (LABEL *)niobj->link.next;
3127 dest = NEW_LABEL(line);
3128 ELEM_INSERT_NEXT(&niobj->link, &dest->link);
3131 INSERT_AFTER_INSN1(iobj, &dummy_line_node, jump, dest);
3133 if (!dup) INSERT_AFTER_INSN(iobj, &dummy_line_node, pop);
3138ci_flag_set(
const rb_iseq_t *iseq,
const struct rb_callinfo *ci,
unsigned int add)
3140 const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
3141 vm_ci_flag(ci) | add,
3149ci_argc_set(
const rb_iseq_t *iseq,
const struct rb_callinfo *ci,
int argc)
3151 const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
3160iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list,
const int do_tailcallopt)
3162 INSN *
const iobj = (INSN *)list;
3165 optimize_checktype(iseq, iobj);
3167 if (IS_INSN_ID(iobj, jump)) {
3168 INSN *niobj, *diobj, *piobj;
3169 diobj = (INSN *)get_destination_insn(iobj);
3170 niobj = (INSN *)get_next_insn(iobj);
3172 if (diobj == niobj) {
3179 unref_destination(iobj, 0);
3180 ELEM_REMOVE(&iobj->link);
3183 else if (iobj != diobj && IS_INSN(&diobj->link) &&
3184 IS_INSN_ID(diobj, jump) &&
3185 OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0) &&
3186 diobj->insn_info.events == 0) {
3197 replace_destination(iobj, diobj);
3198 remove_unreachable_chunk(iseq, iobj->link.next);
3201 else if (IS_INSN_ID(diobj, leave)) {
3214 unref_destination(iobj, 0);
3215 iobj->insn_id = BIN(leave);
3216 iobj->operand_size = 0;
3217 iobj->insn_info = diobj->insn_info;
3220 else if (IS_INSN(iobj->link.prev) &&
3221 (piobj = (INSN *)iobj->link.prev) &&
3222 (IS_INSN_ID(piobj, branchif) ||
3223 IS_INSN_ID(piobj, branchunless))) {
3224 INSN *pdiobj = (INSN *)get_destination_insn(piobj);
3225 if (niobj == pdiobj) {
3226 int refcnt = IS_LABEL(piobj->link.next) ?
3227 ((LABEL *)piobj->link.next)->refcnt : 0;
3242 piobj->insn_id = (IS_INSN_ID(piobj, branchif))
3243 ? BIN(branchunless) : BIN(branchif);
3244 replace_destination(piobj, iobj);
3246 ELEM_REMOVE(&iobj->link);
3253 else if (diobj == pdiobj) {
3267 NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
3268 INSN *popiobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, 0);
3269 ELEM_REPLACE(&piobj->link, &popiobj->link);
3272 if (remove_unreachable_chunk(iseq, iobj->link.next)) {
3286 if (IS_INSN_ID(iobj, newrange)) {
3287 INSN *
const range = iobj;
3289 VALUE str_beg, str_end;
3291 if ((end = (INSN *)get_prev_insn(range)) != 0 &&
3292 is_frozen_putstring(end, &str_end) &&
3293 (beg = (INSN *)get_prev_insn(end)) != 0 &&
3294 is_frozen_putstring(beg, &str_beg)) {
3295 int excl =
FIX2INT(OPERAND_AT(range, 0));
3298 ELEM_REMOVE(&beg->link);
3299 ELEM_REMOVE(&end->link);
3300 range->insn_id = BIN(putobject);
3301 OPERAND_AT(range, 0) = lit_range;
3306 if (IS_INSN_ID(iobj, leave)) {
3307 remove_unreachable_chunk(iseq, iobj->link.next);
3319 if (IS_INSN_ID(iobj, duparray)) {
3320 LINK_ELEMENT *next = iobj->link.next;
3321 if (IS_INSN(next) && IS_INSN_ID(next, concatarray)) {
3322 iobj->insn_id = BIN(putobject);
3326 if (IS_INSN_ID(iobj, branchif) ||
3327 IS_INSN_ID(iobj, branchnil) ||
3328 IS_INSN_ID(iobj, branchunless)) {
3337 INSN *nobj = (INSN *)get_destination_insn(iobj);
3359 int stop_optimization =
3360 ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq) &&
3361 nobj->link.type == ISEQ_ELEMENT_INSN &&
3362 nobj->insn_info.events;
3363 if (!stop_optimization) {
3364 INSN *pobj = (INSN *)iobj->link.prev;
3367 if (!IS_INSN(&pobj->link))
3369 else if (IS_INSN_ID(pobj, dup))
3374 if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) {
3375 replace_destination(iobj, nobj);
3377 else if (prev_dup && IS_INSN_ID(nobj, dup) &&
3378 !!(nobj = (INSN *)nobj->link.next) &&
3380 nobj->insn_id == iobj->insn_id) {
3396 replace_destination(iobj, nobj);
3424 if (prev_dup && IS_INSN(pobj->link.prev)) {
3425 pobj = (INSN *)pobj->link.prev;
3427 if (IS_INSN_ID(pobj, putobject)) {
3428 cond = (IS_INSN_ID(iobj, branchif) ?
3429 OPERAND_AT(pobj, 0) !=
Qfalse :
3430 IS_INSN_ID(iobj, branchunless) ?
3431 OPERAND_AT(pobj, 0) ==
Qfalse :
3434 else if (IS_INSN_ID(pobj, putstring) ||
3435 IS_INSN_ID(pobj, duparray) ||
3436 IS_INSN_ID(pobj, newarray)) {
3437 cond = IS_INSN_ID(iobj, branchif);
3439 else if (IS_INSN_ID(pobj, putnil)) {
3440 cond = !IS_INSN_ID(iobj, branchif);
3443 if (prev_dup || !IS_INSN_ID(pobj, newarray)) {
3444 ELEM_REMOVE(iobj->link.prev);
3446 else if (!iseq_pop_newarray(iseq, pobj)) {
3447 NODE dummy_line_node = generate_dummy_line_node(pobj->insn_info.line_no, pobj->insn_info.node_id);
3448 pobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, NULL);
3449 ELEM_INSERT_PREV(&iobj->link, &pobj->link);
3453 NODE dummy_line_node = generate_dummy_line_node(pobj->insn_info.line_no, pobj->insn_info.node_id);
3454 pobj = new_insn_core(iseq, &dummy_line_node, BIN(putnil), 0, NULL);
3455 ELEM_INSERT_NEXT(&iobj->link, &pobj->link);
3457 iobj->insn_id = BIN(jump);
3461 unref_destination(iobj, 0);
3462 ELEM_REMOVE(&iobj->link);
3467 nobj = (INSN *)get_destination_insn(nobj);
3472 if (IS_INSN_ID(iobj, pop)) {
3479 LINK_ELEMENT *prev = iobj->link.prev;
3480 if (IS_INSN(prev)) {
3481 enum ruby_vminsn_type previ = ((INSN *)prev)->insn_id;
3482 if (previ == BIN(putobject) || previ == BIN(putnil) ||
3483 previ == BIN(putself) || previ == BIN(putstring) ||
3484 previ == BIN(dup) ||
3485 previ == BIN(getlocal) ||
3486 previ == BIN(getblockparam) ||
3487 previ == BIN(getblockparamproxy) ||
3488 previ == BIN(getinstancevariable) ||
3489 previ == BIN(duparray)) {
3493 ELEM_REMOVE(&iobj->link);
3495 else if (previ == BIN(newarray) && iseq_pop_newarray(iseq, (INSN*)prev)) {
3496 ELEM_REMOVE(&iobj->link);
3498 else if (previ == BIN(concatarray)) {
3499 INSN *piobj = (INSN *)prev;
3500 NODE dummy_line_node = generate_dummy_line_node(piobj->insn_info.line_no, piobj->insn_info.node_id);
3501 INSERT_BEFORE_INSN1(piobj, &dummy_line_node, splatarray,
Qfalse);
3502 INSN_OF(piobj) = BIN(pop);
3504 else if (previ == BIN(concatstrings)) {
3505 if (OPERAND_AT(prev, 0) ==
INT2FIX(1)) {
3509 ELEM_REMOVE(&iobj->link);
3510 INSN_OF(prev) = BIN(adjuststack);
3516 if (IS_INSN_ID(iobj, newarray) ||
3517 IS_INSN_ID(iobj, duparray) ||
3518 IS_INSN_ID(iobj, expandarray) ||
3519 IS_INSN_ID(iobj, concatarray) ||
3520 IS_INSN_ID(iobj, splatarray) ||
3529 LINK_ELEMENT *next = iobj->link.next;
3530 if (IS_INSN(next) && IS_INSN_ID(next, splatarray)) {
3536 if (IS_INSN_ID(iobj, newarray)) {
3537 LINK_ELEMENT *next = iobj->link.next;
3538 if (IS_INSN(next) && IS_INSN_ID(next, expandarray) &&
3539 OPERAND_AT(next, 1) ==
INT2FIX(0)) {
3541 op1 = OPERAND_AT(iobj, 0);
3542 op2 = OPERAND_AT(next, 0);
3553 INSN_OF(iobj) = BIN(swap);
3554 iobj->operand_size = 0;
3563 INSN_OF(iobj) = BIN(opt_reverse);
3567 NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
3569 INSN_OF(iobj) = BIN(opt_reverse);
3570 OPERAND_AT(iobj, 0) = OPERAND_AT(next, 0);
3580 for (; diff > 0; diff--) {
3581 INSERT_BEFORE_INSN(iobj, &dummy_line_node, pop);
3592 for (; diff < 0; diff++) {
3593 INSERT_BEFORE_INSN(iobj, &dummy_line_node, putnil);
3600 if (IS_INSN_ID(iobj, duparray)) {
3601 LINK_ELEMENT *next = iobj->link.next;
3609 if (IS_INSN(next) && IS_INSN_ID(next, expandarray)) {
3610 INSN_OF(iobj) = BIN(putobject);
3614 if (IS_INSN_ID(iobj, anytostring)) {
3615 LINK_ELEMENT *next = iobj->link.next;
3622 if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) &&
3623 OPERAND_AT(next, 0) ==
INT2FIX(1)) {
3628 if (IS_INSN_ID(iobj, putstring) ||
3629 (IS_INSN_ID(iobj, putobject) && RB_TYPE_P(OPERAND_AT(iobj, 0),
T_STRING))) {
3636 if (IS_NEXT_INSN_ID(&iobj->link, concatstrings) &&
3637 RSTRING_LEN(OPERAND_AT(iobj, 0)) == 0) {
3638 INSN *next = (INSN *)iobj->link.next;
3639 if ((OPERAND_AT(next, 0) = FIXNUM_INC(OPERAND_AT(next, 0), -1)) ==
INT2FIX(1)) {
3640 ELEM_REMOVE(&next->link);
3642 ELEM_REMOVE(&iobj->link);
3646 if (IS_INSN_ID(iobj, concatstrings)) {
3653 LINK_ELEMENT *next = iobj->link.next;
3655 if (IS_INSN(next) && IS_INSN_ID(next, jump))
3656 next = get_destination_insn(jump = (INSN *)next);
3657 if (IS_INSN(next) && IS_INSN_ID(next, concatstrings)) {
3658 int n =
FIX2INT(OPERAND_AT(iobj, 0)) +
FIX2INT(OPERAND_AT(next, 0)) - 1;
3659 OPERAND_AT(iobj, 0) =
INT2FIX(n);
3661 LABEL *label = ((LABEL *)OPERAND_AT(jump, 0));
3662 if (!--label->refcnt) {
3663 ELEM_REMOVE(&label->link);
3666 label = NEW_LABEL(0);
3667 OPERAND_AT(jump, 0) = (
VALUE)label;
3670 ELEM_INSERT_NEXT(next, &label->link);
3671 CHECK(iseq_peephole_optimize(iseq, get_next_insn(jump), do_tailcallopt));
3679 if (do_tailcallopt &&
3680 (IS_INSN_ID(iobj, send) ||
3681 IS_INSN_ID(iobj, opt_aref_with) ||
3682 IS_INSN_ID(iobj, opt_aset_with) ||
3683 IS_INSN_ID(iobj, invokesuper))) {
3692 if (iobj->link.next) {
3693 LINK_ELEMENT *next = iobj->link.next;
3695 if (!IS_INSN(next)) {
3699 switch (INSN_OF(next)) {
3708 next = get_destination_insn((INSN *)next);
3722 if (IS_INSN_ID(piobj, send) ||
3723 IS_INSN_ID(piobj, invokesuper)) {
3724 if (OPERAND_AT(piobj, 1) == 0) {
3725 ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
3726 OPERAND_AT(piobj, 0) = (
VALUE)ci;
3731 ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
3732 OPERAND_AT(piobj, 0) = (
VALUE)ci;
3738 if (IS_INSN_ID(iobj, dup)) {
3739 if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) {
3740 LINK_ELEMENT *set1 = iobj->link.next, *set2 = NULL;
3750 if (IS_NEXT_INSN_ID(set1, setlocal)) {
3752 if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
3753 OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
3755 ELEM_REMOVE(&iobj->link);
3768 else if (IS_NEXT_INSN_ID(set1, dup) &&
3769 IS_NEXT_INSN_ID(set1->next, setlocal)) {
3770 set2 = set1->next->next;
3771 if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
3772 OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
3773 ELEM_REMOVE(set1->next);
3787 if (IS_INSN_ID(iobj, getlocal)) {
3788 LINK_ELEMENT *niobj = &iobj->link;
3789 if (IS_NEXT_INSN_ID(niobj, dup)) {
3790 niobj = niobj->next;
3792 if (IS_NEXT_INSN_ID(niobj, setlocal)) {
3793 LINK_ELEMENT *set1 = niobj->next;
3794 if (OPERAND_AT(iobj, 0) == OPERAND_AT(set1, 0) &&
3795 OPERAND_AT(iobj, 1) == OPERAND_AT(set1, 1)) {
3811 if (IS_INSN_ID(iobj, opt_invokebuiltin_delegate)) {
3812 if (IS_TRACE(iobj->link.next)) {
3813 if (IS_NEXT_INSN_ID(iobj->link.next, leave)) {
3814 iobj->insn_id = BIN(opt_invokebuiltin_delegate_leave);
3816 if (iobj == (INSN *)list && bf->argc == 0 && (iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF)) {
3817 iseq->body->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_INLINE;
3830 if (IS_INSN_ID(iobj, getblockparam)) {
3831 if (IS_NEXT_INSN_ID(&iobj->link, branchif) || IS_NEXT_INSN_ID(&iobj->link, branchunless)) {
3832 iobj->insn_id = BIN(getblockparamproxy);
3836 if (IS_INSN_ID(iobj, splatarray) && OPERAND_AT(iobj, 0) ==
Qtrue) {
3837 LINK_ELEMENT *niobj = &iobj->link;
3848 if (IS_NEXT_INSN_ID(niobj, send)) {
3849 niobj = niobj->next;
3850 unsigned int flag = vm_ci_flag((
const struct rb_callinfo *)OPERAND_AT(niobj, 0));
3851 if ((flag & VM_CALL_ARGS_SPLAT) && !(flag & (VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG))) {
3852 OPERAND_AT(iobj, 0) =
Qfalse;
3854 }
else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) {
3855 niobj = niobj->next;
3857 if (IS_NEXT_INSN_ID(niobj, send)) {
3858 niobj = niobj->next;
3859 unsigned int flag = vm_ci_flag((
const struct rb_callinfo *)OPERAND_AT(niobj, 0));
3861 if ((flag & VM_CALL_ARGS_SPLAT)) {
3873 if ((flag & VM_CALL_ARGS_BLOCKARG) && !(flag & VM_CALL_KW_SPLAT)) {
3874 OPERAND_AT(iobj, 0) =
Qfalse;
3888 else if (!(flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT)) {
3889 OPERAND_AT(iobj, 0) =
Qfalse;
3893 else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
3894 IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
3895 niobj = niobj->next;
3910 if (IS_NEXT_INSN_ID(niobj, send)) {
3911 niobj = niobj->next;
3912 unsigned int flag = vm_ci_flag((
const struct rb_callinfo *)OPERAND_AT(niobj, 0));
3914 if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) && (flag & VM_CALL_ARGS_BLOCKARG)) {
3915 OPERAND_AT(iobj, 0) =
Qfalse;
3920 else if (IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
3921 niobj = niobj->next;
3923 if (IS_NEXT_INSN_ID(niobj, send)) {
3924 niobj = niobj->next;
3925 unsigned int flag = vm_ci_flag((
const struct rb_callinfo *)OPERAND_AT(niobj, 0));
3938 if ((flag & VM_CALL_ARGS_BLOCKARG) & (flag & VM_CALL_ARGS_SPLAT) && !(flag & VM_CALL_KW_SPLAT)) {
3939 OPERAND_AT(iobj, 0) =
Qfalse;
3943 else if (IS_NEXT_INSN_ID(niobj, duphash)) {
3944 niobj = niobj->next;
3957 if (IS_NEXT_INSN_ID(niobj, send)) {
3958 niobj = niobj->next;
3959 unsigned int flag = vm_ci_flag((
const struct rb_callinfo *)OPERAND_AT(niobj, 0));
3961 if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) &&
3962 (flag & VM_CALL_KW_SPLAT_MUT) && !(flag & VM_CALL_ARGS_BLOCKARG)) {
3963 OPERAND_AT(iobj, 0) =
Qfalse;
3966 else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
3967 IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
3968 niobj = niobj->next;
3983 if (IS_NEXT_INSN_ID(niobj, send)) {
3984 niobj = niobj->next;
3985 unsigned int flag = vm_ci_flag((
const struct rb_callinfo *)OPERAND_AT(niobj, 0));
3987 if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) &&
3988 (flag & VM_CALL_KW_SPLAT_MUT) && (flag & VM_CALL_ARGS_BLOCKARG)) {
3989 OPERAND_AT(iobj, 0) =
Qfalse;
4000insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj,
int insn_id)
4002 iobj->insn_id = insn_id;
4003 iobj->operand_size = insn_len(insn_id) - 1;
4006 if (insn_id == BIN(opt_neq)) {
4007 VALUE original_ci = iobj->operands[0];
4008 iobj->operand_size = 2;
4009 iobj->operands = compile_data_calloc2(iseq, iobj->operand_size,
sizeof(
VALUE));
4010 iobj->operands[0] = (
VALUE)new_callinfo(iseq, idEq, 1, 0, NULL, FALSE);
4011 iobj->operands[1] = original_ci;
4018iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
4020 if (IS_INSN_ID(iobj, newarray) && iobj->link.next &&
4021 IS_INSN(iobj->link.next)) {
4025 INSN *niobj = (INSN *)iobj->link.next;
4026 if (IS_INSN_ID(niobj, send)) {
4028 if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) {
4029 switch (vm_ci_mid(ci)) {
4034 VALUE num = iobj->operands[0];
4035 iobj->insn_id = BIN(opt_newarray_send);
4036 iobj->operands = compile_data_calloc2(iseq, insn_len(iobj->insn_id) - 1,
sizeof(
VALUE));
4037 iobj->operands[0] = num;
4038 iobj->operands[1] = rb_id2sym(vm_ci_mid(ci));
4039 iobj->operand_size = insn_len(iobj->insn_id) - 1;
4040 ELEM_REMOVE(&niobj->link);
4048 if (IS_INSN_ID(iobj, send)) {
4050 const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 1);
4052#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
4053 if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) {
4054 switch (vm_ci_argc(ci)) {
4056 switch (vm_ci_mid(ci)) {
4057 case idLength: SP_INSN(length);
return COMPILE_OK;
4058 case idSize: SP_INSN(size);
return COMPILE_OK;
4059 case idEmptyP: SP_INSN(empty_p);
return COMPILE_OK;
4060 case idNilP: SP_INSN(nil_p);
return COMPILE_OK;
4061 case idSucc: SP_INSN(succ);
return COMPILE_OK;
4062 case idNot: SP_INSN(not);
return COMPILE_OK;
4066 switch (vm_ci_mid(ci)) {
4067 case idPLUS: SP_INSN(plus);
return COMPILE_OK;
4068 case idMINUS: SP_INSN(minus);
return COMPILE_OK;
4069 case idMULT: SP_INSN(mult);
return COMPILE_OK;
4070 case idDIV: SP_INSN(div);
return COMPILE_OK;
4071 case idMOD: SP_INSN(mod);
return COMPILE_OK;
4072 case idEq: SP_INSN(eq);
return COMPILE_OK;
4073 case idNeq: SP_INSN(neq);
return COMPILE_OK;
4074 case idEqTilde:SP_INSN(regexpmatch2);
return COMPILE_OK;
4075 case idLT: SP_INSN(lt);
return COMPILE_OK;
4076 case idLE: SP_INSN(le);
return COMPILE_OK;
4077 case idGT: SP_INSN(gt);
return COMPILE_OK;
4078 case idGE: SP_INSN(ge);
return COMPILE_OK;
4079 case idLTLT: SP_INSN(ltlt);
return COMPILE_OK;
4080 case idAREF: SP_INSN(aref);
return COMPILE_OK;
4081 case idAnd: SP_INSN(and);
return COMPILE_OK;
4082 case idOr: SP_INSN(or);
return COMPILE_OK;
4086 switch (vm_ci_mid(ci)) {
4087 case idASET: SP_INSN(aset);
return COMPILE_OK;
4093 if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) {
4094 iobj->insn_id = BIN(opt_send_without_block);
4095 iobj->operand_size = insn_len(iobj->insn_id) - 1;
4104tailcallable_p(rb_iseq_t *iseq)
4106 switch (ISEQ_BODY(iseq)->
type) {
4108 case ISEQ_TYPE_EVAL:
4109 case ISEQ_TYPE_MAIN:
4111 case ISEQ_TYPE_RESCUE:
4112 case ISEQ_TYPE_ENSURE:
4121iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor)
4124 const int do_peepholeopt = ISEQ_COMPILE_DATA(iseq)->option->peephole_optimization;
4125 const int do_tailcallopt = tailcallable_p(iseq) &&
4126 ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization;
4127 const int do_si = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction;
4128 const int do_ou = ISEQ_COMPILE_DATA(iseq)->option->operands_unification;
4129 int rescue_level = 0;
4130 int tailcallopt = do_tailcallopt;
4132 list = FIRST_ELEMENT(anchor);
4134 int do_block_optimization = 0;
4136 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_BLOCK && !ISEQ_COMPILE_DATA(iseq)->catch_except_p) {
4137 do_block_optimization = 1;
4141 if (IS_INSN(list)) {
4142 if (do_peepholeopt) {
4143 iseq_peephole_optimize(iseq, list, tailcallopt);
4146 iseq_specialized_instruction(iseq, (INSN *)list);
4149 insn_operands_unification((INSN *)list);
4152 if (do_block_optimization) {
4153 INSN * item = (INSN *)list;
4154 if (IS_INSN_ID(item, jump)) {
4155 do_block_optimization = 0;
4159 if (IS_LABEL(list)) {
4160 switch (((LABEL *)list)->rescued) {
4161 case LABEL_RESCUE_BEG:
4163 tailcallopt = FALSE;
4165 case LABEL_RESCUE_END:
4166 if (!--rescue_level) tailcallopt = do_tailcallopt;
4173 if (do_block_optimization) {
4174 LINK_ELEMENT * le = FIRST_ELEMENT(anchor)->next;
4175 if (IS_INSN(le) && IS_INSN_ID((INSN *)le, nop)) {
4182#if OPT_INSTRUCTIONS_UNIFICATION
4184new_unified_insn(rb_iseq_t *iseq,
4185 int insn_id,
int size, LINK_ELEMENT *seq_list)
4188 LINK_ELEMENT *list = seq_list;
4190 VALUE *operands = 0, *ptr = 0;
4194 for (i = 0; i < size; i++) {
4195 iobj = (INSN *)list;
4196 argc += iobj->operand_size;
4201 ptr = operands = compile_data_alloc2(iseq,
sizeof(
VALUE), argc);
4206 for (i = 0; i < size; i++) {
4207 iobj = (INSN *)list;
4208 MEMCPY(ptr, iobj->operands,
VALUE, iobj->operand_size);
4209 ptr += iobj->operand_size;
4213 NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
4214 return new_insn_core(iseq, &dummy_line_node, insn_id, argc, operands);
4224iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor)
4226#if OPT_INSTRUCTIONS_UNIFICATION
4232 list = FIRST_ELEMENT(anchor);
4234 if (IS_INSN(list)) {
4235 iobj = (INSN *)list;
4237 if (unified_insns_data[
id] != 0) {
4238 const int *
const *entry = unified_insns_data[id];
4239 for (j = 1; j < (intptr_t)entry[0]; j++) {
4240 const int *unified = entry[j];
4241 LINK_ELEMENT *li = list->next;
4242 for (k = 2; k < unified[1]; k++) {
4244 ((INSN *)li)->insn_id != unified[k]) {
4251 new_unified_insn(iseq, unified[0], unified[1] - 1,
4255 niobj->link.prev = (LINK_ELEMENT *)iobj->link.prev;
4256 niobj->link.next = li;
4258 li->prev = (LINK_ELEMENT *)niobj;
4261 list->prev->next = (LINK_ELEMENT *)niobj;
4262 list = (LINK_ELEMENT *)niobj;
4275all_string_result_p(
const NODE *node)
4277 if (!node)
return FALSE;
4278 switch (nd_type(node)) {
4279 case NODE_STR:
case NODE_DSTR:
4281 case NODE_IF:
case NODE_UNLESS:
4282 if (!RNODE_IF(node)->nd_body || !RNODE_IF(node)->nd_else)
return FALSE;
4283 if (all_string_result_p(RNODE_IF(node)->nd_body))
4284 return all_string_result_p(RNODE_IF(node)->nd_else);
4286 case NODE_AND:
case NODE_OR:
4287 if (!RNODE_AND(node)->nd_2nd)
4288 return all_string_result_p(RNODE_AND(node)->nd_1st);
4289 if (!all_string_result_p(RNODE_AND(node)->nd_1st))
4291 return all_string_result_p(RNODE_AND(node)->nd_2nd);
4298compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int *cntp)
4300 const struct RNode_LIST *list = RNODE_DSTR(node)->nd_next;
4301 VALUE lit = RNODE_DSTR(node)->nd_lit;
4302 LINK_ELEMENT *first_lit = 0;
4305 debugp_param(
"nd_lit", lit);
4309 COMPILE_ERROR(ERROR_ARGS
"dstr: must be string: %s",
4310 rb_builtin_type_name(
TYPE(lit)));
4313 lit = rb_fstring(lit);
4314 ADD_INSN1(ret, node, putobject, lit);
4316 if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
4320 const NODE *
const head = list->nd_head;
4321 if (nd_type_p(head, NODE_STR)) {
4322 lit = rb_fstring(RNODE_STR(head)->nd_lit);
4323 ADD_INSN1(ret, head, putobject, lit);
4328 CHECK(COMPILE(ret,
"each string", head));
4333 if (
NIL_P(lit) && first_lit) {
4334 ELEM_REMOVE(first_lit);
4343compile_block(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *node,
int popped)
4345 while (node && nd_type_p(node, NODE_BLOCK)) {
4346 CHECK(COMPILE_(ret,
"BLOCK body", RNODE_BLOCK(node)->nd_head,
4347 (RNODE_BLOCK(node)->nd_next ? 1 : popped)));
4348 node = RNODE_BLOCK(node)->nd_next;
4351 CHECK(COMPILE_(ret,
"BLOCK next", RNODE_BLOCK(node)->nd_next, popped));
4357compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node)
4360 if (!RNODE_DSTR(node)->nd_next) {
4361 VALUE lit = rb_fstring(RNODE_DSTR(node)->nd_lit);
4362 ADD_INSN1(ret, node, putstring, lit);
4366 CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
4367 ADD_INSN1(ret, node, concatstrings,
INT2FIX(cnt));
4373compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
4377 if (!RNODE_DREGX(node)->nd_next) {
4378 VALUE match = RNODE_DREGX(node)->nd_lit;
4381 ADD_INSN1(ret, node, putobject, match);
4388 CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
4389 ADD_INSN2(ret, node, toregexp,
INT2FIX(RNODE_DREGX(node)->nd_cflag),
INT2FIX(cnt));
4392 ADD_INSN(ret, node, pop);
4399compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int again,
4400 LABEL *then_label, LABEL *else_label)
4402 const int line = nd_line(node);
4403 LABEL *lend = NEW_LABEL(line);
4404 rb_num_t cnt = ISEQ_FLIP_CNT_INCREMENT(ISEQ_BODY(iseq)->local_iseq)
4405 + VM_SVAR_FLIPFLOP_START;
4408 ADD_INSN2(ret, node, getspecial, key,
INT2FIX(0));
4409 ADD_INSNL(ret, node, branchif, lend);
4412 CHECK(COMPILE(ret,
"flip2 beg", RNODE_FLIP2(node)->nd_beg));
4413 ADD_INSNL(ret, node, branchunless, else_label);
4414 ADD_INSN1(ret, node, putobject,
Qtrue);
4415 ADD_INSN1(ret, node, setspecial, key);
4417 ADD_INSNL(ret, node, jump, then_label);
4421 ADD_LABEL(ret, lend);
4422 CHECK(COMPILE(ret,
"flip2 end", RNODE_FLIP2(node)->nd_end));
4423 ADD_INSNL(ret, node, branchunless, then_label);
4424 ADD_INSN1(ret, node, putobject,
Qfalse);
4425 ADD_INSN1(ret, node, setspecial, key);
4426 ADD_INSNL(ret, node, jump, then_label);
4432compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret,
const NODE *cond,
4433 LABEL *then_label, LABEL *else_label);
4435#define COMPILE_SINGLE 2
4437compile_logical(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *cond,
4438 LABEL *then_label, LABEL *else_label)
4442 LABEL *label = NEW_LABEL(nd_line(cond));
4443 if (!then_label) then_label = label;
4444 else if (!else_label) else_label = label;
4446 CHECK(compile_branch_condition(iseq, seq, cond, then_label, else_label));
4448 if (LIST_INSN_SIZE_ONE(seq)) {
4449 INSN *insn = (INSN *)ELEM_FIRST_INSN(FIRST_ELEMENT(seq));
4450 if (insn->insn_id == BIN(jump) && (LABEL *)(insn->operands[0]) == label)
4453 if (!label->refcnt) {
4454 return COMPILE_SINGLE;
4456 ADD_LABEL(seq, label);
4462compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret,
const NODE *cond,
4463 LABEL *then_label, LABEL *else_label)
4466 DECL_ANCHOR(ignore);
4469 switch (nd_type(cond)) {
4471 CHECK(ok = compile_logical(iseq, ret, RNODE_AND(cond)->nd_1st, NULL, else_label));
4472 cond = RNODE_AND(cond)->nd_2nd;
4473 if (ok == COMPILE_SINGLE) {
4474 INIT_ANCHOR(ignore);
4476 then_label = NEW_LABEL(nd_line(cond));
4480 CHECK(ok = compile_logical(iseq, ret, RNODE_OR(cond)->nd_1st, then_label, NULL));
4481 cond = RNODE_OR(cond)->nd_2nd;
4482 if (ok == COMPILE_SINGLE) {
4483 INIT_ANCHOR(ignore);
4485 else_label = NEW_LABEL(nd_line(cond));
4494 ADD_INSNL(ret, cond, jump, then_label);
4499 ADD_INSNL(ret, cond, jump, else_label);
4505 CHECK(COMPILE_POPPED(ret,
"branch condition", cond));
4506 ADD_INSNL(ret, cond, jump, then_label);
4509 CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label));
4512 CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
4515 CHECK(compile_defined_expr(iseq, ret, cond,
Qfalse));
4519 DECL_ANCHOR(cond_seq);
4520 INIT_ANCHOR(cond_seq);
4522 CHECK(COMPILE(cond_seq,
"branch condition", cond));
4524 if (LIST_INSN_SIZE_ONE(cond_seq)) {
4525 INSN *insn = (INSN *)ELEM_FIRST_INSN(FIRST_ELEMENT(cond_seq));
4526 if (insn->insn_id == BIN(putobject)) {
4527 if (
RTEST(insn->operands[0])) {
4528 ADD_INSNL(ret, cond, jump, then_label);
4533 ADD_INSNL(ret, cond, jump, else_label);
4538 ADD_SEQ(ret, cond_seq);
4543 ADD_INSNL(ret, cond, branchunless, else_label);
4544 ADD_INSNL(ret, cond, jump, then_label);
4551keyword_node_p(
const NODE *
const node)
4553 return nd_type_p(node, NODE_HASH) && (RNODE_HASH(node)->nd_brace & HASH_BRACE) != HASH_BRACE;
4557compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
4558 const NODE *
const root_node,
4566 if (RNODE_HASH(root_node)->nd_head && nd_type_p(RNODE_HASH(root_node)->nd_head, NODE_LIST)) {
4567 const NODE *node = RNODE_HASH(root_node)->nd_head;
4571 const NODE *key_node = RNODE_LIST(node)->nd_head;
4574 assert(nd_type_p(node, NODE_LIST));
4575 if (key_node && nd_type_p(key_node, NODE_LIT) &&
SYMBOL_P(RNODE_LIT(key_node)->nd_lit)) {
4580 *flag |= VM_CALL_KW_SPLAT;
4581 if (seen_nodes > 1 || RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
4586 *flag |= VM_CALL_KW_SPLAT_MUT;
4591 node = RNODE_LIST(node)->nd_next;
4592 node = RNODE_LIST(node)->nd_next;
4596 node = RNODE_HASH(root_node)->nd_head;
4598 int len = (int)RNODE_LIST(node)->as.nd_alen / 2;
4601 VALUE *keywords = kw_arg->keywords;
4603 kw_arg->references = 0;
4604 kw_arg->keyword_len =
len;
4606 *kw_arg_ptr = kw_arg;
4608 for (i=0; node != NULL; i++, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
4609 const NODE *key_node = RNODE_LIST(node)->nd_head;
4610 const NODE *val_node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head;
4611 keywords[i] = RNODE_LIT(key_node)->nd_lit;
4612 NO_CHECK(COMPILE(ret,
"keyword values", val_node));
4622compile_args(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *node, NODE **kwnode_ptr)
4626 for (; node;
len++, node = RNODE_LIST(node)->nd_next) {
4628 EXPECT_NODE(
"compile_args", node, NODE_LIST, -1);
4631 if (RNODE_LIST(node)->nd_next == NULL && keyword_node_p(RNODE_LIST(node)->nd_head)) {
4632 *kwnode_ptr = RNODE_LIST(node)->nd_head;
4635 RUBY_ASSERT(!keyword_node_p(RNODE_LIST(node)->nd_head));
4636 NO_CHECK(COMPILE_(ret,
"array element", RNODE_LIST(node)->nd_head, FALSE));
4644static_literal_node_p(
const NODE *node,
const rb_iseq_t *iseq)
4646 switch (nd_type(node)) {
4653 return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal;
4660static_literal_value(
const NODE *node, rb_iseq_t *iseq)
4662 switch (nd_type(node)) {
4670 if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal ||
RTEST(
ruby_debug)) {
4672 VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq),
INT2FIX((
int)nd_line(node)));
4673 lit = rb_str_dup(RNODE_STR(node)->nd_lit);
4674 rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
4678 return rb_fstring(RNODE_STR(node)->nd_lit);
4681 return RNODE_LIT(node)->nd_lit;
4686compile_array(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *node,
int popped)
4688 const NODE *line_node = node;
4690 if (nd_type_p(node, NODE_ZLIST)) {
4692 ADD_INSN1(ret, line_node, newarray,
INT2FIX(0));
4697 EXPECT_NODE(
"compile_array", node, NODE_LIST, -1);
4700 for (; node; node = RNODE_LIST(node)->nd_next) {
4701 NO_CHECK(COMPILE_(ret,
"array element", RNODE_LIST(node)->nd_head, popped));
4743 const int max_stack_len = 0x100;
4744 const int min_tmp_ary_len = 0x40;
4746 int first_chunk = 1;
4749#define FLUSH_CHUNK(newarrayinsn) \
4751 ADD_INSN1(ret, line_node, newarrayinsn, INT2FIX(stack_len)); \
4752 if (!first_chunk) ADD_INSN(ret, line_node, concatarray); \
4753 first_chunk = stack_len = 0; \
4760 if (static_literal_node_p(RNODE_LIST(node)->nd_head, iseq)) {
4762 const NODE *node_tmp = RNODE_LIST(node)->nd_next;
4763 for (; node_tmp && static_literal_node_p(RNODE_LIST(node_tmp)->nd_head, iseq); node_tmp = RNODE_LIST(node_tmp)->nd_next)
4766 if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_ary_len) {
4768 VALUE ary = rb_ary_hidden_new(count);
4771 for (; count; count--, node = RNODE_LIST(node)->nd_next)
4772 rb_ary_push(ary, static_literal_value(RNODE_LIST(node)->nd_head, iseq));
4776 FLUSH_CHUNK(newarray);
4778 ADD_INSN1(ret, line_node, duparray, ary);
4782 ADD_INSN1(ret, line_node, putobject, ary);
4783 ADD_INSN(ret, line_node, concatarray);
4790 for (; count; count--, node = RNODE_LIST(node)->nd_next) {
4792 EXPECT_NODE(
"compile_array", node, NODE_LIST, -1);
4795 NO_CHECK(COMPILE_(ret,
"array element", RNODE_LIST(node)->nd_head, 0));
4798 if (!RNODE_LIST(node)->nd_next && keyword_node_p(RNODE_LIST(node)->nd_head)) {
4800 FLUSH_CHUNK(newarraykwsplat);
4805 if (stack_len >= max_stack_len) FLUSH_CHUNK(newarray);
4809 FLUSH_CHUNK(newarray);
4816compile_array_1(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *node)
4818 if (static_literal_node_p(node, iseq)) {
4819 VALUE ary = rb_ary_hidden_new(1);
4820 rb_ary_push(ary, static_literal_value(node, iseq));
4823 ADD_INSN1(ret, node, duparray, ary);
4826 CHECK(COMPILE_(ret,
"array element", node, FALSE));
4827 if (keyword_node_p(node)) {
4828 ADD_INSN1(ret, node, newarraykwsplat,
INT2FIX(1));
4831 ADD_INSN1(ret, node, newarray,
INT2FIX(1));
4839static_literal_node_pair_p(
const NODE *node,
const rb_iseq_t *iseq)
4841 return RNODE_LIST(node)->nd_head && static_literal_node_p(RNODE_LIST(node)->nd_head, iseq) && static_literal_node_p(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq);
4845compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *node,
int method_call_keywords,
int popped)
4847 const NODE *line_node = node;
4849 node = RNODE_HASH(node)->nd_head;
4851 if (!node || nd_type_p(node, NODE_ZLIST)) {
4853 ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
4858 EXPECT_NODE(
"compile_hash", node, NODE_LIST, -1);
4861 for (; node; node = RNODE_LIST(node)->nd_next) {
4862 NO_CHECK(COMPILE_(ret,
"hash element", RNODE_LIST(node)->nd_head, popped));
4885 const int max_stack_len = 0x100;
4886 const int min_tmp_hash_len = 0x800;
4888 int first_chunk = 1;
4889 DECL_ANCHOR(anchor);
4890 INIT_ANCHOR(anchor);
4893#define FLUSH_CHUNK() \
4895 if (first_chunk) { \
4896 APPEND_LIST(ret, anchor); \
4897 ADD_INSN1(ret, line_node, newhash, INT2FIX(stack_len)); \
4900 ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \
4901 ADD_INSN(ret, line_node, swap); \
4902 APPEND_LIST(ret, anchor); \
4903 ADD_SEND(ret, line_node, id_core_hash_merge_ptr, INT2FIX(stack_len + 1)); \
4905 INIT_ANCHOR(anchor); \
4906 first_chunk = stack_len = 0; \
4913 if (static_literal_node_pair_p(node, iseq)) {
4915 const NODE *node_tmp = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next;
4916 for (; node_tmp && static_literal_node_pair_p(node_tmp, iseq); node_tmp = RNODE_LIST(RNODE_LIST(node_tmp)->nd_next)->nd_next)
4919 if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_hash_len) {
4921 VALUE ary = rb_ary_hidden_new(count);
4924 for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
4926 elem[0] = static_literal_value(RNODE_LIST(node)->nd_head, iseq);
4927 elem[1] = static_literal_value(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq);
4928 rb_ary_cat(ary, elem, 2);
4932 hash = rb_obj_hide(hash);
4938 ADD_INSN1(ret, line_node, duphash, hash);
4942 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
4943 ADD_INSN(ret, line_node, swap);
4945 ADD_INSN1(ret, line_node, putobject, hash);
4947 ADD_SEND(ret, line_node, id_core_hash_merge_kwd,
INT2FIX(2));
4954 for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
4957 EXPECT_NODE(
"compile_hash", node, NODE_LIST, -1);
4960 if (RNODE_LIST(node)->nd_head) {
4962 NO_CHECK(COMPILE_(anchor,
"hash key element", RNODE_LIST(node)->nd_head, 0));
4963 NO_CHECK(COMPILE_(anchor,
"hash value element", RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, 0));
4967 if (stack_len >= max_stack_len) FLUSH_CHUNK();
4973 const NODE *kw = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head;
4974 int empty_kw = nd_type_p(kw, NODE_LIT) && RB_TYPE_P(RNODE_LIT(kw)->nd_lit,
T_HASH);
4975 int first_kw = first_chunk && stack_len == 0;
4976 int last_kw = !RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next;
4977 int only_kw = last_kw && first_kw;
4980 if (only_kw && method_call_keywords) {
4988 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
4990 else if (first_kw) {
4994 ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
5001 if (only_kw && method_call_keywords) {
5007 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
5014 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5015 if (first_kw) ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
5016 else ADD_INSN(ret, line_node, swap);
5018 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
5020 ADD_SEND(ret, line_node, id_core_hash_merge_kwd,
INT2FIX(2));
5035rb_node_case_when_optimizable_literal(
const NODE *
const node)
5037 switch (nd_type(node)) {
5039 VALUE v = RNODE_LIT(node)->nd_lit;
5060 return rb_fstring(RNODE_STR(node)->nd_lit);
5066when_vals(rb_iseq_t *iseq, LINK_ANCHOR *
const cond_seq,
const NODE *vals,
5067 LABEL *l1,
int only_special_literals,
VALUE literals)
5070 const NODE *val = RNODE_LIST(vals)->nd_head;
5071 VALUE lit = rb_node_case_when_optimizable_literal(val);
5074 only_special_literals = 0;
5076 else if (
NIL_P(rb_hash_lookup(literals, lit))) {
5077 rb_hash_aset(literals, lit, (
VALUE)(l1) | 1);
5080 if (nd_type_p(val, NODE_STR)) {
5081 debugp_param(
"nd_lit", RNODE_STR(val)->nd_lit);
5082 lit = rb_fstring(RNODE_STR(val)->nd_lit);
5083 ADD_INSN1(cond_seq, val, putobject, lit);
5087 if (!COMPILE(cond_seq,
"when cond", val))
return -1;
5091 ADD_INSN1(cond_seq, vals, topn,
INT2FIX(1));
5092 ADD_CALL(cond_seq, vals, idEqq,
INT2FIX(1));
5093 ADD_INSNL(cond_seq, val, branchif, l1);
5094 vals = RNODE_LIST(vals)->nd_next;
5096 return only_special_literals;
5100when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *
const cond_seq,
const NODE *vals,
5101 LABEL *l1,
int only_special_literals,
VALUE literals)
5103 const NODE *line_node = vals;
5105 switch (nd_type(vals)) {
5107 if (when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals) < 0)
5111 ADD_INSN (cond_seq, line_node, dup);
5112 CHECK(COMPILE(cond_seq,
"when splat", RNODE_SPLAT(vals)->nd_head));
5113 ADD_INSN1(cond_seq, line_node, splatarray,
Qfalse);
5114 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
5115 ADD_INSNL(cond_seq, line_node, branchif, l1);
5118 CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSCAT(vals)->nd_head, l1, only_special_literals, literals));
5119 CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSCAT(vals)->nd_body, l1, only_special_literals, literals));
5122 CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSPUSH(vals)->nd_head, l1, only_special_literals, literals));
5123 ADD_INSN (cond_seq, line_node, dup);
5124 CHECK(COMPILE(cond_seq,
"when argspush body", RNODE_ARGSPUSH(vals)->nd_body));
5125 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
5126 ADD_INSNL(cond_seq, line_node, branchif, l1);
5129 ADD_INSN (cond_seq, line_node, dup);
5130 CHECK(COMPILE(cond_seq,
"when val", vals));
5131 ADD_INSN1(cond_seq, line_node, splatarray,
Qfalse);
5132 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
5133 ADD_INSNL(cond_seq, line_node, branchif, l1);
5226 const NODE *line_node;
5241add_masgn_lhs_node(
struct masgn_state *state,
int lhs_pos,
const NODE *line_node,
int argc, INSN *before_insn)
5244 rb_bug(
"no masgn_state");
5253 memo->before_insn = before_insn;
5254 memo->line_node = line_node;
5255 memo->argn = state->num_args + 1;
5256 memo->num_args = argc;
5257 state->num_args += argc;
5258 memo->lhs_pos = lhs_pos;
5260 if (!state->first_memo) {
5261 state->first_memo = memo;
5264 state->last_memo->next = memo;
5266 state->last_memo = memo;
5271static int compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *
const pre, LINK_ANCHOR *
const rhs, LINK_ANCHOR *
const lhs, LINK_ANCHOR *
const post,
const NODE *
const node,
struct masgn_state *state,
int popped);
5274compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *
const pre, LINK_ANCHOR *
const rhs, LINK_ANCHOR *
const lhs, LINK_ANCHOR *
const post,
const NODE *
const node,
struct masgn_state *state,
int lhs_pos)
5276 switch (nd_type(node)) {
5277 case NODE_ATTRASGN: {
5279 const NODE *line_node = node;
5281 CHECK(COMPILE_POPPED(pre,
"masgn lhs (NODE_ATTRASGN)", node));
5283 bool safenav_call =
false;
5284 LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
5285 iobj = (INSN *)get_prev_insn((INSN *)insn_element);
5287 ELEM_REMOVE(insn_element);
5288 if (!IS_INSN_ID(iobj, send)) {
5289 safenav_call =
true;
5290 iobj = (INSN *)get_prev_insn(iobj);
5291 ELEM_INSERT_NEXT(&iobj->link, insn_element);
5293 (pre->last = iobj->link.prev)->next = 0;
5296 int argc = vm_ci_argc(ci) + 1;
5297 ci = ci_argc_set(iseq, ci, argc);
5298 OPERAND_AT(iobj, 0) = (
VALUE)ci;
5302 ADD_INSN(lhs, line_node, swap);
5305 ADD_INSN1(lhs, line_node, topn,
INT2FIX(argc));
5308 if (!add_masgn_lhs_node(state, lhs_pos, line_node, argc, (INSN *)LAST_ELEMENT(lhs))) {
5312 iobj->link.prev = lhs->last;
5313 lhs->last->next = &iobj->link;
5314 for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next);
5315 if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
5316 int argc = vm_ci_argc(ci);
5317 ci = ci_argc_set(iseq, ci, argc - 1);
5318 OPERAND_AT(iobj, 0) = (
VALUE)ci;
5320 INSERT_BEFORE_INSN1(iobj, line_node, newarray,
INT2FIX(1));
5321 INSERT_BEFORE_INSN(iobj, line_node, concatarray);
5323 if (!safenav_call) {
5324 ADD_INSN(lhs, line_node, pop);
5326 ADD_INSN(lhs, line_node, pop);
5329 for (
int i=0; i < argc; i++) {
5330 ADD_INSN(post, line_node, pop);
5335 DECL_ANCHOR(nest_rhs);
5336 INIT_ANCHOR(nest_rhs);
5337 DECL_ANCHOR(nest_lhs);
5338 INIT_ANCHOR(nest_lhs);
5340 int prev_level = state->lhs_level;
5341 bool prev_nested = state->nested;
5343 state->lhs_level = lhs_pos - 1;
5344 CHECK(compile_massign0(iseq, pre, nest_rhs, nest_lhs, post, node, state, 1));
5345 state->lhs_level = prev_level;
5346 state->nested = prev_nested;
5348 ADD_SEQ(lhs, nest_rhs);
5349 ADD_SEQ(lhs, nest_lhs);
5353 if (!RNODE_CDECL(node)->nd_vid) {
5357 CHECK(COMPILE_POPPED(pre,
"masgn lhs (NODE_CDECL)", node));
5359 LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
5360 iobj = (INSN *)insn_element;
5361 ELEM_REMOVE((LINK_ELEMENT *)get_prev_insn((INSN *)get_prev_insn(iobj)));
5362 ELEM_REMOVE((LINK_ELEMENT *)get_prev_insn(iobj));
5363 ELEM_REMOVE(insn_element);
5364 pre->last = iobj->link.prev;
5365 ADD_ELEM(lhs, (LINK_ELEMENT *)iobj);
5367 if (!add_masgn_lhs_node(state, lhs_pos, node, 1, (INSN *)LAST_ELEMENT(lhs))) {
5371 ADD_INSN(post, node, pop);
5376 DECL_ANCHOR(anchor);
5377 INIT_ANCHOR(anchor);
5378 CHECK(COMPILE_POPPED(anchor,
"masgn lhs", node));
5379 ELEM_REMOVE(FIRST_ELEMENT(anchor));
5380 ADD_SEQ(lhs, anchor);
5388compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *lhsn)
5391 CHECK(compile_massign_opt_lhs(iseq, ret, RNODE_LIST(lhsn)->nd_next));
5392 CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, RNODE_LIST(lhsn)->nd_head, NULL, 0));
5398compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
5399 const NODE *rhsn,
const NODE *orig_lhsn)
5402 const int memsize = numberof(mem);
5404 int llen = 0, rlen = 0;
5406 const NODE *lhsn = orig_lhsn;
5408#define MEMORY(v) { \
5410 if (memindex == memsize) return 0; \
5411 for (i=0; i<memindex; i++) { \
5412 if (mem[i] == (v)) return 0; \
5414 mem[memindex++] = (v); \
5417 if (rhsn == 0 || !nd_type_p(rhsn, NODE_LIST)) {
5422 const NODE *ln = RNODE_LIST(lhsn)->nd_head;
5423 switch (nd_type(ln)) {
5428 MEMORY(get_nd_vid(ln));
5433 lhsn = RNODE_LIST(lhsn)->nd_next;
5439 NO_CHECK(COMPILE_POPPED(ret,
"masgn val (popped)", RNODE_LIST(rhsn)->nd_head));
5442 NO_CHECK(COMPILE(ret,
"masgn val", RNODE_LIST(rhsn)->nd_head));
5444 rhsn = RNODE_LIST(rhsn)->nd_next;
5449 for (i=0; i<llen-rlen; i++) {
5450 ADD_INSN(ret, orig_lhsn, putnil);
5454 compile_massign_opt_lhs(iseq, ret, orig_lhsn);
5459compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *
const pre, LINK_ANCHOR *
const rhs, LINK_ANCHOR *
const lhs, LINK_ANCHOR *
const post,
const NODE *
const node,
struct masgn_state *state,
int popped)
5461 const NODE *rhsn = RNODE_MASGN(node)->nd_value;
5462 const NODE *splatn = RNODE_MASGN(node)->nd_args;
5463 const NODE *lhsn = RNODE_MASGN(node)->nd_head;
5464 const NODE *lhsn_count = lhsn;
5465 int lhs_splat = (splatn && NODE_NAMED_REST_P(splatn)) ? 1 : 0;
5470 while (lhsn_count) {
5472 lhsn_count = RNODE_LIST(lhsn_count)->nd_next;
5475 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, RNODE_LIST(lhsn)->nd_head, state, (llen - lpos) + lhs_splat + state->lhs_level));
5477 lhsn = RNODE_LIST(lhsn)->nd_next;
5481 if (nd_type_p(splatn, NODE_POSTARG)) {
5483 const NODE *postn = RNODE_POSTARG(splatn)->nd_2nd;
5484 const NODE *restn = RNODE_POSTARG(splatn)->nd_1st;
5485 int plen = (int)RNODE_LIST(postn)->as.nd_alen;
5487 int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00);
5489 ADD_INSN2(lhs, splatn, expandarray,
INT2FIX(plen),
INT2FIX(flag));
5491 if (NODE_NAMED_REST_P(restn)) {
5492 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, restn, state, 1 + plen + state->lhs_level));
5495 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, RNODE_LIST(postn)->nd_head, state, (plen - ppos) + state->lhs_level));
5497 postn = RNODE_LIST(postn)->nd_next;
5502 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, splatn, state, 1 + state->lhs_level));
5506 if (!state->nested) {
5507 NO_CHECK(COMPILE(rhs,
"normal masgn rhs", rhsn));
5511 ADD_INSN(rhs, node, dup);
5513 ADD_INSN2(rhs, node, expandarray,
INT2FIX(llen),
INT2FIX(lhs_splat));
5518compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
5520 if (!popped || RNODE_MASGN(node)->nd_args || !compile_massign_opt(iseq, ret, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head)) {
5522 state.lhs_level = popped ? 0 : 1;
5525 state.first_memo = NULL;
5526 state.last_memo = NULL;
5536 int ok = compile_massign0(iseq, pre, rhs, lhs, post, node, &state, popped);
5540 VALUE topn_arg =
INT2FIX((state.num_args - memo->argn) + memo->lhs_pos);
5541 for (
int i = 0; i < memo->num_args; i++) {
5542 INSERT_BEFORE_INSN1(memo->before_insn, memo->line_node, topn, topn_arg);
5544 tmp_memo = memo->next;
5553 if (!popped && state.num_args >= 1) {
5555 ADD_INSN1(ret, node, setn,
INT2FIX(state.num_args));
5563collect_const_segments(rb_iseq_t *iseq,
const NODE *node)
5565 VALUE arr = rb_ary_new();
5567 switch (nd_type(node)) {
5569 rb_ary_unshift(arr,
ID2SYM(RNODE_CONST(node)->nd_vid));
5572 rb_ary_unshift(arr,
ID2SYM(RNODE_COLON3(node)->nd_mid));
5573 rb_ary_unshift(arr,
ID2SYM(idNULL));
5576 rb_ary_unshift(arr,
ID2SYM(RNODE_COLON2(node)->nd_mid));
5577 node = RNODE_COLON2(node)->nd_head;
5586compile_const_prefix(rb_iseq_t *iseq,
const NODE *
const node,
5587 LINK_ANCHOR *
const pref, LINK_ANCHOR *
const body)
5589 switch (nd_type(node)) {
5591 debugi(
"compile_const_prefix - colon", RNODE_CONST(node)->nd_vid);
5592 ADD_INSN1(body, node, putobject,
Qtrue);
5593 ADD_INSN1(body, node, getconstant,
ID2SYM(RNODE_CONST(node)->nd_vid));
5596 debugi(
"compile_const_prefix - colon3", RNODE_COLON3(node)->nd_mid);
5597 ADD_INSN(body, node, pop);
5598 ADD_INSN1(body, node, putobject, rb_cObject);
5599 ADD_INSN1(body, node, putobject,
Qtrue);
5600 ADD_INSN1(body, node, getconstant,
ID2SYM(RNODE_COLON3(node)->nd_mid));
5603 CHECK(compile_const_prefix(iseq, RNODE_COLON2(node)->nd_head, pref, body));
5604 debugi(
"compile_const_prefix - colon2", RNODE_COLON2(node)->nd_mid);
5605 ADD_INSN1(body, node, putobject,
Qfalse);
5606 ADD_INSN1(body, node, getconstant,
ID2SYM(RNODE_COLON2(node)->nd_mid));
5609 CHECK(COMPILE(pref,
"const colon2 prefix", node));
5616compile_cpath(LINK_ANCHOR *
const ret, rb_iseq_t *iseq,
const NODE *cpath)
5618 if (nd_type_p(cpath, NODE_COLON3)) {
5620 ADD_INSN1(ret, cpath, putobject, rb_cObject);
5621 return VM_DEFINECLASS_FLAG_SCOPED;
5623 else if (nd_type_p(cpath, NODE_COLON2) && RNODE_COLON2(cpath)->nd_head) {
5625 NO_CHECK(COMPILE(ret,
"nd_else->nd_head", RNODE_COLON2(cpath)->nd_head));
5626 return VM_DEFINECLASS_FLAG_SCOPED;
5630 ADD_INSN1(ret, cpath, putspecialobject,
5631 INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
5637private_recv_p(
const NODE *node)
5639 NODE *recv = get_nd_recv(node);
5640 if (recv && nd_type_p(recv, NODE_SELF)) {
5641 return RNODE_SELF(recv)->nd_state != 0;
5647defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
5648 const NODE *
const node, LABEL **lfinish,
VALUE needstr);
5651compile_call(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
const enum node_type
type,
const NODE *
const line_node,
int popped,
bool assume_receiver);
5654defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
5655 const NODE *
const node, LABEL **lfinish,
VALUE needstr,
5658 enum defined_type expr_type = DEFINED_NOT_DEFINED;
5659 enum node_type
type;
5660 const int line = nd_line(node);
5661 const NODE *line_node = node;
5663 switch (
type = nd_type(node)) {
5667 expr_type = DEFINED_NIL;
5670 expr_type = DEFINED_SELF;
5673 expr_type = DEFINED_TRUE;
5676 expr_type = DEFINED_FALSE;
5680 const NODE *vals = node;
5683 defined_expr0(iseq, ret, RNODE_LIST(vals)->nd_head, lfinish,
Qfalse,
false);
5686 lfinish[1] = NEW_LABEL(line);
5688 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
5689 }
while ((vals = RNODE_LIST(vals)->nd_next) != NULL);
5698 expr_type = DEFINED_EXPR;
5704 expr_type = DEFINED_LVAR;
5707#define PUSH_VAL(type) (needstr == Qfalse ? Qtrue : rb_iseq_defined_string(type))
5709 ADD_INSN3(ret, line_node, definedivar,
5710 ID2SYM(RNODE_IVAR(node)->nd_vid), get_ivar_ic_value(iseq,RNODE_IVAR(node)->nd_vid), PUSH_VAL(DEFINED_IVAR));
5714 ADD_INSN(ret, line_node, putnil);
5715 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_GVAR),
5716 ID2SYM(RNODE_GVAR(node)->nd_vid), PUSH_VAL(DEFINED_GVAR));
5720 ADD_INSN(ret, line_node, putnil);
5721 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CVAR),
5722 ID2SYM(RNODE_CVAR(node)->nd_vid), PUSH_VAL(DEFINED_CVAR));
5726 ADD_INSN(ret, line_node, putnil);
5727 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CONST),
5728 ID2SYM(RNODE_CONST(node)->nd_vid), PUSH_VAL(DEFINED_CONST));
5732 lfinish[1] = NEW_LABEL(line);
5734 defined_expr0(iseq, ret, RNODE_COLON2(node)->nd_head, lfinish,
Qfalse,
false);
5735 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
5736 NO_CHECK(COMPILE(ret,
"defined/colon2#nd_head", RNODE_COLON2(node)->nd_head));
5739 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CONST_FROM),
5740 ID2SYM(RNODE_COLON2(node)->nd_mid), PUSH_VAL(DEFINED_CONST));
5743 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_METHOD),
5744 ID2SYM(RNODE_COLON2(node)->nd_mid), PUSH_VAL(DEFINED_METHOD));
5748 ADD_INSN1(ret, line_node, putobject, rb_cObject);
5749 ADD_INSN3(ret, line_node, defined,
5750 INT2FIX(DEFINED_CONST_FROM),
ID2SYM(RNODE_COLON3(node)->nd_mid), PUSH_VAL(DEFINED_CONST));
5758 case NODE_ATTRASGN:{
5759 const int explicit_receiver =
5760 (
type == NODE_CALL ||
type == NODE_OPCALL ||
5761 (
type == NODE_ATTRASGN && !private_recv_p(node)));
5763 if (get_nd_args(node) || explicit_receiver) {
5765 lfinish[1] = NEW_LABEL(line);
5768 lfinish[2] = NEW_LABEL(line);
5771 if (get_nd_args(node)) {
5772 defined_expr0(iseq, ret, get_nd_args(node), lfinish,
Qfalse,
false);
5773 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
5775 if (explicit_receiver) {
5776 defined_expr0(iseq, ret, get_nd_recv(node), lfinish,
Qfalse,
true);
5777 switch (nd_type(get_nd_recv(node))) {
5783 ADD_INSNL(ret, line_node, branchunless, lfinish[2]);
5784 compile_call(iseq, ret, get_nd_recv(node), nd_type(get_nd_recv(node)), line_node, 0,
true);
5787 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
5788 NO_CHECK(COMPILE(ret,
"defined/recv", get_nd_recv(node)));
5792 ADD_INSN(ret, line_node, dup);
5794 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_METHOD),
5795 ID2SYM(get_node_call_nd_mid(node)), PUSH_VAL(DEFINED_METHOD));
5798 ADD_INSN(ret, line_node, putself);
5800 ADD_INSN(ret, line_node, dup);
5802 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_FUNC),
5803 ID2SYM(get_node_call_nd_mid(node)), PUSH_VAL(DEFINED_METHOD));
5809 ADD_INSN(ret, line_node, putnil);
5810 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_YIELD), 0,
5811 PUSH_VAL(DEFINED_YIELD));
5816 ADD_INSN(ret, line_node, putnil);
5817 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_REF),
5818 INT2FIX((RNODE_BACK_REF(node)->nd_nth << 1) | (
type == NODE_BACK_REF)),
5819 PUSH_VAL(DEFINED_GVAR));
5824 ADD_INSN(ret, line_node, putnil);
5825 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_ZSUPER), 0,
5826 PUSH_VAL(DEFINED_ZSUPER));
5832 case NODE_OP_ASGN_OR:
5833 case NODE_OP_ASGN_AND:
5841 expr_type = DEFINED_ASGN;
5845 assert(expr_type != DEFINED_NOT_DEFINED);
5848 VALUE str = rb_iseq_defined_string(expr_type);
5849 ADD_INSN1(ret, line_node, putobject, str);
5852 ADD_INSN1(ret, line_node, putobject,
Qtrue);
5857build_defined_rescue_iseq(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const void *unused)
5859 NODE dummy_line_node = generate_dummy_line_node(0, -1);
5860 ADD_INSN(ret, &dummy_line_node, putnil);
5861 iseq_set_exception_local_table(iseq);
5865defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
5866 const NODE *
const node, LABEL **lfinish,
VALUE needstr)
5868 LINK_ELEMENT *lcur = ret->last;
5869 defined_expr0(iseq, ret, node, lfinish, needstr,
false);
5871 int line = nd_line(node);
5872 LABEL *lstart = NEW_LABEL(line);
5873 LABEL *lend = NEW_LABEL(line);
5874 const rb_iseq_t *rescue;
5876 rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq, NULL);
5877 rescue = new_child_iseq_with_callback(iseq, ifunc,
5879 ISEQ_BODY(iseq)->location.label),
5880 iseq, ISEQ_TYPE_RESCUE, 0);
5881 lstart->rescued = LABEL_RESCUE_BEG;
5882 lend->rescued = LABEL_RESCUE_END;
5883 APPEND_LABEL(ret, lcur, lstart);
5884 ADD_LABEL(ret, lend);
5885 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
5890compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
VALUE needstr)
5892 const int line = nd_line(node);
5893 const NODE *line_node = node;
5894 if (!RNODE_DEFINED(node)->nd_head) {
5895 VALUE str = rb_iseq_defined_string(DEFINED_NIL);
5896 ADD_INSN1(ret, line_node, putobject, str);
5900 LINK_ELEMENT *last = ret->last;
5901 lfinish[0] = NEW_LABEL(line);
5904 defined_expr(iseq, ret, RNODE_DEFINED(node)->nd_head, lfinish, needstr);
5906 ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line_node, BIN(putnil), 0)->link);
5907 ADD_INSN(ret, line_node, swap);
5909 ADD_LABEL(ret, lfinish[2]);
5911 ADD_INSN(ret, line_node, pop);
5912 ADD_LABEL(ret, lfinish[1]);
5914 ADD_LABEL(ret, lfinish[0]);
5920make_name_for_block(
const rb_iseq_t *orig_iseq)
5923 const rb_iseq_t *iseq = orig_iseq;
5925 if (ISEQ_BODY(orig_iseq)->parent_iseq != 0) {
5926 while (ISEQ_BODY(orig_iseq)->local_iseq != iseq) {
5927 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_BLOCK) {
5930 iseq = ISEQ_BODY(iseq)->parent_iseq;
5935 return rb_sprintf(
"block in %"PRIsVALUE, ISEQ_BODY(iseq)->location.label);
5938 return rb_sprintf(
"block (%d levels) in %"PRIsVALUE, level, ISEQ_BODY(iseq)->location.label);
5943push_ensure_entry(rb_iseq_t *iseq,
5947 enl->ensure_node = node;
5948 enl->prev = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
5950 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl;
5954add_ensure_range(rb_iseq_t *iseq,
struct ensure_range *erange,
5955 LABEL *lstart, LABEL *lend)
5960 while (erange->next != 0) {
5961 erange = erange->next;
5965 ne->end = erange->end;
5966 erange->end = lstart;
5972can_add_ensure_iseq(
const rb_iseq_t *iseq)
5975 if (ISEQ_COMPILE_DATA(iseq)->in_rescue && (e = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack) != NULL) {
5977 if (e->ensure_node)
return false;
5985add_ensure_iseq(LINK_ANCHOR *
const ret, rb_iseq_t *iseq,
int is_return)
5987 assert(can_add_ensure_iseq(iseq));
5990 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
5992 DECL_ANCHOR(ensure);
5994 INIT_ANCHOR(ensure);
5996 if (enlp->erange != NULL) {
5997 DECL_ANCHOR(ensure_part);
5998 LABEL *lstart = NEW_LABEL(0);
5999 LABEL *lend = NEW_LABEL(0);
6000 INIT_ANCHOR(ensure_part);
6002 add_ensure_range(iseq, enlp->erange, lstart, lend);
6004 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enlp->prev;
6005 ADD_LABEL(ensure_part, lstart);
6006 NO_CHECK(COMPILE_POPPED(ensure_part,
"ensure part", enlp->ensure_node));
6007 ADD_LABEL(ensure_part, lend);
6008 ADD_SEQ(ensure, ensure_part);
6017 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = prev_enlp;
6018 ADD_SEQ(ret, ensure);
6023check_keyword(
const NODE *node)
6027 if (nd_type_p(node, NODE_LIST)) {
6028 while (RNODE_LIST(node)->nd_next) {
6029 node = RNODE_LIST(node)->nd_next;
6031 node = RNODE_LIST(node)->nd_head;
6034 return keyword_node_p(node);
6039keyword_node_single_splat_p(NODE *kwnode)
6043 NODE *node = RNODE_HASH(kwnode)->nd_head;
6044 return RNODE_LIST(node)->nd_head == NULL &&
6045 RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next == NULL;
6049setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *
const args,
const NODE *argn,
6052 if (!argn)
return 0;
6054 NODE *kwnode = NULL;
6056 switch (nd_type(argn)) {
6059 int len = compile_args(iseq, args, argn, &kwnode);
6060 RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_ARGS_SPLAT) == 0);
6063 if (compile_keyword_arg(iseq, args, kwnode, kwarg_ptr, flag_ptr)) {
6067 compile_hash(iseq, args, kwnode, TRUE, FALSE);
6075 NO_CHECK(COMPILE(args,
"args (splat)", RNODE_SPLAT(argn)->nd_head));
6076 ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
6077 if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
6078 RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0);
6081 case NODE_ARGSCAT: {
6082 if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
6083 int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, 1, NULL, NULL);
6085 if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) {
6086 int rest_len = compile_args(iseq, args, RNODE_ARGSCAT(argn)->nd_body, &kwnode);
6087 if (kwnode) rest_len--;
6088 ADD_INSN1(args, argn, newarray,
INT2FIX(rest_len));
6091 RUBY_ASSERT(!check_keyword(RNODE_ARGSCAT(argn)->nd_body));
6092 NO_CHECK(COMPILE(args,
"args (cat: splat)", RNODE_ARGSCAT(argn)->nd_body));
6095 if (nd_type_p(RNODE_ARGSCAT(argn)->nd_head, NODE_LIST)) {
6096 ADD_INSN1(args, argn, splatarray,
Qtrue);
6100 ADD_INSN1(args, argn, splatarray,
Qfalse);
6101 ADD_INSN(args, argn, concatarray);
6107 *flag_ptr |= VM_CALL_KW_SPLAT;
6108 compile_hash(iseq, args, kwnode, TRUE, FALSE);
6114 case NODE_ARGSPUSH: {
6115 if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
6116 int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
6118 if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) {
6119 int rest_len = compile_args(iseq, args, RNODE_ARGSPUSH(argn)->nd_body, &kwnode);
6120 if (kwnode) rest_len--;
6121 ADD_INSN1(args, argn, newarray,
INT2FIX(rest_len));
6122 ADD_INSN1(args, argn, newarray,
INT2FIX(1));
6123 ADD_INSN(args, argn, concatarray);
6126 if (keyword_node_p(RNODE_ARGSPUSH(argn)->nd_body)) {
6127 kwnode = RNODE_ARGSPUSH(argn)->nd_body;
6130 NO_CHECK(COMPILE(args,
"args (cat: splat)", RNODE_ARGSPUSH(argn)->nd_body));
6131 ADD_INSN1(args, argn, newarray,
INT2FIX(1));
6132 ADD_INSN(args, argn, concatarray);
6138 *flag_ptr |= VM_CALL_KW_SPLAT;
6139 if (!keyword_node_single_splat_p(kwnode)) {
6140 *flag_ptr |= VM_CALL_KW_SPLAT_MUT;
6142 compile_hash(iseq, args, kwnode, TRUE, FALSE);
6149 UNKNOWN_NODE(
"setup_arg", argn,
Qnil);
6155setup_args(rb_iseq_t *iseq, LINK_ANCHOR *
const args,
const NODE *argn,
6159 if (argn && nd_type_p(argn, NODE_BLOCK_PASS)) {
6160 unsigned int dup_rest = 1;
6161 DECL_ANCHOR(arg_block);
6162 INIT_ANCHOR(arg_block);
6163 NO_CHECK(COMPILE(arg_block,
"block", RNODE_BLOCK_PASS(argn)->nd_body));
6165 *flag |= VM_CALL_ARGS_BLOCKARG;
6167 if (LIST_INSN_SIZE_ONE(arg_block)) {
6168 LINK_ELEMENT *elem = FIRST_ELEMENT(arg_block);
6169 if (IS_INSN(elem)) {
6170 INSN *iobj = (INSN *)elem;
6171 if (iobj->insn_id == BIN(getblockparam)) {
6172 iobj->insn_id = BIN(getblockparamproxy);
6177 ret =
INT2FIX(setup_args_core(iseq, args, RNODE_BLOCK_PASS(argn)->nd_head, dup_rest, flag, keywords));
6178 ADD_SEQ(args, arg_block);
6181 ret =
INT2FIX(setup_args_core(iseq, args, argn, 0, flag, keywords));
6187build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret,
const void *ptr)
6189 const NODE *body = ptr;
6190 int line = nd_line(body);
6192 const rb_iseq_t *block = NEW_CHILD_ISEQ(body, make_name_for_block(ISEQ_BODY(iseq)->parent_iseq), ISEQ_TYPE_BLOCK, line);
6194 ADD_INSN1(ret, body, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6195 ADD_CALL_WITH_BLOCK(ret, body, id_core_set_postexe, argc, block);
6197 iseq_set_local_table(iseq, 0);
6201compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node)
6205 int line = nd_line(node);
6206 const NODE *line_node = node;
6207 LABEL *fail_label = NEW_LABEL(line), *end_label = NEW_LABEL(line);
6209#if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0)
6210 ADD_INSN1(ret, line_node, getglobal,
ID2SYM(idBACKREF));
6214 ADD_INSN(ret, line_node, dup);
6215 ADD_INSNL(ret, line_node, branchunless, fail_label);
6217 for (vars = node; vars; vars = RNODE_BLOCK(vars)->nd_next) {
6219 if (RNODE_BLOCK(vars)->nd_next) {
6220 ADD_INSN(ret, line_node, dup);
6223 NO_CHECK(COMPILE_POPPED(ret,
"capture", RNODE_BLOCK(vars)->nd_head));
6225 cap = new_insn_send(iseq, line_node, idAREF,
INT2FIX(1),
6227 ELEM_INSERT_PREV(last->next, (LINK_ELEMENT *)cap);
6228#if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
6229 if (!RNODE_BLOCK(vars)->nd_next && vars == node) {
6234 ADD_INSNL(nom, line_node, jump, end_label);
6235 ADD_LABEL(nom, fail_label);
6237 ADD_INSN(nom, line_node, pop);
6238 ADD_INSN(nom, line_node, putnil);
6240 ADD_LABEL(nom, end_label);
6241 (nom->last->next = cap->link.next)->prev = nom->last;
6242 (cap->link.next = nom->anchor.next)->prev = &cap->link;
6247 ADD_INSNL(ret, line_node, jump, end_label);
6248 ADD_LABEL(ret, fail_label);
6249 ADD_INSN(ret, line_node, pop);
6250 for (vars = node; vars; vars = RNODE_BLOCK(vars)->nd_next) {
6252 NO_CHECK(COMPILE_POPPED(ret,
"capture", RNODE_BLOCK(vars)->nd_head));
6254 ((INSN*)last)->insn_id = BIN(putnil);
6255 ((INSN*)last)->operand_size = 0;
6257 ADD_LABEL(ret, end_label);
6261optimizable_range_item_p(
const NODE *n)
6263 if (!n)
return FALSE;
6264 switch (nd_type(n)) {
6275compile_if(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped,
const enum node_type
type)
6277 const NODE *
const node_body =
type == NODE_IF ? RNODE_IF(node)->nd_body : RNODE_UNLESS(node)->nd_else;
6278 const NODE *
const node_else =
type == NODE_IF ? RNODE_IF(node)->nd_else : RNODE_UNLESS(node)->nd_body;
6280 const int line = nd_line(node);
6281 const NODE *line_node = node;
6282 DECL_ANCHOR(cond_seq);
6283 LABEL *then_label, *else_label, *end_label;
6286 INIT_ANCHOR(cond_seq);
6287 then_label = NEW_LABEL(line);
6288 else_label = NEW_LABEL(line);
6291 compile_branch_condition(iseq, cond_seq, RNODE_IF(node)->nd_cond, then_label, else_label);
6292 ADD_SEQ(ret, cond_seq);
6294 if (then_label->refcnt && else_label->refcnt) {
6295 branches = decl_branch_base(iseq, node,
type == NODE_IF ?
"if" :
"unless");
6298 if (then_label->refcnt) {
6299 ADD_LABEL(ret, then_label);
6301 DECL_ANCHOR(then_seq);
6302 INIT_ANCHOR(then_seq);
6303 CHECK(COMPILE_(then_seq,
"then", node_body, popped));
6305 if (else_label->refcnt) {
6306 add_trace_branch_coverage(
6309 node_body ? node_body : node,
6311 type == NODE_IF ?
"then" :
"else",
6313 end_label = NEW_LABEL(line);
6314 ADD_INSNL(then_seq, line_node, jump, end_label);
6316 ADD_INSN(then_seq, line_node, pop);
6319 ADD_SEQ(ret, then_seq);
6322 if (else_label->refcnt) {
6323 ADD_LABEL(ret, else_label);
6325 DECL_ANCHOR(else_seq);
6326 INIT_ANCHOR(else_seq);
6327 CHECK(COMPILE_(else_seq,
"else", node_else, popped));
6329 if (then_label->refcnt) {
6330 add_trace_branch_coverage(
6333 node_else ? node_else : node,
6335 type == NODE_IF ?
"else" :
"then",
6338 ADD_SEQ(ret, else_seq);
6342 ADD_LABEL(ret, end_label);
6349compile_case(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const orig_node,
int popped)
6352 const NODE *node = orig_node;
6353 LABEL *endlabel, *elselabel;
6355 DECL_ANCHOR(body_seq);
6356 DECL_ANCHOR(cond_seq);
6357 int only_special_literals = 1;
6358 VALUE literals = rb_hash_new();
6360 enum node_type
type;
6361 const NODE *line_node;
6366 INIT_ANCHOR(body_seq);
6367 INIT_ANCHOR(cond_seq);
6369 RHASH_TBL_RAW(literals)->type = &cdhash_type;
6371 CHECK(COMPILE(head,
"case base", RNODE_CASE(node)->nd_head));
6373 branches = decl_branch_base(iseq, node,
"case");
6375 node = RNODE_CASE(node)->nd_body;
6376 EXPECT_NODE(
"NODE_CASE", node, NODE_WHEN, COMPILE_NG);
6377 type = nd_type(node);
6378 line = nd_line(node);
6381 endlabel = NEW_LABEL(line);
6382 elselabel = NEW_LABEL(line);
6386 while (
type == NODE_WHEN) {
6389 l1 = NEW_LABEL(line);
6390 ADD_LABEL(body_seq, l1);
6391 ADD_INSN(body_seq, line_node, pop);
6392 add_trace_branch_coverage(
6395 RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node,
6399 CHECK(COMPILE_(body_seq,
"when body", RNODE_WHEN(node)->nd_body, popped));
6400 ADD_INSNL(body_seq, line_node, jump, endlabel);
6402 vals = RNODE_WHEN(node)->nd_head;
6404 switch (nd_type(vals)) {
6406 only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
6407 if (only_special_literals < 0)
return COMPILE_NG;
6412 only_special_literals = 0;
6413 CHECK(when_splat_vals(iseq, cond_seq, vals, l1, only_special_literals, literals));
6416 UNKNOWN_NODE(
"NODE_CASE", vals, COMPILE_NG);
6420 EXPECT_NODE_NONULL(
"NODE_CASE", node, NODE_LIST, COMPILE_NG);
6423 node = RNODE_WHEN(node)->nd_next;
6427 type = nd_type(node);
6428 line = nd_line(node);
6433 ADD_LABEL(cond_seq, elselabel);
6434 ADD_INSN(cond_seq, line_node, pop);
6435 add_trace_branch_coverage(iseq, cond_seq, node, branch_id,
"else", branches);
6436 CHECK(COMPILE_(cond_seq,
"else", node, popped));
6437 ADD_INSNL(cond_seq, line_node, jump, endlabel);
6440 debugs(
"== else (implicit)\n");
6441 ADD_LABEL(cond_seq, elselabel);
6442 ADD_INSN(cond_seq, orig_node, pop);
6443 add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id,
"else", branches);
6445 ADD_INSN(cond_seq, orig_node, putnil);
6447 ADD_INSNL(cond_seq, orig_node, jump, endlabel);
6450 if (only_special_literals && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
6451 ADD_INSN(ret, orig_node, dup);
6452 ADD_INSN2(ret, orig_node, opt_case_dispatch, literals, elselabel);
6454 LABEL_REF(elselabel);
6457 ADD_SEQ(ret, cond_seq);
6458 ADD_SEQ(ret, body_seq);
6459 ADD_LABEL(ret, endlabel);
6464compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const orig_node,
int popped)
6468 const NODE *node = RNODE_CASE2(orig_node)->nd_body;
6470 DECL_ANCHOR(body_seq);
6474 branches = decl_branch_base(iseq, orig_node,
"case");
6476 INIT_ANCHOR(body_seq);
6477 endlabel = NEW_LABEL(nd_line(node));
6479 while (node && nd_type_p(node, NODE_WHEN)) {
6480 const int line = nd_line(node);
6481 LABEL *l1 = NEW_LABEL(line);
6482 ADD_LABEL(body_seq, l1);
6483 add_trace_branch_coverage(
6486 RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node,
6490 CHECK(COMPILE_(body_seq,
"when", RNODE_WHEN(node)->nd_body, popped));
6491 ADD_INSNL(body_seq, node, jump, endlabel);
6493 vals = RNODE_WHEN(node)->nd_head;
6495 EXPECT_NODE_NONULL(
"NODE_WHEN", node, NODE_LIST, COMPILE_NG);
6497 switch (nd_type(vals)) {
6501 val = RNODE_LIST(vals)->nd_head;
6502 lnext = NEW_LABEL(nd_line(val));
6503 debug_compile(
"== when2\n", (
void)0);
6504 CHECK(compile_branch_condition(iseq, ret, val, l1, lnext));
6505 ADD_LABEL(ret, lnext);
6506 vals = RNODE_LIST(vals)->nd_next;
6512 ADD_INSN(ret, vals, putnil);
6513 CHECK(COMPILE(ret,
"when2/cond splat", vals));
6514 ADD_INSN1(ret, vals, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY));
6515 ADD_INSNL(ret, vals, branchif, l1);
6518 UNKNOWN_NODE(
"NODE_WHEN", vals, COMPILE_NG);
6520 node = RNODE_WHEN(node)->nd_next;
6523 add_trace_branch_coverage(
6526 node ? node : orig_node,
6530 CHECK(COMPILE_(ret,
"else", node, popped));
6531 ADD_INSNL(ret, orig_node, jump, endlabel);
6533 ADD_SEQ(ret, body_seq);
6534 ADD_LABEL(ret, endlabel);
6538static int iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node, LABEL *unmatched,
bool in_single_pattern,
bool in_alt_pattern,
int base_index,
bool use_deconstructed_cache);
6540static int iseq_compile_pattern_constant(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node, LABEL *match_failed,
bool in_single_pattern,
int base_index);
6541static int iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error,
bool in_single_pattern,
int base_index,
bool use_deconstructed_cache);
6542static int iseq_compile_pattern_set_general_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
VALUE errmsg,
int base_index);
6543static int iseq_compile_pattern_set_length_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
VALUE errmsg,
VALUE pattern_length,
int base_index);
6544static int iseq_compile_pattern_set_eqq_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int base_index);
6546#define CASE3_BI_OFFSET_DECONSTRUCTED_CACHE 0
6547#define CASE3_BI_OFFSET_ERROR_STRING 1
6548#define CASE3_BI_OFFSET_KEY_ERROR_P 2
6549#define CASE3_BI_OFFSET_KEY_ERROR_MATCHEE 3
6550#define CASE3_BI_OFFSET_KEY_ERROR_KEY 4
6553iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node, LABEL *matched, LABEL *unmatched,
bool in_single_pattern,
bool in_alt_pattern,
int base_index,
bool use_deconstructed_cache)
6555 const int line = nd_line(node);
6556 const NODE *line_node = node;
6558 switch (nd_type(node)) {
6612 const NODE *args = RNODE_ARYPTN(node)->pre_args;
6613 const int pre_args_num = RNODE_ARYPTN(node)->pre_args ?
rb_long2int(RNODE_LIST(RNODE_ARYPTN(node)->pre_args)->as.nd_alen) : 0;
6614 const int post_args_num = RNODE_ARYPTN(node)->post_args ?
rb_long2int(RNODE_LIST(RNODE_ARYPTN(node)->post_args)->as.nd_alen) : 0;
6616 const int min_argc = pre_args_num + post_args_num;
6617 const int use_rest_num = RNODE_ARYPTN(node)->rest_arg && (NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg) ||
6618 (!NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg) && post_args_num > 0));
6620 LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
6622 match_failed = NEW_LABEL(line);
6623 type_error = NEW_LABEL(line);
6624 deconstruct = NEW_LABEL(line);
6625 deconstructed = NEW_LABEL(line);
6628 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
6629 ADD_INSN(ret, line_node, swap);
6635 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
6637 CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
6639 ADD_INSN(ret, line_node, dup);
6640 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6641 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
6642 ADD_SEND(ret, line_node, RNODE_ARYPTN(node)->rest_arg ? idGE : idEq,
INT2FIX(1));
6643 if (in_single_pattern) {
6644 CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node,
6645 RNODE_ARYPTN(node)->rest_arg ? rb_fstring_lit(
"%p length mismatch (given %p, expected %p+)") :
6646 rb_fstring_lit(
"%p length mismatch (given %p, expected %p)"),
6647 INT2FIX(min_argc), base_index + 1 ));
6649 ADD_INSNL(ret, line_node, branchunless, match_failed);
6651 for (i = 0; i < pre_args_num; i++) {
6652 ADD_INSN(ret, line_node, dup);
6653 ADD_INSN1(ret, line_node, putobject,
INT2FIX(i));
6654 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
6655 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
6656 args = RNODE_LIST(args)->nd_next;
6659 if (RNODE_ARYPTN(node)->rest_arg) {
6660 if (NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg)) {
6661 ADD_INSN(ret, line_node, dup);
6662 ADD_INSN1(ret, line_node, putobject,
INT2FIX(pre_args_num));
6663 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
6664 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6665 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
6666 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
6667 ADD_INSN1(ret, line_node, setn,
INT2FIX(4));
6668 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
6670 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_ARYPTN(node)->rest_arg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
6673 if (post_args_num > 0) {
6674 ADD_INSN(ret, line_node, dup);
6675 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6676 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
6677 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
6678 ADD_INSN1(ret, line_node, setn,
INT2FIX(2));
6679 ADD_INSN(ret, line_node, pop);
6684 args = RNODE_ARYPTN(node)->post_args;
6685 for (i = 0; i < post_args_num; i++) {
6686 ADD_INSN(ret, line_node, dup);
6688 ADD_INSN1(ret, line_node, putobject,
INT2FIX(pre_args_num + i));
6689 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6690 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
6692 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
6693 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
6694 args = RNODE_LIST(args)->nd_next;
6697 ADD_INSN(ret, line_node, pop);
6699 ADD_INSN(ret, line_node, pop);
6701 ADD_INSNL(ret, line_node, jump, matched);
6702 ADD_INSN(ret, line_node, putnil);
6704 ADD_INSN(ret, line_node, putnil);
6707 ADD_LABEL(ret, type_error);
6708 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6710 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct must return Array"));
6711 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
6712 ADD_INSN(ret, line_node, pop);
6714 ADD_LABEL(ret, match_failed);
6715 ADD_INSN(ret, line_node, pop);
6717 ADD_INSN(ret, line_node, pop);
6719 ADD_INSNL(ret, line_node, jump, unmatched);
6772 const NODE *args = RNODE_FNDPTN(node)->args;
6773 const int args_num = RNODE_FNDPTN(node)->args ?
rb_long2int(RNODE_LIST(RNODE_FNDPTN(node)->args)->as.nd_alen) : 0;
6775 LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
6776 match_failed = NEW_LABEL(line);
6777 type_error = NEW_LABEL(line);
6778 deconstruct = NEW_LABEL(line);
6779 deconstructed = NEW_LABEL(line);
6781 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
6783 CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
6785 ADD_INSN(ret, line_node, dup);
6786 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6787 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
6788 ADD_SEND(ret, line_node, idGE,
INT2FIX(1));
6789 if (in_single_pattern) {
6790 CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node, rb_fstring_lit(
"%p length mismatch (given %p, expected %p+)"),
INT2FIX(args_num), base_index + 1 ));
6792 ADD_INSNL(ret, line_node, branchunless, match_failed);
6795 LABEL *while_begin = NEW_LABEL(nd_line(node));
6796 LABEL *next_loop = NEW_LABEL(nd_line(node));
6797 LABEL *find_succeeded = NEW_LABEL(line);
6798 LABEL *find_failed = NEW_LABEL(nd_line(node));
6801 ADD_INSN(ret, line_node, dup);
6802 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6804 ADD_INSN(ret, line_node, dup);
6805 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
6806 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
6808 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
6810 ADD_LABEL(ret, while_begin);
6812 ADD_INSN(ret, line_node, dup);
6813 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
6814 ADD_SEND(ret, line_node, idLE,
INT2FIX(1));
6815 ADD_INSNL(ret, line_node, branchunless, find_failed);
6817 for (j = 0; j < args_num; j++) {
6818 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6819 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
6821 ADD_INSN1(ret, line_node, putobject,
INT2FIX(j));
6822 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
6824 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
6826 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, next_loop, in_single_pattern, in_alt_pattern, base_index + 4 ,
false));
6827 args = RNODE_LIST(args)->nd_next;
6830 if (NODE_NAMED_REST_P(RNODE_FNDPTN(node)->pre_rest_arg)) {
6831 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6832 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
6833 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
6834 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
6835 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_FNDPTN(node)->pre_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 ,
false));
6837 if (NODE_NAMED_REST_P(RNODE_FNDPTN(node)->post_rest_arg)) {
6838 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6839 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
6840 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
6841 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
6842 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6843 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
6844 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_FNDPTN(node)->post_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 ,
false));
6846 ADD_INSNL(ret, line_node, jump, find_succeeded);
6848 ADD_LABEL(ret, next_loop);
6849 ADD_INSN1(ret, line_node, putobject,
INT2FIX(1));
6850 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
6851 ADD_INSNL(ret, line_node, jump, while_begin);
6853 ADD_LABEL(ret, find_failed);
6854 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(3));
6855 if (in_single_pattern) {
6856 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6857 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"%p does not match to find pattern"));
6858 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
6859 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(2));
6860 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
6862 ADD_INSN1(ret, line_node, putobject,
Qfalse);
6863 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
6865 ADD_INSN(ret, line_node, pop);
6866 ADD_INSN(ret, line_node, pop);
6868 ADD_INSNL(ret, line_node, jump, match_failed);
6869 ADD_INSN1(ret, line_node, dupn,
INT2FIX(3));
6871 ADD_LABEL(ret, find_succeeded);
6872 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(3));
6875 ADD_INSN(ret, line_node, pop);
6876 ADD_INSNL(ret, line_node, jump, matched);
6877 ADD_INSN(ret, line_node, putnil);
6879 ADD_LABEL(ret, type_error);
6880 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6882 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct must return Array"));
6883 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
6884 ADD_INSN(ret, line_node, pop);
6886 ADD_LABEL(ret, match_failed);
6887 ADD_INSN(ret, line_node, pop);
6888 ADD_INSNL(ret, line_node, jump, unmatched);
6952 LABEL *match_failed, *type_error;
6955 match_failed = NEW_LABEL(line);
6956 type_error = NEW_LABEL(line);
6958 if (RNODE_HSHPTN(node)->nd_pkwargs && !RNODE_HSHPTN(node)->nd_pkwrestarg) {
6959 const NODE *kw_args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head;
6960 keys = rb_ary_new_capa(kw_args ? RNODE_LIST(kw_args)->as.nd_alen/2 : 0);
6962 rb_ary_push(keys, RNODE_LIT(RNODE_LIST(kw_args)->nd_head)->nd_lit);
6963 kw_args = RNODE_LIST(RNODE_LIST(kw_args)->nd_next)->nd_next;
6967 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
6969 ADD_INSN(ret, line_node, dup);
6970 ADD_INSN1(ret, line_node, putobject,
ID2SYM(rb_intern(
"deconstruct_keys")));
6971 ADD_SEND(ret, line_node, idRespond_to,
INT2FIX(1));
6972 if (in_single_pattern) {
6973 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p does not respond to #deconstruct_keys"), base_index + 1 ));
6975 ADD_INSNL(ret, line_node, branchunless, match_failed);
6978 ADD_INSN(ret, line_node, putnil);
6981 ADD_INSN1(ret, line_node, duparray, keys);
6984 ADD_SEND(ret, line_node, rb_intern(
"deconstruct_keys"),
INT2FIX(1));
6986 ADD_INSN(ret, line_node, dup);
6988 ADD_INSNL(ret, line_node, branchunless, type_error);
6990 if (RNODE_HSHPTN(node)->nd_pkwrestarg) {
6991 ADD_SEND(ret, line_node, rb_intern(
"dup"),
INT2FIX(0));
6994 if (RNODE_HSHPTN(node)->nd_pkwargs) {
6998 args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head;
7000 DECL_ANCHOR(match_values);
7001 INIT_ANCHOR(match_values);
7002 keys_num =
rb_long2int(RNODE_LIST(args)->as.nd_alen) / 2;
7003 for (i = 0; i < keys_num; i++) {
7004 NODE *key_node = RNODE_LIST(args)->nd_head;
7005 NODE *value_node = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_head;
7008 if (!nd_type_p(key_node, NODE_LIT)) {
7009 UNKNOWN_NODE(
"NODE_IN", key_node, COMPILE_NG);
7011 key = RNODE_LIT(key_node)->nd_lit;
7013 ADD_INSN(ret, line_node, dup);
7014 ADD_INSN1(ret, line_node, putobject, key);
7015 ADD_SEND(ret, line_node, rb_intern(
"key?"),
INT2FIX(1));
7016 if (in_single_pattern) {
7017 LABEL *match_succeeded;
7018 match_succeeded = NEW_LABEL(line);
7020 ADD_INSN(ret, line_node, dup);
7021 ADD_INSNL(ret, line_node, branchif, match_succeeded);
7023 ADD_INSN1(ret, line_node, putobject,
rb_str_freeze(rb_sprintf(
"key not found: %+"PRIsVALUE, key)));
7024 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 2 ));
7025 ADD_INSN1(ret, line_node, putobject,
Qtrue);
7026 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 3 ));
7027 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7028 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4 ));
7029 ADD_INSN1(ret, line_node, putobject, key);
7030 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_KEY + 5 ));
7032 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(4));
7034 ADD_LABEL(ret, match_succeeded);
7036 ADD_INSNL(ret, line_node, branchunless, match_failed);
7038 ADD_INSN(match_values, line_node, dup);
7039 ADD_INSN1(match_values, line_node, putobject, key);
7040 ADD_SEND(match_values, line_node, RNODE_HSHPTN(node)->nd_pkwrestarg ? rb_intern(
"delete") : idAREF,
INT2FIX(1));
7041 CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
7042 args = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_next;
7044 ADD_SEQ(ret, match_values);
7048 ADD_INSN(ret, line_node, dup);
7049 ADD_SEND(ret, line_node, idEmptyP,
INT2FIX(0));
7050 if (in_single_pattern) {
7051 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p is not empty"), base_index + 1 ));
7053 ADD_INSNL(ret, line_node, branchunless, match_failed);
7056 if (RNODE_HSHPTN(node)->nd_pkwrestarg) {
7057 if (RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
7058 ADD_INSN(ret, line_node, dup);
7059 ADD_SEND(ret, line_node, idEmptyP,
INT2FIX(0));
7060 if (in_single_pattern) {
7061 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"rest of %p is not empty"), base_index + 1 ));
7063 ADD_INSNL(ret, line_node, branchunless, match_failed);
7066 ADD_INSN(ret, line_node, dup);
7067 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_HSHPTN(node)->nd_pkwrestarg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
7071 ADD_INSN(ret, line_node, pop);
7072 ADD_INSNL(ret, line_node, jump, matched);
7073 ADD_INSN(ret, line_node, putnil);
7075 ADD_LABEL(ret, type_error);
7076 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7078 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct_keys must return Hash"));
7079 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
7080 ADD_INSN(ret, line_node, pop);
7082 ADD_LABEL(ret, match_failed);
7083 ADD_INSN(ret, line_node, pop);
7084 ADD_INSNL(ret, line_node, jump, unmatched);
7112 CHECK(COMPILE(ret,
"case in literal", node));
7113 if (in_single_pattern) {
7114 ADD_INSN1(ret, line_node, dupn,
INT2FIX(2));
7116 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
7117 if (in_single_pattern) {
7118 CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 2 ));
7120 ADD_INSNL(ret, line_node, branchif, matched);
7121 ADD_INSNL(ret, line_node, jump, unmatched);
7125 ID id = RNODE_LASGN(node)->nd_vid;
7126 int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
7128 if (in_alt_pattern) {
7129 const char *name = rb_id2name(
id);
7130 if (name && strlen(name) > 0 && name[0] !=
'_') {
7131 COMPILE_ERROR(ERROR_ARGS
"illegal variable in alternative pattern (%"PRIsVALUE
")",
7137 ADD_SETLOCAL(ret, line_node, idx, get_lvar_level(iseq));
7138 ADD_INSNL(ret, line_node, jump, matched);
7143 ID id = RNODE_DASGN(node)->nd_vid;
7145 idx = get_dyna_var_idx(iseq,
id, &lv, &ls);
7147 if (in_alt_pattern) {
7148 const char *name = rb_id2name(
id);
7149 if (name && strlen(name) > 0 && name[0] !=
'_') {
7150 COMPILE_ERROR(ERROR_ARGS
"illegal variable in alternative pattern (%"PRIsVALUE
")",
7157 COMPILE_ERROR(ERROR_ARGS
"NODE_DASGN: unknown id (%"PRIsVALUE
")",
7161 ADD_SETLOCAL(ret, line_node, ls - idx, lv);
7162 ADD_INSNL(ret, line_node, jump, matched);
7167 LABEL *match_failed;
7168 match_failed = unmatched;
7169 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_IF(node)->nd_body, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
7170 CHECK(COMPILE(ret,
"case in if", RNODE_IF(node)->nd_cond));
7171 if (in_single_pattern) {
7172 LABEL *match_succeeded;
7173 match_succeeded = NEW_LABEL(line);
7175 ADD_INSN(ret, line_node, dup);
7176 if (nd_type_p(node, NODE_IF)) {
7177 ADD_INSNL(ret, line_node, branchif, match_succeeded);
7180 ADD_INSNL(ret, line_node, branchunless, match_succeeded);
7183 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"guard clause does not return true"));
7184 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
7185 ADD_INSN1(ret, line_node, putobject,
Qfalse);
7186 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
7188 ADD_INSN(ret, line_node, pop);
7189 ADD_INSN(ret, line_node, pop);
7191 ADD_LABEL(ret, match_succeeded);
7193 if (nd_type_p(node, NODE_IF)) {
7194 ADD_INSNL(ret, line_node, branchunless, match_failed);
7197 ADD_INSNL(ret, line_node, branchif, match_failed);
7199 ADD_INSNL(ret, line_node, jump, matched);
7204 LABEL *match_failed;
7205 match_failed = NEW_LABEL(line);
7207 n = RNODE_HASH(node)->nd_head;
7208 if (! (nd_type_p(n, NODE_LIST) && RNODE_LIST(n)->as.nd_alen == 2)) {
7209 COMPILE_ERROR(ERROR_ARGS
"unexpected node");
7213 ADD_INSN(ret, line_node, dup);
7214 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(n)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 , use_deconstructed_cache));
7215 CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head, matched, match_failed, in_single_pattern, in_alt_pattern, base_index,
false));
7216 ADD_INSN(ret, line_node, putnil);
7218 ADD_LABEL(ret, match_failed);
7219 ADD_INSN(ret, line_node, pop);
7220 ADD_INSNL(ret, line_node, jump, unmatched);
7224 LABEL *match_succeeded, *fin;
7225 match_succeeded = NEW_LABEL(line);
7226 fin = NEW_LABEL(line);
7228 ADD_INSN(ret, line_node, dup);
7229 CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_OR(node)->nd_1st, match_succeeded, fin, in_single_pattern,
true, base_index + 1 , use_deconstructed_cache));
7230 ADD_LABEL(ret, match_succeeded);
7231 ADD_INSN(ret, line_node, pop);
7232 ADD_INSNL(ret, line_node, jump, matched);
7233 ADD_INSN(ret, line_node, putnil);
7234 ADD_LABEL(ret, fin);
7235 CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_OR(node)->nd_2nd, matched, unmatched, in_single_pattern,
true, base_index, use_deconstructed_cache));
7239 UNKNOWN_NODE(
"NODE_IN", node, COMPILE_NG);
7245iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node, LABEL *unmatched,
bool in_single_pattern,
bool in_alt_pattern,
int base_index,
bool use_deconstructed_cache)
7247 LABEL *fin = NEW_LABEL(nd_line(node));
7248 CHECK(iseq_compile_pattern_each(iseq, ret, node, fin, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
7249 ADD_LABEL(ret, fin);
7254iseq_compile_pattern_constant(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node, LABEL *match_failed,
bool in_single_pattern,
int base_index)
7256 const NODE *line_node = node;
7258 if (RNODE_ARYPTN(node)->nd_pconst) {
7259 ADD_INSN(ret, line_node, dup);
7260 CHECK(COMPILE(ret,
"constant", RNODE_ARYPTN(node)->nd_pconst));
7261 if (in_single_pattern) {
7262 ADD_INSN1(ret, line_node, dupn,
INT2FIX(2));
7264 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
7265 if (in_single_pattern) {
7266 CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 3 ));
7268 ADD_INSNL(ret, line_node, branchunless, match_failed);
7275iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error,
bool in_single_pattern,
int base_index,
bool use_deconstructed_cache)
7277 const NODE *line_node = node;
7281 if (use_deconstructed_cache) {
7283 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
7284 ADD_INSNL(ret, line_node, branchnil, deconstruct);
7287 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
7288 ADD_INSNL(ret, line_node, branchunless, match_failed);
7291 ADD_INSN(ret, line_node, pop);
7292 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE - 1 ));
7293 ADD_INSNL(ret, line_node, jump, deconstructed);
7296 ADD_INSNL(ret, line_node, jump, deconstruct);
7299 ADD_LABEL(ret, deconstruct);
7300 ADD_INSN(ret, line_node, dup);
7301 ADD_INSN1(ret, line_node, putobject,
ID2SYM(rb_intern(
"deconstruct")));
7302 ADD_SEND(ret, line_node, idRespond_to,
INT2FIX(1));
7305 if (use_deconstructed_cache) {
7306 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE + 1 ));
7309 if (in_single_pattern) {
7310 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p does not respond to #deconstruct"), base_index + 1 ));
7313 ADD_INSNL(ret, line_node, branchunless, match_failed);
7315 ADD_SEND(ret, line_node, rb_intern(
"deconstruct"),
INT2FIX(0));
7318 if (use_deconstructed_cache) {
7319 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
7322 ADD_INSN(ret, line_node, dup);
7324 ADD_INSNL(ret, line_node, branchunless, type_error);
7326 ADD_LABEL(ret, deconstructed);
7332iseq_compile_pattern_set_general_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
VALUE errmsg,
int base_index)
7342 const int line = nd_line(node);
7343 const NODE *line_node = node;
7344 LABEL *match_succeeded = NEW_LABEL(line);
7346 ADD_INSN(ret, line_node, dup);
7347 ADD_INSNL(ret, line_node, branchif, match_succeeded);
7349 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7350 ADD_INSN1(ret, line_node, putobject, errmsg);
7351 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7352 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(2));
7353 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
7355 ADD_INSN1(ret, line_node, putobject,
Qfalse);
7356 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
7358 ADD_INSN(ret, line_node, pop);
7359 ADD_INSN(ret, line_node, pop);
7360 ADD_LABEL(ret, match_succeeded);
7366iseq_compile_pattern_set_length_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
VALUE errmsg,
VALUE pattern_length,
int base_index)
7376 const int line = nd_line(node);
7377 const NODE *line_node = node;
7378 LABEL *match_succeeded = NEW_LABEL(line);
7380 ADD_INSN(ret, line_node, dup);
7381 ADD_INSNL(ret, line_node, branchif, match_succeeded);
7383 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7384 ADD_INSN1(ret, line_node, putobject, errmsg);
7385 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7386 ADD_INSN(ret, line_node, dup);
7387 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
7388 ADD_INSN1(ret, line_node, putobject, pattern_length);
7389 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(4));
7390 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
7392 ADD_INSN1(ret, line_node, putobject,
Qfalse);
7393 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2));
7395 ADD_INSN(ret, line_node, pop);
7396 ADD_INSN(ret, line_node, pop);
7397 ADD_LABEL(ret, match_succeeded);
7403iseq_compile_pattern_set_eqq_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int base_index)
7413 const int line = nd_line(node);
7414 const NODE *line_node = node;
7415 LABEL *match_succeeded = NEW_LABEL(line);
7417 ADD_INSN(ret, line_node, dup);
7418 ADD_INSNL(ret, line_node, branchif, match_succeeded);
7420 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7421 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"%p === %p does not return true"));
7422 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7423 ADD_INSN1(ret, line_node, topn,
INT2FIX(5));
7424 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(3));
7425 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
7427 ADD_INSN1(ret, line_node, putobject,
Qfalse);
7428 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
7430 ADD_INSN(ret, line_node, pop);
7431 ADD_INSN(ret, line_node, pop);
7433 ADD_LABEL(ret, match_succeeded);
7434 ADD_INSN1(ret, line_node, setn,
INT2FIX(2));
7435 ADD_INSN(ret, line_node, pop);
7436 ADD_INSN(ret, line_node, pop);
7442compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const orig_node,
int popped)
7444 const NODE *pattern;
7445 const NODE *node = orig_node;
7446 LABEL *endlabel, *elselabel;
7448 DECL_ANCHOR(body_seq);
7449 DECL_ANCHOR(cond_seq);
7451 enum node_type
type;
7452 const NODE *line_node;
7455 bool single_pattern;
7458 INIT_ANCHOR(body_seq);
7459 INIT_ANCHOR(cond_seq);
7461 branches = decl_branch_base(iseq, node,
"case");
7463 node = RNODE_CASE3(node)->nd_body;
7464 EXPECT_NODE(
"NODE_CASE3", node, NODE_IN, COMPILE_NG);
7465 type = nd_type(node);
7466 line = nd_line(node);
7468 single_pattern = !RNODE_IN(node)->nd_next;
7470 endlabel = NEW_LABEL(line);
7471 elselabel = NEW_LABEL(line);
7473 if (single_pattern) {
7475 ADD_INSN(head, line_node, putnil);
7476 ADD_INSN(head, line_node, putnil);
7477 ADD_INSN1(head, line_node, putobject,
Qfalse);
7478 ADD_INSN(head, line_node, putnil);
7480 ADD_INSN(head, line_node, putnil);
7482 CHECK(COMPILE(head,
"case base", RNODE_CASE3(orig_node)->nd_head));
7486 while (
type == NODE_IN) {
7490 ADD_INSN(body_seq, line_node, putnil);
7492 l1 = NEW_LABEL(line);
7493 ADD_LABEL(body_seq, l1);
7494 ADD_INSN1(body_seq, line_node, adjuststack,
INT2FIX(single_pattern ? 6 : 2));
7495 add_trace_branch_coverage(
7498 RNODE_IN(node)->nd_body ? RNODE_IN(node)->nd_body : node,
7502 CHECK(COMPILE_(body_seq,
"in body", RNODE_IN(node)->nd_body, popped));
7503 ADD_INSNL(body_seq, line_node, jump, endlabel);
7505 pattern = RNODE_IN(node)->nd_head;
7507 int pat_line = nd_line(pattern);
7508 LABEL *next_pat = NEW_LABEL(pat_line);
7509 ADD_INSN (cond_seq, pattern, dup);
7511 CHECK(iseq_compile_pattern_each(iseq, cond_seq, pattern, l1, next_pat, single_pattern,
false, 2,
true));
7512 ADD_LABEL(cond_seq, next_pat);
7513 LABEL_UNREMOVABLE(next_pat);
7516 COMPILE_ERROR(ERROR_ARGS
"unexpected node");
7520 node = RNODE_IN(node)->nd_next;
7524 type = nd_type(node);
7525 line = nd_line(node);
7530 ADD_LABEL(cond_seq, elselabel);
7531 ADD_INSN(cond_seq, line_node, pop);
7532 ADD_INSN(cond_seq, line_node, pop);
7533 add_trace_branch_coverage(iseq, cond_seq, node, branch_id,
"else", branches);
7534 CHECK(COMPILE_(cond_seq,
"else", node, popped));
7535 ADD_INSNL(cond_seq, line_node, jump, endlabel);
7536 ADD_INSN(cond_seq, line_node, putnil);
7538 ADD_INSN(cond_seq, line_node, putnil);
7542 debugs(
"== else (implicit)\n");
7543 ADD_LABEL(cond_seq, elselabel);
7544 add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id,
"else", branches);
7545 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7547 if (single_pattern) {
7555 LABEL *key_error, *fin;
7558 key_error = NEW_LABEL(line);
7559 fin = NEW_LABEL(line);
7562 kw_arg->references = 0;
7563 kw_arg->keyword_len = 2;
7564 kw_arg->keywords[0] =
ID2SYM(rb_intern(
"matchee"));
7565 kw_arg->keywords[1] =
ID2SYM(rb_intern(
"key"));
7567 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_P + 2));
7568 ADD_INSNL(cond_seq, orig_node, branchif, key_error);
7570 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7571 ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit(
"%p: %s"));
7572 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(4));
7573 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6));
7574 ADD_SEND(cond_seq, orig_node, id_core_sprintf,
INT2FIX(3));
7575 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(2));
7576 ADD_INSNL(cond_seq, orig_node, jump, fin);
7578 ADD_LABEL(cond_seq, key_error);
7580 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7581 ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit(
"%p: %s"));
7582 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(4));
7583 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6));
7584 ADD_SEND(cond_seq, orig_node, id_core_sprintf,
INT2FIX(3));
7585 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4));
7586 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_KEY + 5));
7587 ADD_SEND_R(cond_seq, orig_node, rb_intern(
"new"),
INT2FIX(1), NULL,
INT2FIX(VM_CALL_KWARG), kw_arg);
7588 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(1));
7590 ADD_LABEL(cond_seq, fin);
7594 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(2));
7595 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(2));
7597 ADD_INSN1(cond_seq, orig_node, adjuststack,
INT2FIX(single_pattern ? 7 : 3));
7599 ADD_INSN(cond_seq, orig_node, putnil);
7601 ADD_INSNL(cond_seq, orig_node, jump, endlabel);
7602 ADD_INSN1(cond_seq, orig_node, dupn,
INT2FIX(single_pattern ? 5 : 1));
7604 ADD_INSN(cond_seq, line_node, putnil);
7608 ADD_SEQ(ret, cond_seq);
7609 ADD_SEQ(ret, body_seq);
7610 ADD_LABEL(ret, endlabel);
7614#undef CASE3_BI_OFFSET_DECONSTRUCTED_CACHE
7615#undef CASE3_BI_OFFSET_ERROR_STRING
7616#undef CASE3_BI_OFFSET_KEY_ERROR_P
7617#undef CASE3_BI_OFFSET_KEY_ERROR_MATCHEE
7618#undef CASE3_BI_OFFSET_KEY_ERROR_KEY
7621compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped,
const enum node_type
type)
7623 const int line = (int)nd_line(node);
7624 const NODE *line_node = node;
7626 LABEL *prev_start_label = ISEQ_COMPILE_DATA(iseq)->start_label;
7627 LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label;
7628 LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label;
7629 int prev_loopval_popped = ISEQ_COMPILE_DATA(iseq)->loopval_popped;
7634 LABEL *next_label = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(line);
7635 LABEL *redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label = NEW_LABEL(line);
7636 LABEL *break_label = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(line);
7637 LABEL *end_label = NEW_LABEL(line);
7638 LABEL *adjust_label = NEW_LABEL(line);
7640 LABEL *next_catch_label = NEW_LABEL(line);
7641 LABEL *tmp_label = NULL;
7643 ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0;
7644 push_ensure_entry(iseq, &enl, NULL, NULL);
7646 if (RNODE_WHILE(node)->nd_state == 1) {
7647 ADD_INSNL(ret, line_node, jump, next_label);
7650 tmp_label = NEW_LABEL(line);
7651 ADD_INSNL(ret, line_node, jump, tmp_label);
7653 ADD_LABEL(ret, adjust_label);
7654 ADD_INSN(ret, line_node, putnil);
7655 ADD_LABEL(ret, next_catch_label);
7656 ADD_INSN(ret, line_node, pop);
7657 ADD_INSNL(ret, line_node, jump, next_label);
7658 if (tmp_label) ADD_LABEL(ret, tmp_label);
7660 ADD_LABEL(ret, redo_label);
7661 branches = decl_branch_base(iseq, node,
type == NODE_WHILE ?
"while" :
"until");
7662 add_trace_branch_coverage(
7665 RNODE_WHILE(node)->nd_body ? RNODE_WHILE(node)->nd_body : node,
7669 CHECK(COMPILE_POPPED(ret,
"while body", RNODE_WHILE(node)->nd_body));
7670 ADD_LABEL(ret, next_label);
7672 if (
type == NODE_WHILE) {
7673 compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
7674 redo_label, end_label);
7678 compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
7679 end_label, redo_label);
7682 ADD_LABEL(ret, end_label);
7683 ADD_ADJUST_RESTORE(ret, adjust_label);
7685 if (UNDEF_P(RNODE_WHILE(node)->nd_state)) {
7687 COMPILE_ERROR(ERROR_ARGS
"unsupported: putundef");
7691 ADD_INSN(ret, line_node, putnil);
7694 ADD_LABEL(ret, break_label);
7697 ADD_INSN(ret, line_node, pop);
7700 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, NULL,
7702 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, NULL,
7704 ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, NULL,
7705 ISEQ_COMPILE_DATA(iseq)->redo_label);
7707 ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label;
7708 ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label;
7709 ISEQ_COMPILE_DATA(iseq)->redo_label = prev_redo_label;
7710 ISEQ_COMPILE_DATA(iseq)->loopval_popped = prev_loopval_popped;
7711 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->prev;
7716compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
7718 const int line = nd_line(node);
7719 const NODE *line_node = node;
7720 const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(iseq)->current_block;
7721 LABEL *retry_label = NEW_LABEL(line);
7722 LABEL *retry_end_l = NEW_LABEL(line);
7723 const rb_iseq_t *child_iseq;
7725 ADD_LABEL(ret, retry_label);
7726 if (nd_type_p(node, NODE_FOR)) {
7727 CHECK(COMPILE(ret,
"iter caller (for)", RNODE_FOR(node)->nd_iter));
7729 ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
7730 NEW_CHILD_ISEQ(RNODE_FOR(node)->nd_body, make_name_for_block(iseq),
7731 ISEQ_TYPE_BLOCK, line);
7732 ADD_SEND_WITH_BLOCK(ret, line_node, idEach,
INT2FIX(0), child_iseq);
7735 ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
7736 NEW_CHILD_ISEQ(RNODE_ITER(node)->nd_body, make_name_for_block(iseq),
7737 ISEQ_TYPE_BLOCK, line);
7738 CHECK(COMPILE(ret,
"iter caller", RNODE_ITER(node)->nd_iter));
7751 LINK_ELEMENT *last_elem = LAST_ELEMENT(ret);
7752 iobj = IS_INSN(last_elem) ? (INSN*) last_elem : (INSN*) get_prev_insn((INSN*) last_elem);
7753 while (INSN_OF(iobj) != BIN(send) && INSN_OF(iobj) != BIN(invokesuper)) {
7754 iobj = (INSN*) get_prev_insn(iobj);
7756 ELEM_INSERT_NEXT(&iobj->link, (LINK_ELEMENT*) retry_end_l);
7760 if (&iobj->link == LAST_ELEMENT(ret)) {
7761 ret->last = (LINK_ELEMENT*) retry_end_l;
7766 ADD_INSN(ret, line_node, pop);
7769 ISEQ_COMPILE_DATA(iseq)->current_block = prevblock;
7771 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l);
7776compile_for_masgn(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
7781 const NODE *line_node = node;
7782 const NODE *var = RNODE_FOR_MASGN(node)->nd_var;
7783 LABEL *not_single = NEW_LABEL(nd_line(var));
7784 LABEL *not_ary = NEW_LABEL(nd_line(var));
7785 CHECK(COMPILE(ret,
"for var", var));
7786 ADD_INSN(ret, line_node, dup);
7787 ADD_CALL(ret, line_node, idLength,
INT2FIX(0));
7788 ADD_INSN1(ret, line_node, putobject,
INT2FIX(1));
7789 ADD_CALL(ret, line_node, idEq,
INT2FIX(1));
7790 ADD_INSNL(ret, line_node, branchunless, not_single);
7791 ADD_INSN(ret, line_node, dup);
7792 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
7793 ADD_CALL(ret, line_node, idAREF,
INT2FIX(1));
7794 ADD_INSN1(ret, line_node, putobject,
rb_cArray);
7795 ADD_INSN(ret, line_node, swap);
7796 ADD_CALL(ret, line_node, rb_intern(
"try_convert"),
INT2FIX(1));
7797 ADD_INSN(ret, line_node, dup);
7798 ADD_INSNL(ret, line_node, branchunless, not_ary);
7799 ADD_INSN(ret, line_node, swap);
7800 ADD_LABEL(ret, not_ary);
7801 ADD_INSN(ret, line_node, pop);
7802 ADD_LABEL(ret, not_single);
7807compile_break(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
7809 const NODE *line_node = node;
7810 unsigned long throw_flag = 0;
7812 if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
7814 LABEL *splabel = NEW_LABEL(0);
7815 ADD_LABEL(ret, splabel);
7816 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
7817 CHECK(COMPILE_(ret,
"break val (while/until)", RNODE_BREAK(node)->nd_stts,
7818 ISEQ_COMPILE_DATA(iseq)->loopval_popped));
7819 add_ensure_iseq(ret, iseq, 0);
7820 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
7821 ADD_ADJUST_RESTORE(ret, splabel);
7824 ADD_INSN(ret, line_node, putnil);
7828 const rb_iseq_t *ip = iseq;
7831 if (!ISEQ_COMPILE_DATA(ip)) {
7836 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
7837 throw_flag = VM_THROW_NO_ESCAPE_FLAG;
7839 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
7842 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
7843 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with break");
7847 ip = ISEQ_BODY(ip)->parent_iseq;
7852 CHECK(COMPILE(ret,
"break val (block)", RNODE_BREAK(node)->nd_stts));
7853 ADD_INSN1(ret, line_node,
throw,
INT2FIX(throw_flag | TAG_BREAK));
7855 ADD_INSN(ret, line_node, pop);
7859 COMPILE_ERROR(ERROR_ARGS
"Invalid break");
7866compile_next(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
7868 const NODE *line_node = node;
7869 unsigned long throw_flag = 0;
7871 if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
7872 LABEL *splabel = NEW_LABEL(0);
7873 debugs(
"next in while loop\n");
7874 ADD_LABEL(ret, splabel);
7875 CHECK(COMPILE(ret,
"next val/valid syntax?", RNODE_NEXT(node)->nd_stts));
7876 add_ensure_iseq(ret, iseq, 0);
7877 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
7878 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
7879 ADD_ADJUST_RESTORE(ret, splabel);
7881 ADD_INSN(ret, line_node, putnil);
7884 else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) {
7885 LABEL *splabel = NEW_LABEL(0);
7886 debugs(
"next in block\n");
7887 ADD_LABEL(ret, splabel);
7888 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
7889 CHECK(COMPILE(ret,
"next val", RNODE_NEXT(node)->nd_stts));
7890 add_ensure_iseq(ret, iseq, 0);
7891 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
7892 ADD_ADJUST_RESTORE(ret, splabel);
7895 ADD_INSN(ret, line_node, putnil);
7899 const rb_iseq_t *ip = iseq;
7902 if (!ISEQ_COMPILE_DATA(ip)) {
7907 throw_flag = VM_THROW_NO_ESCAPE_FLAG;
7908 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
7912 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
7915 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
7916 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with next");
7920 ip = ISEQ_BODY(ip)->parent_iseq;
7923 CHECK(COMPILE(ret,
"next val", RNODE_NEXT(node)->nd_stts));
7924 ADD_INSN1(ret, line_node,
throw,
INT2FIX(throw_flag | TAG_NEXT));
7927 ADD_INSN(ret, line_node, pop);
7931 COMPILE_ERROR(ERROR_ARGS
"Invalid next");
7939compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
7941 const NODE *line_node = node;
7943 if (ISEQ_COMPILE_DATA(iseq)->redo_label && can_add_ensure_iseq(iseq)) {
7944 LABEL *splabel = NEW_LABEL(0);
7945 debugs(
"redo in while");
7946 ADD_LABEL(ret, splabel);
7947 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
7948 add_ensure_iseq(ret, iseq, 0);
7949 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
7950 ADD_ADJUST_RESTORE(ret, splabel);
7952 ADD_INSN(ret, line_node, putnil);
7955 else if (ISEQ_BODY(iseq)->
type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) {
7956 LABEL *splabel = NEW_LABEL(0);
7958 debugs(
"redo in block");
7959 ADD_LABEL(ret, splabel);
7960 add_ensure_iseq(ret, iseq, 0);
7961 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
7962 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
7963 ADD_ADJUST_RESTORE(ret, splabel);
7966 ADD_INSN(ret, line_node, putnil);
7970 const rb_iseq_t *ip = iseq;
7973 if (!ISEQ_COMPILE_DATA(ip)) {
7978 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
7981 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
7984 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
7985 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with redo");
7989 ip = ISEQ_BODY(ip)->parent_iseq;
7992 ADD_INSN(ret, line_node, putnil);
7993 ADD_INSN1(ret, line_node,
throw,
INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO));
7996 ADD_INSN(ret, line_node, pop);
8000 COMPILE_ERROR(ERROR_ARGS
"Invalid redo");
8008compile_retry(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
8010 const NODE *line_node = node;
8012 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE) {
8013 ADD_INSN(ret, line_node, putnil);
8014 ADD_INSN1(ret, line_node,
throw,
INT2FIX(TAG_RETRY));
8017 ADD_INSN(ret, line_node, pop);
8021 COMPILE_ERROR(ERROR_ARGS
"Invalid retry");
8028compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
8030 const int line = nd_line(node);
8031 const NODE *line_node = node;
8032 LABEL *lstart = NEW_LABEL(line);
8033 LABEL *lend = NEW_LABEL(line);
8034 LABEL *lcont = NEW_LABEL(line);
8035 const rb_iseq_t *rescue = NEW_CHILD_ISEQ(RNODE_RESCUE(node)->nd_resq,
8037 ISEQ_BODY(iseq)->location.label),
8038 ISEQ_TYPE_RESCUE, line);
8040 lstart->rescued = LABEL_RESCUE_BEG;
8041 lend->rescued = LABEL_RESCUE_END;
8042 ADD_LABEL(ret, lstart);
8044 bool prev_in_rescue = ISEQ_COMPILE_DATA(iseq)->in_rescue;
8045 ISEQ_COMPILE_DATA(iseq)->in_rescue =
true;
8047 CHECK(COMPILE(ret,
"rescue head", RNODE_RESCUE(node)->nd_head));
8049 ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue;
8051 ADD_LABEL(ret, lend);
8052 if (RNODE_RESCUE(node)->nd_else) {
8053 ADD_INSN(ret, line_node, pop);
8054 CHECK(COMPILE(ret,
"rescue else", RNODE_RESCUE(node)->nd_else));
8056 ADD_INSN(ret, line_node, nop);
8057 ADD_LABEL(ret, lcont);
8060 ADD_INSN(ret, line_node, pop);
8064 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont);
8065 ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, NULL, lstart);
8070compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
8072 const int line = nd_line(node);
8073 const NODE *line_node = node;
8074 const NODE *resq = node;
8076 LABEL *label_miss, *label_hit;
8079 label_miss = NEW_LABEL(line);
8080 label_hit = NEW_LABEL(line);
8082 narg = RNODE_RESBODY(resq)->nd_args;
8084 switch (nd_type(narg)) {
8087 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
8088 CHECK(COMPILE(ret,
"rescue arg", RNODE_LIST(narg)->nd_head));
8089 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
8090 ADD_INSNL(ret, line_node, branchif, label_hit);
8091 narg = RNODE_LIST(narg)->nd_next;
8097 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
8098 CHECK(COMPILE(ret,
"rescue/cond splat", narg));
8099 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY));
8100 ADD_INSNL(ret, line_node, branchif, label_hit);
8103 UNKNOWN_NODE(
"NODE_RESBODY", narg, COMPILE_NG);
8107 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
8109 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
8110 ADD_INSNL(ret, line_node, branchif, label_hit);
8112 ADD_INSNL(ret, line_node, jump, label_miss);
8113 ADD_LABEL(ret, label_hit);
8116 if (nd_type(RNODE_RESBODY(resq)->nd_body) == NODE_BEGIN && RNODE_BEGIN(RNODE_RESBODY(resq)->nd_body)->nd_body == NULL) {
8118 int lineno = nd_line(RNODE_RESBODY(resq)->nd_body);
8119 NODE dummy_line_node = generate_dummy_line_node(lineno, -1);
8120 ADD_INSN(ret, &dummy_line_node, putnil);
8123 CHECK(COMPILE(ret,
"resbody body", RNODE_RESBODY(resq)->nd_body));
8126 if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
8127 ADD_INSN(ret, line_node, nop);
8129 ADD_INSN(ret, line_node, leave);
8130 ADD_LABEL(ret, label_miss);
8131 resq = RNODE_RESBODY(resq)->nd_head;
8137compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
8139 const int line = nd_line(node);
8140 const NODE *line_node = node;
8142 const rb_iseq_t *ensure = NEW_CHILD_ISEQ(RNODE_ENSURE(node)->nd_ensr,
8144 ISEQ_TYPE_ENSURE, line);
8145 LABEL *lstart = NEW_LABEL(line);
8146 LABEL *lend = NEW_LABEL(line);
8147 LABEL *lcont = NEW_LABEL(line);
8155 CHECK(COMPILE_POPPED(ensr,
"ensure ensr", RNODE_ENSURE(node)->nd_ensr));
8157 last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave);
8162 push_ensure_entry(iseq, &enl, &er, RNODE_ENSURE(node)->nd_ensr);
8164 ADD_LABEL(ret, lstart);
8165 CHECK(COMPILE_(ret,
"ensure head", RNODE_ENSURE(node)->nd_head, (popped | last_leave)));
8166 ADD_LABEL(ret, lend);
8168 if (!popped && last_leave) ADD_INSN(ret, line_node, putnil);
8169 ADD_LABEL(ret, lcont);
8170 if (last_leave) ADD_INSN(ret, line_node, pop);
8172 erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange;
8173 if (lstart->link.next != &lend->link) {
8175 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end,
8177 erange = erange->next;
8181 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev;
8186compile_return(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
8188 const NODE *line_node = node;
8191 enum rb_iseq_type
type = ISEQ_BODY(iseq)->type;
8192 const rb_iseq_t *is = iseq;
8193 enum rb_iseq_type t =
type;
8194 const NODE *retval = RNODE_RETURN(node)->nd_stts;
8197 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) {
8198 if (!(is = ISEQ_BODY(is)->parent_iseq))
break;
8199 t = ISEQ_BODY(is)->type;
8203 case ISEQ_TYPE_MAIN:
8205 rb_warn(
"argument of top-level return is ignored");
8209 type = ISEQ_TYPE_METHOD;
8216 if (
type == ISEQ_TYPE_METHOD) {
8217 splabel = NEW_LABEL(0);
8218 ADD_LABEL(ret, splabel);
8219 ADD_ADJUST(ret, line_node, 0);
8222 CHECK(COMPILE(ret,
"return nd_stts (return val)", retval));
8224 if (
type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
8225 add_ensure_iseq(ret, iseq, 1);
8227 ADD_INSN(ret, line_node, leave);
8228 ADD_ADJUST_RESTORE(ret, splabel);
8231 ADD_INSN(ret, line_node, putnil);
8235 ADD_INSN1(ret, line_node,
throw,
INT2FIX(TAG_RETURN));
8237 ADD_INSN(ret, line_node, pop);
8245compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
8247 CHECK(COMPILE_(ret,
"nd_body", node, popped));
8249 if (!popped && !all_string_result_p(node)) {
8250 const NODE *line_node = node;
8251 const unsigned int flag = VM_CALL_FCALL;
8255 ADD_INSN(ret, line_node, dup);
8256 ADD_INSN1(ret, line_node, objtostring, new_callinfo(iseq, idTo_s, 0, flag, NULL, FALSE));
8257 ADD_INSN(ret, line_node, anytostring);
8263compile_lvar(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *line_node,
ID id)
8265 int idx = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
8267 debugs(
"id: %s idx: %d\n", rb_id2name(
id), idx);
8268 ADD_GETLOCAL(ret, line_node, idx, get_lvar_level(iseq));
8272qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *
const recv,
VALUE *branches,
const NODE *node,
const NODE *line_node)
8274 LABEL *else_label = NEW_LABEL(nd_line(line_node));
8277 br = decl_branch_base(iseq, node,
"&.");
8279 ADD_INSN(recv, line_node, dup);
8280 ADD_INSNL(recv, line_node, branchnil, else_label);
8281 add_trace_branch_coverage(iseq, recv, node, 0,
"then", br);
8286qcall_branch_end(rb_iseq_t *iseq, LINK_ANCHOR *
const ret, LABEL *else_label,
VALUE branches,
const NODE *node,
const NODE *line_node)
8289 if (!else_label)
return;
8290 end_label = NEW_LABEL(nd_line(line_node));
8291 ADD_INSNL(ret, line_node, jump, end_label);
8292 ADD_LABEL(ret, else_label);
8293 add_trace_branch_coverage(iseq, ret, node, 1,
"else", branches);
8294 ADD_LABEL(ret, end_label);
8298compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
const NODE *line_node,
int popped)
8303 if (get_nd_recv(node) && nd_type_p(get_nd_recv(node), NODE_STR) &&
8304 (get_node_call_nd_mid(node) == idFreeze || get_node_call_nd_mid(node) == idUMinus) &&
8305 get_nd_args(node) == NULL &&
8306 ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
8307 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
8308 VALUE str = rb_fstring(RNODE_STR(get_nd_recv(node))->nd_lit);
8309 if (get_node_call_nd_mid(node) == idUMinus) {
8310 ADD_INSN2(ret, line_node, opt_str_uminus, str,
8311 new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE));
8314 ADD_INSN2(ret, line_node, opt_str_freeze, str,
8315 new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE));
8319 ADD_INSN(ret, line_node, pop);
8326 if (get_node_call_nd_mid(node) == idAREF && !private_recv_p(node) && get_nd_args(node) &&
8327 nd_type_p(get_nd_args(node), NODE_LIST) && RNODE_LIST(get_nd_args(node))->as.nd_alen == 1 &&
8328 nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_STR) &&
8329 ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
8330 !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
8331 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
8332 VALUE str = rb_fstring(RNODE_STR(RNODE_LIST(get_nd_args(node))->nd_head)->nd_lit);
8333 CHECK(COMPILE(ret,
"recv", get_nd_recv(node)));
8334 ADD_INSN2(ret, line_node, opt_aref_with, str,
8335 new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE));
8338 ADD_INSN(ret, line_node, pop);
8346iseq_has_builtin_function_table(
const rb_iseq_t *iseq)
8348 return ISEQ_COMPILE_DATA(iseq)->builtin_function_table != NULL;
8352iseq_builtin_function_lookup(
const rb_iseq_t *iseq,
const char *name)
8355 const struct rb_builtin_function *table = ISEQ_COMPILE_DATA(iseq)->builtin_function_table;
8356 for (i=0; table[i].index != -1; i++) {
8357 if (strcmp(table[i].name, name) == 0) {
8365iseq_builtin_function_name(
const enum node_type
type,
const NODE *recv,
ID mid)
8367 const char *name = rb_id2name(mid);
8368 static const char prefix[] =
"__builtin_";
8369 const size_t prefix_len =
sizeof(prefix) - 1;
8374 switch (nd_type(recv)) {
8376 if (RNODE_VCALL(recv)->nd_mid == rb_intern(
"__builtin")) {
8381 if (RNODE_CONST(recv)->nd_vid == rb_intern(
"Primitive")) {
8391 if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) {
8392 return &name[prefix_len];
8401delegate_call_p(
const rb_iseq_t *iseq,
unsigned int argc,
const LINK_ANCHOR *args,
unsigned int *pstart_index)
8408 else if (argc <= ISEQ_BODY(iseq)->local_table_size) {
8409 unsigned int start=0;
8414 argc + start <= ISEQ_BODY(iseq)->local_table_size;
8416 const LINK_ELEMENT *elem = FIRST_ELEMENT(args);
8418 for (
unsigned int i=start; i-start<argc; i++) {
8419 if (IS_INSN(elem) &&
8420 INSN_OF(elem) == BIN(getlocal)) {
8421 int local_index =
FIX2INT(OPERAND_AT(elem, 0));
8422 int local_level =
FIX2INT(OPERAND_AT(elem, 1));
8424 if (local_level == 0) {
8425 unsigned int index = ISEQ_BODY(iseq)->local_table_size - (local_index - VM_ENV_DATA_SIZE + 1);
8427 fprintf(stderr,
"lvar:%s (%d), id:%s (%d) local_index:%d, local_size:%d\n",
8428 rb_id2name(ISEQ_BODY(iseq)->local_table[i]), i,
8429 rb_id2name(ISEQ_BODY(iseq)->local_table[index]), index,
8430 local_index, (
int)ISEQ_BODY(iseq)->local_table_size);
8454 *pstart_index = start;
8464compile_builtin_attr(rb_iseq_t *iseq,
const NODE *node)
8468 if (!node)
goto no_arg;
8470 if (!nd_type_p(node, NODE_LIST))
goto bad_arg;
8471 const NODE *next = RNODE_LIST(node)->nd_next;
8473 node = RNODE_LIST(node)->nd_head;
8474 if (!node)
goto no_arg;
8475 if (!nd_type_p(node, NODE_LIT))
goto bad_arg;
8477 symbol = RNODE_LIT(node)->nd_lit;
8478 if (!
SYMBOL_P(symbol))
goto non_symbol_arg;
8481 if (strcmp(RSTRING_PTR(
string),
"leaf") == 0) {
8482 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_LEAF;
8484 else if (strcmp(RSTRING_PTR(
string),
"no_gc") == 0) {
8485 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_NO_GC;
8494 COMPILE_ERROR(ERROR_ARGS
"attr!: no argument");
8497 COMPILE_ERROR(ERROR_ARGS
"non symbol argument to attr!: %s", rb_builtin_class_name(symbol));
8500 COMPILE_ERROR(ERROR_ARGS
"unknown argument to attr!: %s", RSTRING_PTR(
string));
8503 UNKNOWN_NODE(
"attr!", node, COMPILE_NG);
8507compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *node,
const NODE *line_node,
int popped)
8509 if (!node)
goto no_arg;
8510 if (!nd_type_p(node, NODE_LIST))
goto bad_arg;
8511 if (RNODE_LIST(node)->nd_next)
goto too_many_arg;
8512 node = RNODE_LIST(node)->nd_head;
8513 if (!node)
goto no_arg;
8514 if (!nd_type_p(node, NODE_LIT))
goto bad_arg;
8515 VALUE name = RNODE_LIT(node)->nd_lit;
8516 if (!
SYMBOL_P(name))
goto non_symbol_arg;
8518 compile_lvar(iseq, ret, line_node,
SYM2ID(name));
8522 COMPILE_ERROR(ERROR_ARGS
"arg!: no argument");
8525 COMPILE_ERROR(ERROR_ARGS
"arg!: too many argument");
8528 COMPILE_ERROR(ERROR_ARGS
"non symbol argument to arg!: %s",
8529 rb_builtin_class_name(name));
8532 UNKNOWN_NODE(
"arg!", node, COMPILE_NG);
8536mandatory_node(
const rb_iseq_t *iseq,
const NODE *cond_node)
8538 const NODE *node = ISEQ_COMPILE_DATA(iseq)->root_node;
8539 if (nd_type(node) == NODE_IF && RNODE_IF(node)->nd_cond == cond_node) {
8540 return RNODE_IF(node)->nd_body;
8543 rb_bug(
"mandatory_node: can't find mandatory node");
8548compile_builtin_mandatory_only_method(rb_iseq_t *iseq,
const NODE *node,
const NODE *line_node)
8552 .pre_args_num = ISEQ_BODY(iseq)->param.lead_num,
8554 rb_node_args_t args_node;
8555 rb_node_init(RNODE(&args_node), NODE_ARGS);
8556 args_node.nd_ainfo = args;
8559 const int skip_local_size = ISEQ_BODY(iseq)->param.size - ISEQ_BODY(iseq)->param.lead_num;
8560 const int table_size = ISEQ_BODY(iseq)->local_table_size - skip_local_size;
8563 rb_ast_id_table_t *tbl =
ALLOCV(idtmp,
sizeof(rb_ast_id_table_t) + table_size *
sizeof(
ID));
8564 tbl->size = table_size;
8569 for (i=0; i<ISEQ_BODY(iseq)->param.lead_num; i++) {
8570 tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i];
8573 for (; i<table_size; i++) {
8574 tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i + skip_local_size];
8577 rb_node_scope_t scope_node;
8578 rb_node_init(RNODE(&scope_node), NODE_SCOPE);
8579 scope_node.nd_tbl = tbl;
8580 scope_node.nd_body = mandatory_node(iseq, node);
8581 scope_node.nd_args = &args_node;
8583 rb_ast_body_t ast = {
8584 .root = RNODE(&scope_node),
8585 .frozen_string_literal = -1,
8586 .coverage_enabled = -1,
8587 .script_lines = ISEQ_BODY(iseq)->variable.script_lines,
8590 ISEQ_BODY(iseq)->mandatory_only_iseq =
8591 rb_iseq_new_with_opt(&ast, rb_iseq_base_label(iseq),
8592 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
8593 nd_line(line_node), NULL, 0,
8594 ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option);
8601compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
const NODE *line_node,
int popped,
8602 const rb_iseq_t *parent_block, LINK_ANCHOR *args,
const char *builtin_func)
8604 NODE *args_node = get_nd_args(node);
8606 if (parent_block != NULL) {
8607 COMPILE_ERROR(ERROR_ARGS_AT(line_node)
"should not call builtins here.");
8611# define BUILTIN_INLINE_PREFIX "_bi"
8612 char inline_func[
sizeof(BUILTIN_INLINE_PREFIX) +
DECIMAL_SIZE_OF(
int)];
8613 bool cconst =
false;
8618 if (strcmp(
"cstmt!", builtin_func) == 0 ||
8619 strcmp(
"cexpr!", builtin_func) == 0) {
8622 else if (strcmp(
"cconst!", builtin_func) == 0) {
8625 else if (strcmp(
"cinit!", builtin_func) == 0) {
8627 GET_VM()->builtin_inline_index++;
8630 else if (strcmp(
"attr!", builtin_func) == 0) {
8631 return compile_builtin_attr(iseq, args_node);
8633 else if (strcmp(
"arg!", builtin_func) == 0) {
8634 return compile_builtin_arg(iseq, ret, args_node, line_node, popped);
8636 else if (strcmp(
"mandatory_only?", builtin_func) == 0) {
8638 rb_bug(
"mandatory_only? should be in if condition");
8640 else if (!LIST_INSN_SIZE_ZERO(ret)) {
8641 rb_bug(
"mandatory_only? should be put on top");
8644 ADD_INSN1(ret, line_node, putobject,
Qfalse);
8645 return compile_builtin_mandatory_only_method(iseq, node, line_node);
8648 rb_bug(
"can't find builtin function:%s", builtin_func);
8651 COMPILE_ERROR(ERROR_ARGS
"can't find builtin function:%s", builtin_func);
8655 if (GET_VM()->builtin_inline_index == INT_MAX) {
8656 rb_bug(
"builtin inline function index overflow:%s", builtin_func);
8658 int inline_index = GET_VM()->builtin_inline_index++;
8659 snprintf(inline_func,
sizeof(inline_func), BUILTIN_INLINE_PREFIX
"%d", inline_index);
8660 builtin_func = inline_func;
8666 typedef VALUE(*builtin_func0)(
void *,
VALUE);
8667 VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL,
Qnil);
8668 ADD_INSN1(ret, line_node, putobject, const_val);
8674 unsigned int flag = 0;
8676 VALUE argc = setup_args(iseq, args, args_node, &flag, &keywords);
8678 if (
FIX2INT(argc) != bf->argc) {
8679 COMPILE_ERROR(ERROR_ARGS
"argc is not match for builtin function:%s (expect %d but %d)",
8680 builtin_func, bf->argc,
FIX2INT(argc));
8684 unsigned int start_index;
8685 if (delegate_call_p(iseq,
FIX2INT(argc), args, &start_index)) {
8686 ADD_INSN2(ret, line_node, opt_invokebuiltin_delegate, bf,
INT2FIX(start_index));
8690 ADD_INSN1(ret, line_node, invokebuiltin, bf);
8693 if (popped) ADD_INSN(ret, line_node, pop);
8699compile_call(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
const enum node_type
type,
const NODE *
const line_node,
int popped,
bool assume_receiver)
8707 ID mid = get_node_call_nd_mid(node);
8709 unsigned int flag = 0;
8711 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
8712 LABEL *else_label = NULL;
8715 ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
8720 if (nd_type_p(node, NODE_VCALL)) {
8725 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
8727 if (mid == id_bitblt) {
8728 ADD_INSN(ret, line_node, bitblt);
8731 else if (mid == id_answer) {
8732 ADD_INSN(ret, line_node, answer);
8744 if (nd_type_p(node, NODE_FCALL) &&
8745 (mid == goto_id || mid == label_id)) {
8748 st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
8751 if (!labels_table) {
8752 labels_table = st_init_numtable();
8753 ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
8755 if (nd_type_p(node->nd_args->nd_head, NODE_LIT) &&
8756 SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
8758 label_name = node->nd_args->nd_head->nd_lit;
8759 if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
8760 label = NEW_LABEL(nd_line(line_node));
8761 label->position = nd_line(line_node);
8762 st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
8765 label = (LABEL *)data;
8769 COMPILE_ERROR(ERROR_ARGS
"invalid goto/label format");
8773 if (mid == goto_id) {
8774 ADD_INSNL(ret, line_node, jump, label);
8777 ADD_LABEL(ret, label);
8784 const char *builtin_func;
8785 if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
8786 (builtin_func = iseq_builtin_function_name(
type, get_nd_recv(node), mid)) != NULL) {
8787 return compile_builtin_function_call(iseq, ret, node, line_node, popped, parent_block, args, builtin_func);
8791 if (!assume_receiver) {
8792 if (
type == NODE_CALL ||
type == NODE_OPCALL ||
type == NODE_QCALL) {
8795 if (mid == idCall &&
8796 nd_type_p(get_nd_recv(node), NODE_LVAR) &&
8797 iseq_block_param_id_p(iseq, RNODE_LVAR(get_nd_recv(node))->nd_vid, &idx, &level)) {
8798 ADD_INSN2(recv, get_nd_recv(node), getblockparamproxy,
INT2FIX(idx + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
8800 else if (private_recv_p(node)) {
8801 ADD_INSN(recv, node, putself);
8802 flag |= VM_CALL_FCALL;
8805 CHECK(COMPILE(recv,
"recv", get_nd_recv(node)));
8808 if (
type == NODE_QCALL) {
8809 else_label = qcall_branch_start(iseq, recv, &branches, node, line_node);
8812 else if (
type == NODE_FCALL ||
type == NODE_VCALL) {
8813 ADD_CALL_RECEIVER(recv, line_node);
8818 if (
type != NODE_VCALL) {
8819 argc = setup_args(iseq, args, get_nd_args(node), &flag, &keywords);
8820 CHECK(!
NIL_P(argc));
8829 debugp_param(
"call args argc", argc);
8830 debugp_param(
"call method",
ID2SYM(mid));
8832 switch ((
int)
type) {
8834 flag |= VM_CALL_VCALL;
8837 flag |= VM_CALL_FCALL;
8840 if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) {
8841 ADD_INSN(ret, line_node, splatkw);
8843 ADD_SEND_R(ret, line_node, mid, argc, parent_block,
INT2FIX(flag), keywords);
8845 qcall_branch_end(iseq, ret, else_label, branches, node, line_node);
8847 ADD_INSN(ret, line_node, pop);
8853compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
8855 const int line = nd_line(node);
8857 unsigned int flag = 0;
8859 ID id = RNODE_OP_ASGN1(node)->nd_mid;
8861 int keyword_len = 0;
8888 ADD_INSN(ret, node, putnil);
8890 asgnflag = COMPILE_RECV(ret,
"NODE_OP_ASGN1 recv", node, RNODE_OP_ASGN1(node)->nd_recv);
8891 CHECK(asgnflag != -1);
8892 switch (nd_type(RNODE_OP_ASGN1(node)->nd_index)) {
8896 case NODE_BLOCK_PASS:
8900 argc = setup_args(iseq, ret, RNODE_OP_ASGN1(node)->nd_index, &flag, &keywords);
8901 if (flag & VM_CALL_KW_SPLAT) {
8903 ADD_INSN(ret, node, splatkw);
8907 ADD_INSN(ret, node, dup);
8908 ADD_INSN(ret, node, splatkw);
8909 ADD_INSN(ret, node, pop);
8912 CHECK(!
NIL_P(argc));
8914 int dup_argn =
FIX2INT(argc) + 1 + boff;
8916 keyword_len = keywords->keyword_len;
8917 dup_argn += keyword_len;
8919 ADD_INSN1(ret, node, dupn,
INT2FIX(dup_argn));
8921 ADD_SEND_R(ret, node, idAREF, argc, NULL,
INT2FIX(flag & ~VM_CALL_KW_SPLAT_MUT), keywords);
8923 if (
id == idOROP ||
id == idANDOP) {
8932 LABEL *label = NEW_LABEL(line);
8933 LABEL *lfin = NEW_LABEL(line);
8935 ADD_INSN(ret, node, dup);
8937 ADD_INSNL(ret, node, branchif, label);
8940 ADD_INSNL(ret, node, branchunless, label);
8942 ADD_INSN(ret, node, pop);
8944 CHECK(COMPILE(ret,
"NODE_OP_ASGN1 nd_rvalue: ", RNODE_OP_ASGN1(node)->nd_rvalue));
8946 ADD_INSN1(ret, node, setn,
INT2FIX(dup_argn+1));
8948 if (flag & VM_CALL_ARGS_SPLAT) {
8949 if (flag & VM_CALL_KW_SPLAT) {
8950 ADD_INSN1(ret, node, topn,
INT2FIX(2 + boff));
8951 ADD_INSN(ret, node, swap);
8952 ADD_INSN1(ret, node, newarray,
INT2FIX(1));
8953 ADD_INSN(ret, node, concatarray);
8954 ADD_INSN1(ret, node, setn,
INT2FIX(2 + boff));
8955 ADD_INSN(ret, node, pop);
8958 ADD_INSN1(ret, node, newarray,
INT2FIX(1));
8960 ADD_INSN1(ret, node, dupn,
INT2FIX(3));
8961 ADD_INSN(ret, node, swap);
8962 ADD_INSN(ret, node, pop);
8964 ADD_INSN(ret, node, concatarray);
8966 ADD_INSN1(ret, node, setn,
INT2FIX(3));
8967 ADD_INSN(ret, node, pop);
8968 ADD_INSN(ret, node, pop);
8971 ADD_SEND_R(ret, node, idASET, argc, NULL,
INT2FIX(flag), keywords);
8973 else if (flag & VM_CALL_KW_SPLAT) {
8975 ADD_INSN1(ret, node, topn,
INT2FIX(2));
8976 ADD_INSN(ret, node, swap);
8977 ADD_INSN1(ret, node, setn,
INT2FIX(3));
8978 ADD_INSN(ret, node, pop);
8980 ADD_INSN(ret, node, swap);
8981 ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL,
INT2FIX(flag), keywords);
8983 else if (keyword_len) {
8984 ADD_INSN1(ret, node, opt_reverse,
INT2FIX(keyword_len+boff+1));
8985 ADD_INSN1(ret, node, opt_reverse,
INT2FIX(keyword_len+boff+0));
8986 ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL,
INT2FIX(flag), keywords);
8990 ADD_INSN(ret, node, swap);
8991 ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL,
INT2FIX(flag), keywords);
8993 ADD_INSN(ret, node, pop);
8994 ADD_INSNL(ret, node, jump, lfin);
8995 ADD_LABEL(ret, label);
8997 ADD_INSN1(ret, node, setn,
INT2FIX(dup_argn+1));
8999 ADD_INSN1(ret, node, adjuststack,
INT2FIX(dup_argn+1));
9000 ADD_LABEL(ret, lfin);
9003 CHECK(COMPILE(ret,
"NODE_OP_ASGN1 nd_rvalue: ", RNODE_OP_ASGN1(node)->nd_rvalue));
9004 ADD_SEND(ret, node,
id,
INT2FIX(1));
9006 ADD_INSN1(ret, node, setn,
INT2FIX(dup_argn+1));
9008 if (flag & VM_CALL_ARGS_SPLAT) {
9009 if (flag & VM_CALL_KW_SPLAT) {
9010 ADD_INSN1(ret, node, topn,
INT2FIX(2 + boff));
9011 ADD_INSN(ret, node, swap);
9012 ADD_INSN1(ret, node, newarray,
INT2FIX(1));
9013 ADD_INSN(ret, node, concatarray);
9014 ADD_INSN1(ret, node, setn,
INT2FIX(2 + boff));
9015 ADD_INSN(ret, node, pop);
9018 ADD_INSN1(ret, node, newarray,
INT2FIX(1));
9020 ADD_INSN1(ret, node, dupn,
INT2FIX(3));
9021 ADD_INSN(ret, node, swap);
9022 ADD_INSN(ret, node, pop);
9024 ADD_INSN(ret, node, concatarray);
9026 ADD_INSN1(ret, node, setn,
INT2FIX(3));
9027 ADD_INSN(ret, node, pop);
9028 ADD_INSN(ret, node, pop);
9031 ADD_SEND_R(ret, node, idASET, argc, NULL,
INT2FIX(flag), keywords);
9033 else if (flag & VM_CALL_KW_SPLAT) {
9035 ADD_INSN1(ret, node, topn,
INT2FIX(2));
9036 ADD_INSN(ret, node, swap);
9037 ADD_INSN1(ret, node, setn,
INT2FIX(3));
9038 ADD_INSN(ret, node, pop);
9040 ADD_INSN(ret, node, swap);
9041 ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL,
INT2FIX(flag), keywords);
9043 else if (keyword_len) {
9044 ADD_INSN(ret, node, dup);
9045 ADD_INSN1(ret, node, opt_reverse,
INT2FIX(keyword_len+boff+2));
9046 ADD_INSN1(ret, node, opt_reverse,
INT2FIX(keyword_len+boff+1));
9047 ADD_INSN(ret, node, pop);
9048 ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL,
INT2FIX(flag), keywords);
9052 ADD_INSN(ret, node, swap);
9053 ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL,
INT2FIX(flag), keywords);
9055 ADD_INSN(ret, node, pop);
9061compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9063 const int line = nd_line(node);
9064 ID atype = RNODE_OP_ASGN2(node)->nd_mid;
9065 ID vid = RNODE_OP_ASGN2(node)->nd_vid, aid = rb_id_attrset(vid);
9067 LABEL *lfin = NEW_LABEL(line);
9068 LABEL *lcfin = NEW_LABEL(line);
9123 asgnflag = COMPILE_RECV(ret,
"NODE_OP_ASGN2#recv", node, RNODE_OP_ASGN2(node)->nd_recv);
9124 CHECK(asgnflag != -1);
9125 if (RNODE_OP_ASGN2(node)->nd_aid) {
9126 lskip = NEW_LABEL(line);
9127 ADD_INSN(ret, node, dup);
9128 ADD_INSNL(ret, node, branchnil, lskip);
9130 ADD_INSN(ret, node, dup);
9131 ADD_SEND_WITH_FLAG(ret, node, vid,
INT2FIX(0),
INT2FIX(asgnflag));
9133 if (atype == idOROP || atype == idANDOP) {
9135 ADD_INSN(ret, node, dup);
9137 if (atype == idOROP) {
9138 ADD_INSNL(ret, node, branchif, lcfin);
9141 ADD_INSNL(ret, node, branchunless, lcfin);
9144 ADD_INSN(ret, node, pop);
9146 CHECK(COMPILE(ret,
"NODE_OP_ASGN2 val", RNODE_OP_ASGN2(node)->nd_value));
9148 ADD_INSN(ret, node, swap);
9149 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9151 ADD_SEND_WITH_FLAG(ret, node, aid,
INT2FIX(1),
INT2FIX(asgnflag));
9152 ADD_INSNL(ret, node, jump, lfin);
9154 ADD_LABEL(ret, lcfin);
9156 ADD_INSN(ret, node, swap);
9159 ADD_LABEL(ret, lfin);
9162 CHECK(COMPILE(ret,
"NODE_OP_ASGN2 val", RNODE_OP_ASGN2(node)->nd_value));
9163 ADD_SEND(ret, node, atype,
INT2FIX(1));
9165 ADD_INSN(ret, node, swap);
9166 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9168 ADD_SEND_WITH_FLAG(ret, node, aid,
INT2FIX(1),
INT2FIX(asgnflag));
9170 if (lskip && popped) {
9171 ADD_LABEL(ret, lskip);
9173 ADD_INSN(ret, node, pop);
9174 if (lskip && !popped) {
9175 ADD_LABEL(ret, lskip);
9181compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9183 const int line = nd_line(node);
9188 switch (nd_type(RNODE_OP_CDECL(node)->nd_head)) {
9190 ADD_INSN1(ret, node, putobject, rb_cObject);
9193 CHECK(COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", RNODE_COLON2(RNODE_OP_CDECL(node)->nd_head)->nd_head));
9196 COMPILE_ERROR(ERROR_ARGS
"%s: invalid node in NODE_OP_CDECL",
9197 ruby_node_name(nd_type(RNODE_OP_CDECL(node)->nd_head)));
9200 mid = get_node_colon_nd_mid(RNODE_OP_CDECL(node)->nd_head);
9202 if (RNODE_OP_CDECL(node)->nd_aid == idOROP) {
9203 lassign = NEW_LABEL(line);
9204 ADD_INSN(ret, node, dup);
9205 ADD_INSN3(ret, node, defined,
INT2FIX(DEFINED_CONST_FROM),
9207 ADD_INSNL(ret, node, branchunless, lassign);
9209 ADD_INSN(ret, node, dup);
9210 ADD_INSN1(ret, node, putobject,
Qtrue);
9211 ADD_INSN1(ret, node, getconstant,
ID2SYM(mid));
9213 if (RNODE_OP_CDECL(node)->nd_aid == idOROP || RNODE_OP_CDECL(node)->nd_aid == idANDOP) {
9214 lfin = NEW_LABEL(line);
9215 if (!popped) ADD_INSN(ret, node, dup);
9216 if (RNODE_OP_CDECL(node)->nd_aid == idOROP)
9217 ADD_INSNL(ret, node, branchif, lfin);
9219 ADD_INSNL(ret, node, branchunless, lfin);
9221 if (!popped) ADD_INSN(ret, node, pop);
9222 if (lassign) ADD_LABEL(ret, lassign);
9223 CHECK(COMPILE(ret,
"NODE_OP_CDECL#nd_value", RNODE_OP_CDECL(node)->nd_value));
9226 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9228 ADD_INSN1(ret, node, dupn,
INT2FIX(2));
9229 ADD_INSN(ret, node, swap);
9231 ADD_INSN1(ret, node, setconstant,
ID2SYM(mid));
9232 ADD_LABEL(ret, lfin);
9233 if (!popped) ADD_INSN(ret, node, swap);
9234 ADD_INSN(ret, node, pop);
9237 CHECK(COMPILE(ret,
"NODE_OP_CDECL#nd_value", RNODE_OP_CDECL(node)->nd_value));
9239 ADD_CALL(ret, node, RNODE_OP_CDECL(node)->nd_aid,
INT2FIX(1));
9241 ADD_INSN(ret, node, swap);
9243 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9244 ADD_INSN(ret, node, swap);
9246 ADD_INSN1(ret, node, setconstant,
ID2SYM(mid));
9252compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped,
const enum node_type
type)
9254 const int line = nd_line(node);
9255 LABEL *lfin = NEW_LABEL(line);
9258 if (
type == NODE_OP_ASGN_OR && !nd_type_p(RNODE_OP_ASGN_OR(node)->nd_head, NODE_IVAR)) {
9262 defined_expr(iseq, ret, RNODE_OP_ASGN_OR(node)->nd_head, lfinish,
Qfalse);
9263 lassign = lfinish[1];
9265 lassign = NEW_LABEL(line);
9267 ADD_INSNL(ret, node, branchunless, lassign);
9270 lassign = NEW_LABEL(line);
9273 CHECK(COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", RNODE_OP_ASGN_OR(node)->nd_head));
9276 ADD_INSN(ret, node, dup);
9279 if (
type == NODE_OP_ASGN_AND) {
9280 ADD_INSNL(ret, node, branchunless, lfin);
9283 ADD_INSNL(ret, node, branchif, lfin);
9287 ADD_INSN(ret, node, pop);
9290 ADD_LABEL(ret, lassign);
9291 CHECK(COMPILE_(ret,
"NODE_OP_ASGN_AND/OR#nd_value", RNODE_OP_ASGN_OR(node)->nd_value, popped));
9292 ADD_LABEL(ret, lfin);
9297compile_super(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped,
const enum node_type
type)
9302 unsigned int flag = 0;
9304 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
9307 ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
9308 if (
type == NODE_SUPER) {
9309 VALUE vargc = setup_args(iseq, args, RNODE_SUPER(node)->nd_args, &flag, &keywords);
9310 CHECK(!
NIL_P(vargc));
9312 if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) {
9313 ADD_INSN(args, node, splatkw);
9319 const rb_iseq_t *liseq = body->local_iseq;
9321 const struct rb_iseq_param_keyword *
const local_kwd = local_body->
param.keyword;
9322 int lvar_level = get_lvar_level(iseq);
9324 argc = local_body->
param.lead_num;
9327 for (i = 0; i < local_body->
param.lead_num; i++) {
9328 int idx = local_body->local_table_size - i;
9329 ADD_GETLOCAL(args, node, idx, lvar_level);
9332 if (local_body->
param.flags.has_opt) {
9335 for (j = 0; j < local_body->
param.opt_num; j++) {
9336 int idx = local_body->local_table_size - (i + j);
9337 ADD_GETLOCAL(args, node, idx, lvar_level);
9342 if (local_body->
param.flags.has_rest) {
9344 int idx = local_body->local_table_size - local_body->
param.rest_start;
9345 ADD_GETLOCAL(args, node, idx, lvar_level);
9346 ADD_INSN1(args, node, splatarray,
Qfalse);
9348 argc = local_body->
param.rest_start + 1;
9349 flag |= VM_CALL_ARGS_SPLAT;
9351 if (local_body->
param.flags.has_post) {
9353 int post_len = local_body->
param.post_num;
9354 int post_start = local_body->
param.post_start;
9356 if (local_body->
param.flags.has_rest) {
9358 for (j=0; j<post_len; j++) {
9359 int idx = local_body->local_table_size - (post_start + j);
9360 ADD_GETLOCAL(args, node, idx, lvar_level);
9362 ADD_INSN1(args, node, newarray,
INT2FIX(j));
9363 ADD_INSN (args, node, concatarray);
9368 for (j=0; j<post_len; j++) {
9369 int idx = local_body->local_table_size - (post_start + j);
9370 ADD_GETLOCAL(args, node, idx, lvar_level);
9372 argc = post_len + post_start;
9376 if (local_body->
param.flags.has_kw) {
9377 int local_size = local_body->local_table_size;
9380 ADD_INSN1(args, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
9382 if (local_body->
param.flags.has_kwrest) {
9383 int idx = local_body->local_table_size - local_kwd->rest_start;
9384 ADD_GETLOCAL(args, node, idx, lvar_level);
9385 assert(local_kwd->num > 0);
9386 ADD_SEND (args, node, rb_intern(
"dup"),
INT2FIX(0));
9389 ADD_INSN1(args, node, newhash,
INT2FIX(0));
9391 for (i = 0; i < local_kwd->num; ++i) {
9392 ID id = local_kwd->table[i];
9393 int idx = local_size - get_local_var_idx(liseq,
id);
9394 ADD_INSN1(args, node, putobject,
ID2SYM(
id));
9395 ADD_GETLOCAL(args, node, idx, lvar_level);
9397 ADD_SEND(args, node, id_core_hash_merge_ptr,
INT2FIX(i * 2 + 1));
9398 flag |= VM_CALL_KW_SPLAT| VM_CALL_KW_SPLAT_MUT;
9400 else if (local_body->
param.flags.has_kwrest) {
9401 int idx = local_body->local_table_size - local_kwd->rest_start;
9402 ADD_GETLOCAL(args, node, idx, lvar_level);
9404 flag |= VM_CALL_KW_SPLAT;
9408 flag |= VM_CALL_SUPER | VM_CALL_FCALL;
9409 if (
type == NODE_ZSUPER) flag |= VM_CALL_ZSUPER;
9410 ADD_INSN(ret, node, putself);
9412 ADD_INSN2(ret, node, invokesuper,
9413 new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL),
9417 ADD_INSN(ret, node, pop);
9423compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9427 unsigned int flag = 0;
9432 switch (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->
type) {
9434 case ISEQ_TYPE_MAIN:
9435 case ISEQ_TYPE_CLASS:
9436 COMPILE_ERROR(ERROR_ARGS
"Invalid yield");
9441 if (RNODE_YIELD(node)->nd_head) {
9442 argc = setup_args(iseq, args, RNODE_YIELD(node)->nd_head, &flag, &keywords);
9443 CHECK(!
NIL_P(argc));
9450 ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0,
FIX2INT(argc), flag, keywords, FALSE));
9453 ADD_INSN(ret, node, pop);
9457 const rb_iseq_t *tmp_iseq = iseq;
9458 for (; tmp_iseq != ISEQ_BODY(iseq)->local_iseq; level++ ) {
9459 tmp_iseq = ISEQ_BODY(tmp_iseq)->parent_iseq;
9461 if (level > 0) access_outer_variables(iseq, level, rb_intern(
"yield"),
true);
9467compile_match(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped,
const enum node_type
type)
9474 switch ((
int)
type) {
9476 ADD_INSN1(recv, node, putobject, RNODE_MATCH(node)->nd_lit);
9477 ADD_INSN2(val, node, getspecial,
INT2FIX(0),
9481 CHECK(COMPILE(recv,
"receiver", RNODE_MATCH2(node)->nd_recv));
9482 CHECK(COMPILE(val,
"value", RNODE_MATCH2(node)->nd_value));
9485 CHECK(COMPILE(recv,
"receiver", RNODE_MATCH3(node)->nd_value));
9486 CHECK(COMPILE(val,
"value", RNODE_MATCH3(node)->nd_recv));
9492 ADD_SEND(ret, node, idEqTilde,
INT2FIX(1));
9494 if (nd_type_p(node, NODE_MATCH2) && RNODE_MATCH2(node)->nd_args) {
9495 compile_named_capture_assign(iseq, ret, RNODE_MATCH2(node)->nd_args);
9499 ADD_INSN(ret, node, pop);
9505compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9510 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache &&
9511 (segments = collect_const_segments(iseq, node))) {
9512 ISEQ_BODY(iseq)->ic_size++;
9513 ADD_INSN1(ret, node, opt_getconstant_path, segments);
9523 CHECK(compile_const_prefix(iseq, node, pref, body));
9524 if (LIST_INSN_SIZE_ZERO(pref)) {
9525 ADD_INSN(ret, node, putnil);
9536 ADD_CALL_RECEIVER(ret, node);
9537 CHECK(COMPILE(ret,
"colon2#nd_head", RNODE_COLON2(node)->nd_head));
9538 ADD_CALL(ret, node, RNODE_COLON2(node)->nd_mid,
INT2FIX(1));
9541 ADD_INSN(ret, node, pop);
9547compile_colon3(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9549 debugi(
"colon3#nd_mid", RNODE_COLON3(node)->nd_mid);
9552 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
9553 ISEQ_BODY(iseq)->ic_size++;
9554 VALUE segments = rb_ary_new_from_args(2,
ID2SYM(idNULL),
ID2SYM(RNODE_COLON3(node)->nd_mid));
9555 ADD_INSN1(ret, node, opt_getconstant_path, segments);
9559 ADD_INSN1(ret, node, putobject, rb_cObject);
9560 ADD_INSN1(ret, node, putobject,
Qtrue);
9561 ADD_INSN1(ret, node, getconstant,
ID2SYM(RNODE_COLON3(node)->nd_mid));
9565 ADD_INSN(ret, node, pop);
9571compile_dots(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped,
const int excl)
9574 const NODE *b = RNODE_DOT2(node)->nd_beg;
9575 const NODE *e = RNODE_DOT2(node)->nd_end;
9577 if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
9579 VALUE bv = nd_type_p(b, NODE_LIT) ? RNODE_LIT(b)->nd_lit :
Qnil;
9580 VALUE ev = nd_type_p(e, NODE_LIT) ? RNODE_LIT(e)->nd_lit :
Qnil;
9582 ADD_INSN1(ret, node, putobject, val);
9587 CHECK(COMPILE_(ret,
"min", b, popped));
9588 CHECK(COMPILE_(ret,
"max", e, popped));
9590 ADD_INSN1(ret, node, newrange, flag);
9597compile_errinfo(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9600 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE) {
9601 ADD_GETLOCAL(ret, node, LVAR_ERRINFO, 0);
9604 const rb_iseq_t *ip = iseq;
9607 if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_RESCUE) {
9610 ip = ISEQ_BODY(ip)->parent_iseq;
9614 ADD_GETLOCAL(ret, node, LVAR_ERRINFO, level);
9617 ADD_INSN(ret, node, putnil);
9625compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9628 LABEL *end_label = NEW_LABEL(nd_line(node));
9629 const NODE *default_value = get_nd_value(RNODE_KW_ARG(node)->nd_body);
9631 if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) {
9633 COMPILE_ERROR(ERROR_ARGS
"unreachable");
9636 else if (nd_type_p(default_value, NODE_LIT) ||
9637 nd_type_p(default_value, NODE_NIL) ||
9638 nd_type_p(default_value, NODE_TRUE) ||
9639 nd_type_p(default_value, NODE_FALSE)) {
9640 COMPILE_ERROR(ERROR_ARGS
"unreachable");
9648 int kw_bits_idx = body->local_table_size - body->
param.keyword->bits_start;
9649 int keyword_idx = body->
param.keyword->num;
9651 ADD_INSN2(ret, node, checkkeyword,
INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1),
INT2FIX(keyword_idx));
9652 ADD_INSNL(ret, node, branchif, end_label);
9653 CHECK(COMPILE_POPPED(ret,
"keyword default argument", RNODE_KW_ARG(node)->nd_body));
9654 ADD_LABEL(ret, end_label);
9660compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9664 unsigned int flag = 0;
9665 ID mid = RNODE_ATTRASGN(node)->nd_mid;
9667 LABEL *else_label = NULL;
9673 if (!ISEQ_COMPILE_DATA(iseq)->in_masgn &&
9674 mid == idASET && !private_recv_p(node) && RNODE_ATTRASGN(node)->nd_args &&
9675 nd_type_p(RNODE_ATTRASGN(node)->nd_args, NODE_LIST) && RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->as.nd_alen == 2 &&
9676 nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_STR) &&
9677 ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
9678 !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
9679 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
9681 VALUE str = rb_fstring(RNODE_STR(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head)->nd_lit);
9682 CHECK(COMPILE(ret,
"recv", RNODE_ATTRASGN(node)->nd_recv));
9683 CHECK(COMPILE(ret,
"value", RNODE_LIST(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_next)->nd_head));
9685 ADD_INSN(ret, node, swap);
9686 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9688 ADD_INSN2(ret, node, opt_aset_with, str,
9689 new_callinfo(iseq, idASET, 2, 0, NULL, FALSE));
9691 ADD_INSN(ret, node, pop);
9697 argc = setup_args(iseq, args, RNODE_ATTRASGN(node)->nd_args, &flag, NULL);
9698 CHECK(!
NIL_P(argc));
9700 int asgnflag = COMPILE_RECV(recv,
"recv", node, RNODE_ATTRASGN(node)->nd_recv);
9701 CHECK(asgnflag != -1);
9702 flag |= (
unsigned int)asgnflag;
9704 debugp_param(
"argc", argc);
9705 debugp_param(
"nd_mid",
ID2SYM(mid));
9709 mid = rb_id_attrset(mid);
9710 else_label = qcall_branch_start(iseq, recv, &branches, node, node);
9713 ADD_INSN(ret, node, putnil);
9717 if (flag & VM_CALL_ARGS_BLOCKARG) {
9718 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9719 if (flag & VM_CALL_ARGS_SPLAT) {
9720 ADD_INSN1(ret, node, putobject,
INT2FIX(-1));
9721 ADD_SEND_WITH_FLAG(ret, node, idAREF,
INT2FIX(1),
INT2FIX(asgnflag));
9723 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 3));
9724 ADD_INSN (ret, node, pop);
9726 else if (flag & VM_CALL_ARGS_SPLAT) {
9727 ADD_INSN(ret, node, dup);
9728 ADD_INSN1(ret, node, putobject,
INT2FIX(-1));
9729 ADD_SEND_WITH_FLAG(ret, node, idAREF,
INT2FIX(1),
INT2FIX(asgnflag));
9730 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2));
9731 ADD_INSN (ret, node, pop);
9734 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 1));
9741 ADD_SEND_WITH_FLAG(ret, node, mid, argc,
INT2FIX(flag));
9742 qcall_branch_end(iseq, ret, else_label, branches, node, node);
9743 ADD_INSN(ret, node, pop);
9747static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped);
9756iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret,
const NODE *node,
int popped)
9760 int lineno = ISEQ_COMPILE_DATA(iseq)->last_line;
9761 if (lineno == 0) lineno =
FIX2INT(rb_iseq_first_lineno(iseq));
9762 debugs(
"node: NODE_NIL(implicit)\n");
9763 NODE dummy_line_node = generate_dummy_line_node(lineno, -1);
9764 ADD_INSN(ret, &dummy_line_node, putnil);
9768 return iseq_compile_each0(iseq, ret, node, popped);
9772iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *
const ret,
const NODE *
const node,
int popped)
9774 const int line = (int)nd_line(node);
9775 const enum node_type
type = nd_type(node);
9778 if (ISEQ_COMPILE_DATA(iseq)->last_line == line) {
9782 if (nd_fl_newline(node)) {
9784 ISEQ_COMPILE_DATA(iseq)->last_line = line;
9785 if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
9786 event |= RUBY_EVENT_COVERAGE_LINE;
9788 ADD_TRACE(ret, event);
9792 debug_node_start(node);
9794#define BEFORE_RETURN debug_node_end()
9798 CHECK(compile_block(iseq, ret, node, popped));
9802 CHECK(compile_if(iseq, ret, node, popped,
type));
9805 CHECK(compile_case(iseq, ret, node, popped));
9808 CHECK(compile_case2(iseq, ret, node, popped));
9811 CHECK(compile_case3(iseq, ret, node, popped));
9815 CHECK(compile_loop(iseq, ret, node, popped,
type));
9819 CHECK(compile_iter(iseq, ret, node, popped));
9821 case NODE_FOR_MASGN:
9822 CHECK(compile_for_masgn(iseq, ret, node, popped));
9825 CHECK(compile_break(iseq, ret, node, popped));
9828 CHECK(compile_next(iseq, ret, node, popped));
9831 CHECK(compile_redo(iseq, ret, node, popped));
9834 CHECK(compile_retry(iseq, ret, node, popped));
9837 CHECK(COMPILE_(ret,
"NODE_BEGIN", RNODE_BEGIN(node)->nd_body, popped));
9841 CHECK(compile_rescue(iseq, ret, node, popped));
9844 CHECK(compile_resbody(iseq, ret, node, popped));
9847 CHECK(compile_ensure(iseq, ret, node, popped));
9852 LABEL *end_label = NEW_LABEL(line);
9853 CHECK(COMPILE(ret,
"nd_1st", RNODE_OR(node)->nd_1st));
9855 ADD_INSN(ret, node, dup);
9857 if (
type == NODE_AND) {
9858 ADD_INSNL(ret, node, branchunless, end_label);
9861 ADD_INSNL(ret, node, branchif, end_label);
9864 ADD_INSN(ret, node, pop);
9866 CHECK(COMPILE_(ret,
"nd_2nd", RNODE_OR(node)->nd_2nd, popped));
9867 ADD_LABEL(ret, end_label);
9872 bool prev_in_masgn = ISEQ_COMPILE_DATA(iseq)->in_masgn;
9873 ISEQ_COMPILE_DATA(iseq)->in_masgn =
true;
9874 compile_massign(iseq, ret, node, popped);
9875 ISEQ_COMPILE_DATA(iseq)->in_masgn = prev_in_masgn;
9880 ID id = RNODE_LASGN(node)->nd_vid;
9881 int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
9883 debugs(
"lvar: %s idx: %d\n", rb_id2name(
id), idx);
9884 CHECK(COMPILE(ret,
"rvalue", RNODE_LASGN(node)->nd_value));
9887 ADD_INSN(ret, node, dup);
9889 ADD_SETLOCAL(ret, node, idx, get_lvar_level(iseq));
9894 ID id = RNODE_DASGN(node)->nd_vid;
9895 CHECK(COMPILE(ret,
"dvalue", RNODE_DASGN(node)->nd_value));
9896 debugi(
"dassn id", rb_id2str(
id) ?
id :
'*');
9899 ADD_INSN(ret, node, dup);
9902 idx = get_dyna_var_idx(iseq,
id, &lv, &ls);
9905 COMPILE_ERROR(ERROR_ARGS
"NODE_DASGN: unknown id (%"PRIsVALUE
")",
9909 ADD_SETLOCAL(ret, node, ls - idx, lv);
9913 CHECK(COMPILE(ret,
"lvalue", RNODE_GASGN(node)->nd_value));
9916 ADD_INSN(ret, node, dup);
9918 ADD_INSN1(ret, node, setglobal,
ID2SYM(RNODE_GASGN(node)->nd_vid));
9922 CHECK(COMPILE(ret,
"lvalue", RNODE_IASGN(node)->nd_value));
9924 ADD_INSN(ret, node, dup);
9926 ADD_INSN2(ret, node, setinstancevariable,
9927 ID2SYM(RNODE_IASGN(node)->nd_vid),
9928 get_ivar_ic_value(iseq,RNODE_IASGN(node)->nd_vid));
9932 if (RNODE_CDECL(node)->nd_vid) {
9933 CHECK(COMPILE(ret,
"lvalue", RNODE_CDECL(node)->nd_value));
9936 ADD_INSN(ret, node, dup);
9939 ADD_INSN1(ret, node, putspecialobject,
9940 INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
9941 ADD_INSN1(ret, node, setconstant,
ID2SYM(RNODE_CDECL(node)->nd_vid));
9944 compile_cpath(ret, iseq, RNODE_CDECL(node)->nd_else);
9945 CHECK(COMPILE(ret,
"lvalue", RNODE_CDECL(node)->nd_value));
9946 ADD_INSN(ret, node, swap);
9949 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9950 ADD_INSN(ret, node, swap);
9953 ADD_INSN1(ret, node, setconstant,
ID2SYM(get_node_colon_nd_mid(RNODE_CDECL(node)->nd_else)));
9958 CHECK(COMPILE(ret,
"cvasgn val", RNODE_CVASGN(node)->nd_value));
9960 ADD_INSN(ret, node, dup);
9962 ADD_INSN2(ret, node, setclassvariable,
9963 ID2SYM(RNODE_CVASGN(node)->nd_vid),
9964 get_cvar_ic_value(iseq, RNODE_CVASGN(node)->nd_vid));
9968 CHECK(compile_op_asgn1(iseq, ret, node, popped));
9971 CHECK(compile_op_asgn2(iseq, ret, node, popped));
9974 CHECK(compile_op_cdecl(iseq, ret, node, popped));
9976 case NODE_OP_ASGN_AND:
9977 case NODE_OP_ASGN_OR:
9978 CHECK(compile_op_log(iseq, ret, node, popped,
type));
9982 if (compile_call_precheck_freeze(iseq, ret, node, node, popped) == TRUE) {
9988 if (compile_call(iseq, ret, node,
type, node, popped,
false) == COMPILE_NG) {
9994 CHECK(compile_super(iseq, ret, node, popped,
type));
9997 CHECK(compile_array(iseq, ret, node, popped) >= 0);
10002 ADD_INSN1(ret, node, newarray,
INT2FIX(0));
10007 CHECK(compile_hash(iseq, ret, node, FALSE, popped) >= 0);
10010 CHECK(compile_return(iseq, ret, node, popped));
10013 CHECK(compile_yield(iseq, ret, node, popped));
10017 compile_lvar(iseq, ret, node, RNODE_LVAR(node)->nd_vid);
10023 debugi(
"nd_vid", RNODE_DVAR(node)->nd_vid);
10025 idx = get_dyna_var_idx(iseq, RNODE_DVAR(node)->nd_vid, &lv, &ls);
10027 COMPILE_ERROR(ERROR_ARGS
"unknown dvar (%"PRIsVALUE
")",
10028 rb_id2str(RNODE_DVAR(node)->nd_vid));
10031 ADD_GETLOCAL(ret, node, ls - idx, lv);
10036 ADD_INSN1(ret, node, getglobal,
ID2SYM(RNODE_GVAR(node)->nd_vid));
10038 ADD_INSN(ret, node, pop);
10043 debugi(
"nd_vid", RNODE_IVAR(node)->nd_vid);
10045 ADD_INSN2(ret, node, getinstancevariable,
10046 ID2SYM(RNODE_IVAR(node)->nd_vid),
10047 get_ivar_ic_value(iseq, RNODE_IVAR(node)->nd_vid));
10052 debugi(
"nd_vid", RNODE_CONST(node)->nd_vid);
10054 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
10056 VALUE segments = rb_ary_new_from_args(1,
ID2SYM(RNODE_CONST(node)->nd_vid));
10057 ADD_INSN1(ret, node, opt_getconstant_path, segments);
10061 ADD_INSN(ret, node, putnil);
10062 ADD_INSN1(ret, node, putobject,
Qtrue);
10063 ADD_INSN1(ret, node, getconstant,
ID2SYM(RNODE_CONST(node)->nd_vid));
10067 ADD_INSN(ret, node, pop);
10073 ADD_INSN2(ret, node, getclassvariable,
10074 ID2SYM(RNODE_CVAR(node)->nd_vid),
10075 get_cvar_ic_value(iseq, RNODE_CVAR(node)->nd_vid));
10079 case NODE_NTH_REF:{
10081 if (!RNODE_NTH_REF(node)->nd_nth) {
10082 ADD_INSN(ret, node, putnil);
10085 ADD_INSN2(ret, node, getspecial,
INT2FIX(1) ,
10086 INT2FIX(RNODE_NTH_REF(node)->nd_nth << 1));
10090 case NODE_BACK_REF:{
10092 ADD_INSN2(ret, node, getspecial,
INT2FIX(1) ,
10093 INT2FIX(0x01 | (RNODE_BACK_REF(node)->nd_nth << 1)));
10100 CHECK(compile_match(iseq, ret, node, popped,
type));
10103 debugp_param(
"lit", RNODE_LIT(node)->nd_lit);
10105 if (UNLIKELY(RNODE_LIT(node)->nd_lit == rb_mRubyVMFrozenCore)) {
10106 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10109 ADD_INSN1(ret, node, putobject, RNODE_LIT(node)->nd_lit);
10116 debugp_param(
"nd_lit", RNODE_STR(node)->nd_lit);
10118 VALUE lit = RNODE_STR(node)->nd_lit;
10119 if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
10120 lit = rb_fstring(lit);
10121 ADD_INSN1(ret, node, putstring, lit);
10125 if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal ||
RTEST(
ruby_debug)) {
10126 VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq),
INT2FIX(line));
10127 lit = rb_str_dup(lit);
10128 rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
10132 lit = rb_fstring(lit);
10134 ADD_INSN1(ret, node, putobject, lit);
10141 compile_dstr(iseq, ret, node);
10144 ADD_INSN(ret, node, pop);
10149 ADD_CALL_RECEIVER(ret, node);
10150 VALUE str = rb_fstring(RNODE_XSTR(node)->nd_lit);
10151 ADD_INSN1(ret, node, putobject, str);
10153 ADD_CALL(ret, node, idBackquote,
INT2FIX(1));
10156 ADD_INSN(ret, node, pop);
10161 ADD_CALL_RECEIVER(ret, node);
10162 compile_dstr(iseq, ret, node);
10163 ADD_CALL(ret, node, idBackquote,
INT2FIX(1));
10166 ADD_INSN(ret, node, pop);
10171 CHECK(compile_evstr(iseq, ret, RNODE_EVSTR(node)->nd_body, popped));
10174 compile_dregx(iseq, ret, node, popped);
10177 int ic_index = body->ise_size++;
10178 const rb_iseq_t *block_iseq;
10179 block_iseq = NEW_CHILD_ISEQ(RNODE_ONCE(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line);
10181 ADD_INSN2(ret, node, once, block_iseq,
INT2FIX(ic_index));
10185 ADD_INSN(ret, node, pop);
10189 case NODE_ARGSCAT:{
10191 CHECK(COMPILE(ret,
"argscat head", RNODE_ARGSCAT(node)->nd_head));
10192 ADD_INSN1(ret, node, splatarray,
Qfalse);
10193 ADD_INSN(ret, node, pop);
10194 CHECK(COMPILE(ret,
"argscat body", RNODE_ARGSCAT(node)->nd_body));
10195 ADD_INSN1(ret, node, splatarray,
Qfalse);
10196 ADD_INSN(ret, node, pop);
10199 CHECK(COMPILE(ret,
"argscat head", RNODE_ARGSCAT(node)->nd_head));
10200 CHECK(COMPILE(ret,
"argscat body", RNODE_ARGSCAT(node)->nd_body));
10201 ADD_INSN(ret, node, concatarray);
10205 case NODE_ARGSPUSH:{
10207 CHECK(COMPILE(ret,
"argspush head", RNODE_ARGSPUSH(node)->nd_head));
10208 ADD_INSN1(ret, node, splatarray,
Qfalse);
10209 ADD_INSN(ret, node, pop);
10210 CHECK(COMPILE_(ret,
"argspush body", RNODE_ARGSPUSH(node)->nd_body, popped));
10213 CHECK(COMPILE(ret,
"argspush head", RNODE_ARGSPUSH(node)->nd_head));
10214 CHECK(compile_array_1(iseq, ret, RNODE_ARGSPUSH(node)->nd_body));
10215 ADD_INSN(ret, node, concatarray);
10220 CHECK(COMPILE(ret,
"splat", RNODE_SPLAT(node)->nd_head));
10221 ADD_INSN1(ret, node, splatarray,
Qtrue);
10224 ADD_INSN(ret, node, pop);
10229 ID mid = RNODE_DEFN(node)->nd_mid;
10230 const rb_iseq_t *method_iseq = NEW_ISEQ(RNODE_DEFN(node)->nd_defn,
10232 ISEQ_TYPE_METHOD, line);
10234 debugp_param(
"defn/iseq", rb_iseqw_new(method_iseq));
10235 ADD_INSN2(ret, node, definemethod,
ID2SYM(mid), method_iseq);
10239 ADD_INSN1(ret, node, putobject,
ID2SYM(mid));
10245 ID mid = RNODE_DEFS(node)->nd_mid;
10246 const rb_iseq_t * singleton_method_iseq = NEW_ISEQ(RNODE_DEFS(node)->nd_defn,
10248 ISEQ_TYPE_METHOD, line);
10250 debugp_param(
"defs/iseq", rb_iseqw_new(singleton_method_iseq));
10251 CHECK(COMPILE(ret,
"defs: recv", RNODE_DEFS(node)->nd_recv));
10252 ADD_INSN2(ret, node, definesmethod,
ID2SYM(mid), singleton_method_iseq);
10256 ADD_INSN1(ret, node, putobject,
ID2SYM(mid));
10261 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10262 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_CBASE));
10263 CHECK(COMPILE(ret,
"alias arg1", RNODE_ALIAS(node)->nd_1st));
10264 CHECK(COMPILE(ret,
"alias arg2", RNODE_ALIAS(node)->nd_2nd));
10265 ADD_SEND(ret, node, id_core_set_method_alias,
INT2FIX(3));
10268 ADD_INSN(ret, node, pop);
10273 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10274 ADD_INSN1(ret, node, putobject,
ID2SYM(RNODE_VALIAS(node)->nd_alias));
10275 ADD_INSN1(ret, node, putobject,
ID2SYM(RNODE_VALIAS(node)->nd_orig));
10276 ADD_SEND(ret, node, id_core_set_variable_alias,
INT2FIX(2));
10279 ADD_INSN(ret, node, pop);
10284 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10285 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_CBASE));
10286 CHECK(COMPILE(ret,
"undef arg", RNODE_UNDEF(node)->nd_undef));
10287 ADD_SEND(ret, node, id_core_undef_method,
INT2FIX(2));
10290 ADD_INSN(ret, node, pop);
10295 const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(RNODE_CLASS(node)->nd_body,
10296 rb_str_freeze(rb_sprintf(
"<class:%"PRIsVALUE
">", rb_id2str(get_node_colon_nd_mid(RNODE_CLASS(node)->nd_cpath)))),
10297 ISEQ_TYPE_CLASS, line);
10298 const int flags = VM_DEFINECLASS_TYPE_CLASS |
10299 (RNODE_CLASS(node)->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) |
10300 compile_cpath(ret, iseq, RNODE_CLASS(node)->nd_cpath);
10302 CHECK(COMPILE(ret,
"super", RNODE_CLASS(node)->nd_super));
10303 ADD_INSN3(ret, node, defineclass,
ID2SYM(get_node_colon_nd_mid(RNODE_CLASS(node)->nd_cpath)), class_iseq,
INT2FIX(flags));
10307 ADD_INSN(ret, node, pop);
10312 const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(RNODE_MODULE(node)->nd_body,
10313 rb_str_freeze(rb_sprintf(
"<module:%"PRIsVALUE
">", rb_id2str(get_node_colon_nd_mid(RNODE_MODULE(node)->nd_cpath)))),
10314 ISEQ_TYPE_CLASS, line);
10315 const int flags = VM_DEFINECLASS_TYPE_MODULE |
10316 compile_cpath(ret, iseq, RNODE_MODULE(node)->nd_cpath);
10318 ADD_INSN (ret, node, putnil);
10319 ADD_INSN3(ret, node, defineclass,
ID2SYM(get_node_colon_nd_mid(RNODE_MODULE(node)->nd_cpath)), module_iseq,
INT2FIX(flags));
10323 ADD_INSN(ret, node, pop);
10329 const rb_iseq_t *singleton_class = NEW_ISEQ(RNODE_SCLASS(node)->nd_body, rb_fstring_lit(
"singleton class"),
10330 ISEQ_TYPE_CLASS, line);
10332 CHECK(COMPILE(ret,
"sclass#recv", RNODE_SCLASS(node)->nd_recv));
10333 ADD_INSN (ret, node, putnil);
10334 CONST_ID(singletonclass,
"singletonclass");
10335 ADD_INSN3(ret, node, defineclass,
10336 ID2SYM(singletonclass), singleton_class,
10337 INT2FIX(VM_DEFINECLASS_TYPE_SINGLETON_CLASS));
10341 ADD_INSN(ret, node, pop);
10346 CHECK(compile_colon2(iseq, ret, node, popped));
10349 CHECK(compile_colon3(iseq, ret, node, popped));
10352 CHECK(compile_dots(iseq, ret, node, popped, FALSE));
10355 CHECK(compile_dots(iseq, ret, node, popped, TRUE));
10359 LABEL *lend = NEW_LABEL(line);
10360 LABEL *ltrue = NEW_LABEL(line);
10361 LABEL *lfalse = NEW_LABEL(line);
10362 CHECK(compile_flip_flop(iseq, ret, node,
type == NODE_FLIP2,
10364 ADD_LABEL(ret, ltrue);
10365 ADD_INSN1(ret, node, putobject,
Qtrue);
10366 ADD_INSNL(ret, node, jump, lend);
10367 ADD_LABEL(ret, lfalse);
10368 ADD_INSN1(ret, node, putobject,
Qfalse);
10369 ADD_LABEL(ret, lend);
10374 ADD_INSN(ret, node, putself);
10380 ADD_INSN(ret, node, putnil);
10386 ADD_INSN1(ret, node, putobject,
Qtrue);
10392 ADD_INSN1(ret, node, putobject,
Qfalse);
10397 CHECK(compile_errinfo(iseq, ret, node, popped));
10401 CHECK(compile_defined_expr(iseq, ret, node,
Qtrue));
10404 case NODE_POSTEXE:{
10408 int is_index = body->ise_size++;
10410 rb_iseq_new_with_callback_new_callback(build_postexe_iseq, RNODE_POSTEXE(node)->nd_body);
10411 const rb_iseq_t *once_iseq =
10412 new_child_iseq_with_callback(iseq, ifunc,
10413 rb_fstring(make_name_for_block(iseq)), iseq, ISEQ_TYPE_BLOCK, line);
10415 ADD_INSN2(ret, node, once, once_iseq,
INT2FIX(is_index));
10419 ADD_INSN(ret, node, pop);
10424 CHECK(compile_kw_arg(iseq, ret, node, popped));
10427 compile_dstr(iseq, ret, node);
10429 ADD_INSN(ret, node, intern);
10432 ADD_INSN(ret, node, pop);
10436 case NODE_ATTRASGN:
10437 CHECK(compile_attrasgn(iseq, ret, node, popped));
10441 const rb_iseq_t *block = NEW_CHILD_ISEQ(RNODE_LAMBDA(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
10444 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10445 ADD_CALL_WITH_BLOCK(ret, node, idLambda, argc, block);
10449 ADD_INSN(ret, node, pop);
10454 UNKNOWN_NODE(
"iseq_compile_each", node, COMPILE_NG);
10469insn_data_length(INSN *iobj)
10471 return insn_len(iobj->insn_id);
10475calc_sp_depth(
int depth, INSN *insn)
10477 return comptime_insn_stack_increase(depth, insn->insn_id, insn->operands);
10481opobj_inspect(
VALUE obj)
10489 obj = rb_ary_dup(obj);
10501insn_data_to_s_detail(INSN *iobj)
10503 VALUE str = rb_sprintf(
"%-20s ", insn_name(iobj->insn_id));
10505 if (iobj->operands) {
10506 const char *types = insn_op_types(iobj->insn_id);
10509 for (j = 0; types[j]; j++) {
10510 char type = types[j];
10515 LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j);
10516 rb_str_catf(str, LABEL_FORMAT, lobj->label_no);
10522 rb_iseq_t *iseq = (rb_iseq_t *)OPERAND_AT(iobj, j);
10534 VALUE v = OPERAND_AT(iobj, j);
10549 rb_str_catf(str,
"<ivc:%d>",
FIX2INT(OPERAND_AT(iobj, j)));
10552 rb_str_catf(str,
"<icvarc:%d>",
FIX2INT(OPERAND_AT(iobj, j)));
10555 rb_str_catf(str,
"<ise:%d>",
FIX2INT(OPERAND_AT(iobj, j)));
10561 if (vm_ci_mid(ci)) rb_str_catf(str,
"%"PRIsVALUE, rb_id2str(vm_ci_mid(ci)));
10562 rb_str_catf(str,
", %d>", vm_ci_argc(ci));
10570 void *func = (
void *)OPERAND_AT(iobj, j);
10573 if (dladdr(func, &info) && info.dli_sname) {
10578 rb_str_catf(str,
"<%p>", func);
10588 if (types[j + 1]) {
10597dump_disasm_list(
const LINK_ELEMENT *link)
10599 dump_disasm_list_with_cursor(link, NULL, NULL);
10603dump_disasm_list_with_cursor(
const LINK_ELEMENT *link,
const LINK_ELEMENT *curr,
const LABEL *dest)
10610 printf(
"-- raw disasm--------\n");
10613 if (curr) printf(curr == link ?
"*" :
" ");
10614 switch (link->type) {
10615 case ISEQ_ELEMENT_INSN:
10617 iobj = (INSN *)link;
10618 str = insn_data_to_s_detail(iobj);
10619 printf(
" %04d %-65s(%4u)\n", pos,
StringValueCStr(str), iobj->insn_info.line_no);
10620 pos += insn_data_length(iobj);
10623 case ISEQ_ELEMENT_LABEL:
10625 lobj = (LABEL *)link;
10626 printf(LABEL_FORMAT
" [sp: %d]%s\n", lobj->label_no, lobj->sp,
10627 dest == lobj ?
" <---" :
"");
10630 case ISEQ_ELEMENT_TRACE:
10632 TRACE *trace = (TRACE *)link;
10633 printf(
" trace: %0x\n", trace->event);
10636 case ISEQ_ELEMENT_ADJUST:
10638 ADJUST *adjust = (ADJUST *)link;
10639 printf(
" adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1);
10648 printf(
"---------------------\n");
10653rb_insn_len(
VALUE insn)
10655 return insn_len(insn);
10659rb_insns_name(
int i)
10661 return insn_name(i);
10665rb_insns_name_array(
void)
10667 VALUE ary = rb_ary_new_capa(VM_INSTRUCTION_SIZE);
10669 for (i = 0; i < VM_INSTRUCTION_SIZE; i++) {
10670 rb_ary_push(ary, rb_fstring_cstr(insn_name(i)));
10672 return rb_obj_freeze(ary);
10676register_label(rb_iseq_t *iseq,
struct st_table *labels_table,
VALUE obj)
10680 obj = rb_to_symbol_type(obj);
10682 if (st_lookup(labels_table, obj, &tmp) == 0) {
10683 label = NEW_LABEL(0);
10684 st_insert(labels_table, obj, (st_data_t)label);
10687 label = (LABEL *)tmp;
10694get_exception_sym2type(
VALUE sym)
10696 static VALUE symRescue, symEnsure, symRetry;
10697 static VALUE symBreak, symRedo, symNext;
10699 if (symRescue == 0) {
10708 if (sym == symRescue)
return CATCH_TYPE_RESCUE;
10709 if (sym == symEnsure)
return CATCH_TYPE_ENSURE;
10710 if (sym == symRetry)
return CATCH_TYPE_RETRY;
10711 if (sym == symBreak)
return CATCH_TYPE_BREAK;
10712 if (sym == symRedo)
return CATCH_TYPE_REDO;
10713 if (sym == symNext)
return CATCH_TYPE_NEXT;
10714 rb_raise(
rb_eSyntaxError,
"invalid exception symbol: %+"PRIsVALUE, sym);
10719iseq_build_from_ary_exception(rb_iseq_t *iseq,
struct st_table *labels_table,
10725 const rb_iseq_t *eiseq;
10727 LABEL *lstart, *lend, *lcont;
10742 lstart = register_label(iseq, labels_table,
RARRAY_AREF(v, 2));
10743 lend = register_label(iseq, labels_table,
RARRAY_AREF(v, 3));
10744 lcont = register_label(iseq, labels_table,
RARRAY_AREF(v, 4));
10748 if (
type == CATCH_TYPE_RESCUE ||
10749 type == CATCH_TYPE_BREAK ||
10750 type == CATCH_TYPE_NEXT) {
10756 ADD_CATCH_ENTRY(
type, lstart, lend, eiseq, lcont);
10763static struct st_table *
10764insn_make_insn_table(
void)
10766 struct st_table *table;
10768 table = st_init_numtable_with_size(VM_INSTRUCTION_SIZE);
10770 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
10777static const rb_iseq_t *
10778iseq_build_load_iseq(
const rb_iseq_t *iseq,
VALUE op)
10781 const rb_iseq_t *loaded_iseq;
10783 if (RB_TYPE_P(op,
T_ARRAY)) {
10784 iseqw = rb_iseq_load(op, (
VALUE)iseq,
Qnil);
10786 else if (
CLASS_OF(op) == rb_cISeq) {
10793 loaded_iseq = rb_iseqw_to_iseq(iseqw);
10794 return loaded_iseq;
10798iseq_build_callinfo_from_hash(rb_iseq_t *iseq,
VALUE op)
10802 unsigned int flag = 0;
10813 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
10815 if (!
NIL_P(vkw_arg)) {
10818 size_t n = rb_callinfo_kwarg_bytes(
len);
10821 kw_arg->references = 0;
10822 kw_arg->keyword_len =
len;
10823 for (i = 0; i <
len; i++) {
10826 kw_arg->keywords[i] = kw;
10831 const struct rb_callinfo *ci = new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0);
10837event_name_to_flag(
VALUE sym)
10839#define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern_const(#ev))) return ev;
10853iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *
const anchor,
10858 struct st_table *labels_table =
DATA_PTR(labels_wrapper);
10860 int line_no = 0, node_id = -1, insn_idx = 0;
10861 int ret = COMPILE_OK;
10866 static struct st_table *insn_table;
10868 if (insn_table == 0) {
10869 insn_table = insn_make_insn_table();
10872 for (i=0; i<
len; i++) {
10878 ADD_TRACE(anchor, event);
10881 LABEL *label = register_label(iseq, labels_table, obj);
10882 ADD_LABEL(anchor, label);
10888 else if (RB_TYPE_P(obj,
T_ARRAY)) {
10895 node_id =
NUM2INT(rb_ary_entry(node_ids, insn_idx++));
10899 if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
10901 COMPILE_ERROR(iseq, line_no,
10902 "unknown instruction: %+"PRIsVALUE, insn);
10907 if (argc != insn_len((
VALUE)insn_id)-1) {
10908 COMPILE_ERROR(iseq, line_no,
10909 "operand size mismatch");
10915 argv = compile_data_calloc2(iseq,
sizeof(
VALUE), argc);
10918 NODE dummy_line_node = generate_dummy_line_node(line_no, node_id);
10920 (LINK_ELEMENT*)new_insn_core(iseq, &dummy_line_node,
10921 (
enum ruby_vminsn_type)insn_id, argc, argv));
10923 for (j=0; j<argc; j++) {
10924 VALUE op = rb_ary_entry(obj, j+1);
10925 switch (insn_op_type((
VALUE)insn_id, j)) {
10927 LABEL *label = register_label(iseq, labels_table, op);
10928 argv[j] = (
VALUE)label;
10943 VALUE v = (
VALUE)iseq_build_load_iseq(iseq, op);
10954 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->ise_size) {
10955 ISEQ_BODY(iseq)->ise_size =
NUM2INT(op) + 1;
10960 VALUE segments = rb_ary_new();
10961 op = rb_to_array_type(op);
10965 sym = rb_to_symbol_type(sym);
10966 rb_ary_push(segments, sym);
10970 argv[j] = segments;
10972 ISEQ_BODY(iseq)->ic_size++;
10977 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->ivc_size) {
10978 ISEQ_BODY(iseq)->ivc_size =
NUM2INT(op) + 1;
10983 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->icvarc_size) {
10984 ISEQ_BODY(iseq)->icvarc_size =
NUM2INT(op) + 1;
10988 argv[j] = iseq_build_callinfo_from_hash(iseq, op);
10991 argv[j] = rb_to_symbol_type(op);
10998 RHASH_TBL_RAW(map)->type = &cdhash_type;
10999 op = rb_to_array_type(op);
11004 register_label(iseq, labels_table, sym);
11005 rb_hash_aset(map, key, (
VALUE)label | 1);
11014#if SIZEOF_VALUE <= SIZEOF_LONG
11019 argv[j] = (
VALUE)funcptr;
11028 NODE dummy_line_node = generate_dummy_line_node(line_no, node_id);
11030 (LINK_ELEMENT*)new_insn_core(iseq, &dummy_line_node,
11031 (
enum ruby_vminsn_type)insn_id, argc, NULL));
11035 rb_raise(
rb_eTypeError,
"unexpected object for instruction");
11039 validate_labels(iseq, labels_table);
11040 if (!ret)
return ret;
11041 return iseq_setup(iseq, anchor);
11044#define CHECK_ARRAY(v) rb_to_array_type(v)
11045#define CHECK_SYMBOL(v) rb_to_symbol_type(v)
11050 VALUE val = rb_hash_aref(param, sym);
11055 else if (!
NIL_P(val)) {
11056 rb_raise(
rb_eTypeError,
"invalid %+"PRIsVALUE
" Fixnum: %+"PRIsVALUE,
11062static const struct rb_iseq_param_keyword *
11063iseq_build_kw(rb_iseq_t *iseq,
VALUE params,
VALUE keywords)
11068 VALUE key, sym, default_val;
11071 struct rb_iseq_param_keyword *keyword =
ZALLOC(
struct rb_iseq_param_keyword);
11073 ISEQ_BODY(iseq)->param.flags.has_kw = TRUE;
11075 keyword->num =
len;
11076#define SYM(s) ID2SYM(rb_intern_const(#s))
11077 (void)int_param(&keyword->bits_start, params, SYM(kwbits));
11078 i = keyword->bits_start - keyword->num;
11079 ids = (
ID *)&ISEQ_BODY(iseq)->local_table[i];
11083 for (i = 0; i <
len; i++) {
11087 goto default_values;
11090 keyword->required_num++;
11094 default_len =
len - i;
11095 if (default_len == 0) {
11096 keyword->table = ids;
11099 else if (default_len < 0) {
11105 for (j = 0; i <
len; i++, j++) {
11119 rb_raise(
rb_eTypeError,
"keyword default has unsupported len %+"PRIsVALUE, key);
11122 dvs[j] = default_val;
11125 keyword->table = ids;
11126 keyword->default_values = dvs;
11132iseq_insn_each_object_mark_and_pin(
VALUE obj,
VALUE _)
11141 size_t size =
sizeof(INSN);
11142 unsigned int pos = 0;
11145#ifdef STRICT_ALIGNMENT
11146 size_t padding = calc_padding((
void *)&storage->buff[pos], size);
11148 const size_t padding = 0;
11150 size_t offset = pos + size + padding;
11151 if (offset > storage->size || offset > storage->pos) {
11153 storage = storage->next;
11156#ifdef STRICT_ALIGNMENT
11157 pos += (int)padding;
11160 iobj = (INSN *)&storage->buff[pos];
11162 if (iobj->operands) {
11163 iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark_and_pin, (
VALUE)0);
11171rb_iseq_build_from_ary(rb_iseq_t *iseq,
VALUE misc,
VALUE locals,
VALUE params,
11174#define SYM(s) ID2SYM(rb_intern_const(#s))
11176 unsigned int arg_size, local_size, stack_max;
11178 struct st_table *labels_table = st_init_numtable();
11180 VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt));
11181 VALUE keywords = rb_hash_aref(params, SYM(keyword));
11183 DECL_ANCHOR(anchor);
11184 INIT_ANCHOR(anchor);
11187 ISEQ_BODY(iseq)->local_table_size =
len;
11188 ISEQ_BODY(iseq)->local_table = tbl =
len > 0 ? (
ID *)
ALLOC_N(
ID, ISEQ_BODY(iseq)->local_table_size) : NULL;
11190 for (i = 0; i <
len; i++) {
11193 if (sym_arg_rest == lv) {
11201#define INT_PARAM(F) int_param(&ISEQ_BODY(iseq)->param.F, params, SYM(F))
11202 if (INT_PARAM(lead_num)) {
11203 ISEQ_BODY(iseq)->param.flags.has_lead = TRUE;
11205 if (INT_PARAM(post_num)) ISEQ_BODY(iseq)->param.flags.has_post = TRUE;
11206 if (INT_PARAM(post_start)) ISEQ_BODY(iseq)->param.flags.has_post = TRUE;
11207 if (INT_PARAM(rest_start)) ISEQ_BODY(iseq)->param.flags.has_rest = TRUE;
11208 if (INT_PARAM(block_start)) ISEQ_BODY(iseq)->param.flags.has_block = TRUE;
11211#define INT_PARAM(F) F = (int_param(&x, misc, SYM(F)) ? (unsigned int)x : 0)
11213 INT_PARAM(arg_size);
11214 INT_PARAM(local_size);
11215 INT_PARAM(stack_max);
11220#ifdef USE_ISEQ_NODE_ID
11221 node_ids = rb_hash_aref(misc,
ID2SYM(rb_intern(
"node_ids")));
11222 if (!RB_TYPE_P(node_ids,
T_ARRAY)) {
11227 if (RB_TYPE_P(arg_opt_labels,
T_ARRAY)) {
11229 ISEQ_BODY(iseq)->param.flags.has_opt = !!(
len - 1 >= 0);
11231 if (ISEQ_BODY(iseq)->param.flags.has_opt) {
11234 for (i = 0; i <
len; i++) {
11236 LABEL *label = register_label(iseq, labels_table, ent);
11237 opt_table[i] = (
VALUE)label;
11240 ISEQ_BODY(iseq)->param.opt_num =
len - 1;
11241 ISEQ_BODY(iseq)->param.opt_table = opt_table;
11244 else if (!
NIL_P(arg_opt_labels)) {
11245 rb_raise(
rb_eTypeError,
":opt param is not an array: %+"PRIsVALUE,
11249 if (RB_TYPE_P(keywords,
T_ARRAY)) {
11250 ISEQ_BODY(iseq)->param.keyword = iseq_build_kw(iseq, params, keywords);
11252 else if (!
NIL_P(keywords)) {
11253 rb_raise(
rb_eTypeError,
":keywords param is not an array: %+"PRIsVALUE,
11257 if (
Qtrue == rb_hash_aref(params, SYM(ambiguous_param0))) {
11258 ISEQ_BODY(iseq)->param.flags.ambiguous_param0 = TRUE;
11261 if (int_param(&i, params, SYM(kwrest))) {
11262 struct rb_iseq_param_keyword *keyword = (
struct rb_iseq_param_keyword *)ISEQ_BODY(iseq)->param.keyword;
11263 if (keyword == NULL) {
11264 ISEQ_BODY(iseq)->param.keyword = keyword =
ZALLOC(
struct rb_iseq_param_keyword);
11266 keyword->rest_start = i;
11267 ISEQ_BODY(iseq)->param.flags.has_kwrest = TRUE;
11270 iseq_calc_param_size(iseq);
11273 iseq_build_from_ary_exception(iseq, labels_table, exception);
11276 iseq_build_from_ary_body(iseq, anchor, body, node_ids, labels_wrapper);
11278 ISEQ_BODY(iseq)->param.size = arg_size;
11279 ISEQ_BODY(iseq)->local_table_size = local_size;
11280 ISEQ_BODY(iseq)->stack_max = stack_max;
11286rb_dvar_defined(
ID id,
const rb_iseq_t *iseq)
11290 while (body->type == ISEQ_TYPE_BLOCK ||
11291 body->type == ISEQ_TYPE_RESCUE ||
11292 body->type == ISEQ_TYPE_ENSURE ||
11293 body->type == ISEQ_TYPE_EVAL ||
11294 body->type == ISEQ_TYPE_MAIN
11298 for (i = 0; i < body->local_table_size; i++) {
11299 if (body->local_table[i] ==
id) {
11303 iseq = body->parent_iseq;
11304 body = ISEQ_BODY(iseq);
11311rb_local_defined(
ID id,
const rb_iseq_t *iseq)
11317 for (i=0; i<body->local_table_size; i++) {
11318 if (body->local_table[i] ==
id) {
11328#ifndef IBF_ISEQ_DEBUG
11329#define IBF_ISEQ_DEBUG 0
11332#ifndef IBF_ISEQ_ENABLE_LOCAL_BUFFER
11333#define IBF_ISEQ_ENABLE_LOCAL_BUFFER 0
11336typedef uint32_t ibf_offset_t;
11337#define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
11339#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
11341#define IBF_DEVEL_VERSION 4
11342#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
11344#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
11347static const char IBF_ENDIAN_MARK =
11348#ifdef WORDS_BIGENDIAN
11357 uint32_t major_version;
11358 uint32_t minor_version;
11360 uint32_t extra_size;
11362 uint32_t iseq_list_size;
11363 uint32_t global_object_list_size;
11364 ibf_offset_t iseq_list_offset;
11365 ibf_offset_t global_object_list_offset;
11386 unsigned int obj_list_size;
11387 ibf_offset_t obj_list_offset;
11406pinned_list_mark(
void *ptr)
11410 for (i = 0; i < list->size; i++) {
11411 if (list->buffer[i]) {
11412 rb_gc_mark(list->buffer[i]);
11424 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE
11428pinned_list_fetch(
VALUE list,
long offset)
11434 if (offset >= ptr->size) {
11435 rb_raise(
rb_eIndexError,
"object index out of range: %ld", offset);
11438 return ptr->buffer[offset];
11442pinned_list_store(
VALUE list,
long offset,
VALUE object)
11448 if (offset >= ptr->size) {
11449 rb_raise(
rb_eIndexError,
"object index out of range: %ld", offset);
11456pinned_list_new(
long size)
11458 size_t memsize = offsetof(
struct pinned_list, buffer) + size *
sizeof(
VALUE);
11459 VALUE obj_list = rb_data_typed_object_zalloc(0, memsize, &pinned_list_type);
11460 struct pinned_list * ptr = RTYPEDDATA_GET_DATA(obj_list);
11466ibf_dump_pos(
struct ibf_dump *dump)
11468 long pos = RSTRING_LEN(dump->current_buffer->str);
11469#if SIZEOF_LONG > SIZEOF_INT
11470 if (pos >= UINT_MAX) {
11474 return (
unsigned int)pos;
11478ibf_dump_align(
struct ibf_dump *dump,
size_t align)
11480 ibf_offset_t pos = ibf_dump_pos(dump);
11482 static const char padding[
sizeof(
VALUE)];
11483 size_t size = align - ((size_t)pos % align);
11484#if SIZEOF_LONG > SIZEOF_INT
11485 if (pos + size >= UINT_MAX) {
11489 for (; size >
sizeof(padding); size -=
sizeof(padding)) {
11490 rb_str_cat(dump->current_buffer->str, padding,
sizeof(padding));
11492 rb_str_cat(dump->current_buffer->str, padding, size);
11497ibf_dump_write(
struct ibf_dump *dump,
const void *buff,
unsigned long size)
11499 ibf_offset_t pos = ibf_dump_pos(dump);
11500 rb_str_cat(dump->current_buffer->str, (
const char *)buff, size);
11506ibf_dump_write_byte(
struct ibf_dump *dump,
unsigned char byte)
11508 return ibf_dump_write(dump, &
byte,
sizeof(
unsigned char));
11512ibf_dump_overwrite(
struct ibf_dump *dump,
void *buff,
unsigned int size,
long offset)
11514 VALUE str = dump->current_buffer->str;
11515 char *ptr = RSTRING_PTR(str);
11516 if ((
unsigned long)(size + offset) > (
unsigned long)RSTRING_LEN(str))
11517 rb_bug(
"ibf_dump_overwrite: overflow");
11518 memcpy(ptr + offset, buff, size);
11522ibf_load_ptr(
const struct ibf_load *load, ibf_offset_t *offset,
int size)
11524 ibf_offset_t beg = *offset;
11526 return load->current_buffer->buff + beg;
11530ibf_load_alloc(
const struct ibf_load *load, ibf_offset_t offset,
size_t x,
size_t y)
11532 void *buff = ruby_xmalloc2(x, y);
11533 size_t size = x * y;
11534 memcpy(buff, load->current_buffer->buff + offset, size);
11538#define IBF_W_ALIGN(type) (RUBY_ALIGNOF(type) > 1 ? ibf_dump_align(dump, RUBY_ALIGNOF(type)) : (void)0)
11540#define IBF_W(b, type, n) (IBF_W_ALIGN(type), (type *)(VALUE)IBF_WP(b, type, n))
11541#define IBF_WV(variable) ibf_dump_write(dump, &(variable), sizeof(variable))
11542#define IBF_WP(b, type, n) ibf_dump_write(dump, (b), sizeof(type) * (n))
11543#define IBF_R(val, type, n) (type *)ibf_load_alloc(load, IBF_OFFSET(val), sizeof(type), (n))
11544#define IBF_ZERO(variable) memset(&(variable), 0, sizeof(variable))
11547ibf_table_lookup(
struct st_table *table, st_data_t key)
11551 if (st_lookup(table, key, &val)) {
11560ibf_table_find_or_insert(
struct st_table *table, st_data_t key)
11562 int index = ibf_table_lookup(table, key);
11565 index = (int)table->num_entries;
11566 st_insert(table, key, (st_data_t)index);
11574static void ibf_dump_object_list(
struct ibf_dump *dump, ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size);
11577static rb_iseq_t *ibf_load_iseq(
const struct ibf_load *load,
const rb_iseq_t *index_iseq);
11580ibf_dump_object_table_new(
void)
11582 st_table *obj_table = st_init_numtable();
11583 st_insert(obj_table, (st_data_t)
Qnil, (st_data_t)0);
11591 return ibf_table_find_or_insert(dump->current_buffer->obj_table, (st_data_t)obj);
11597 if (
id == 0 || rb_id2name(
id) == NULL) {
11600 return ibf_dump_object(dump, rb_id2sym(
id));
11604ibf_load_id(
const struct ibf_load *load,
const ID id_index)
11606 if (id_index == 0) {
11609 VALUE sym = ibf_load_object(load, id_index);
11615static ibf_offset_t ibf_dump_iseq_each(
struct ibf_dump *dump,
const rb_iseq_t *iseq);
11618ibf_dump_iseq(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
11620 if (iseq == NULL) {
11624 return ibf_table_find_or_insert(dump->iseq_table, (st_data_t)iseq);
11628static unsigned char
11629ibf_load_byte(
const struct ibf_load *load, ibf_offset_t *offset)
11631 if (*offset >= load->current_buffer->size) { rb_raise(
rb_eRuntimeError,
"invalid bytecode"); }
11632 return (
unsigned char)load->current_buffer->buff[(*offset)++];
11648 if (
sizeof(
VALUE) > 8 || CHAR_BIT != 8) {
11649 ibf_dump_write(dump, &x,
sizeof(
VALUE));
11653 enum { max_byte_length =
sizeof(
VALUE) + 1 };
11655 unsigned char bytes[max_byte_length];
11658 for (n = 0; n <
sizeof(
VALUE) && (x >> (7 - n)); n++, x >>= 8) {
11659 bytes[max_byte_length - 1 - n] = (
unsigned char)x;
11665 bytes[max_byte_length - 1 - n] = (
unsigned char)x;
11668 ibf_dump_write(dump, bytes + max_byte_length - n, n);
11672ibf_load_small_value(
const struct ibf_load *load, ibf_offset_t *offset)
11674 if (
sizeof(
VALUE) > 8 || CHAR_BIT != 8) {
11675 union {
char s[
sizeof(
VALUE)];
VALUE v; } x;
11677 memcpy(x.s, load->current_buffer->buff + *offset,
sizeof(
VALUE));
11678 *offset +=
sizeof(
VALUE);
11683 enum { max_byte_length =
sizeof(
VALUE) + 1 };
11685 const unsigned char *buffer = (
const unsigned char *)load->current_buffer->buff;
11686 const unsigned char c = buffer[*offset];
11690 c == 0 ? 9 : ntz_int32(c) + 1;
11693 if (*offset + n > load->current_buffer->size) {
11698 for (i = 1; i < n; i++) {
11700 x |= (
VALUE)buffer[*offset + i];
11714 ibf_dump_write_small_value(dump, (
VALUE)bf->index);
11716 size_t len = strlen(bf->name);
11717 ibf_dump_write_small_value(dump, (
VALUE)
len);
11718 ibf_dump_write(dump, bf->name,
len);
11722ibf_load_builtin(
const struct ibf_load *load, ibf_offset_t *offset)
11724 int i = (int)ibf_load_small_value(load, offset);
11725 int len = (int)ibf_load_small_value(load, offset);
11726 const char *name = (
char *)ibf_load_ptr(load, offset,
len);
11729 fprintf(stderr,
"%.*s!!\n",
len, name);
11733 if (table == NULL) rb_raise(rb_eArgError,
"builtin function table is not provided");
11734 if (strncmp(table[i].name, name,
len) != 0) {
11735 rb_raise(rb_eArgError,
"builtin function index (%d) mismatch (expect %s but %s)", i, name, table[i].name);
11743ibf_dump_code(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
11746 const int iseq_size = body->iseq_size;
11748 const VALUE *orig_code = rb_iseq_original_iseq(iseq);
11750 ibf_offset_t offset = ibf_dump_pos(dump);
11752 for (code_index=0; code_index<iseq_size;) {
11753 const VALUE insn = orig_code[code_index++];
11754 const char *types = insn_op_types(insn);
11759 ibf_dump_write_small_value(dump, insn);
11762 for (op_index=0; types[op_index]; op_index++, code_index++) {
11763 VALUE op = orig_code[code_index];
11766 switch (types[op_index]) {
11769 wv = ibf_dump_object(dump, op);
11772 wv = (
VALUE)ibf_dump_iseq(dump, (
const rb_iseq_t *)op);
11778 wv = ibf_dump_object(dump, arr);
11786 wv = is - ISEQ_IS_ENTRY_START(body, types[op_index]);
11794 wv = ibf_dump_id(dump, (
ID)op);
11806 ibf_dump_write_small_value(dump, wv);
11809 assert(insn_len(insn) == op_index+1);
11816ibf_load_code(
const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecode_offset, ibf_offset_t bytecode_size,
unsigned int iseq_size)
11819 unsigned int code_index;
11820 ibf_offset_t reading_pos = bytecode_offset;
11824 struct rb_call_data *cd_entries = load_body->call_data;
11827 iseq_bits_t * mark_offset_bits;
11829 iseq_bits_t tmp[1] = {0};
11831 if (ISEQ_MBITS_BUFLEN(iseq_size) == 1) {
11832 mark_offset_bits = tmp;
11835 mark_offset_bits =
ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(iseq_size));
11837 bool needs_bitmap =
false;
11839 for (code_index=0; code_index<iseq_size;) {
11841 const VALUE insn = code[code_index] = ibf_load_small_value(load, &reading_pos);
11842 const char *types = insn_op_types(insn);
11848 for (op_index=0; types[op_index]; op_index++, code_index++) {
11849 const char operand_type = types[op_index];
11850 switch (operand_type) {
11853 VALUE op = ibf_load_small_value(load, &reading_pos);
11854 VALUE v = ibf_load_object(load, op);
11855 code[code_index] = v;
11858 ISEQ_MBITS_SET(mark_offset_bits, code_index);
11859 needs_bitmap =
true;
11865 VALUE op = ibf_load_small_value(load, &reading_pos);
11866 VALUE v = ibf_load_object(load, op);
11867 v = rb_hash_dup(v);
11868 RHASH_TBL_RAW(v)->type = &cdhash_type;
11870 freeze_hide_obj(v);
11875 pinned_list_store(load->current_buffer->obj_list, (
long)op, v);
11877 code[code_index] = v;
11878 ISEQ_MBITS_SET(mark_offset_bits, code_index);
11880 needs_bitmap =
true;
11885 VALUE op = (
VALUE)ibf_load_small_value(load, &reading_pos);
11886 VALUE v = (
VALUE)ibf_load_iseq(load, (
const rb_iseq_t *)op);
11887 code[code_index] = v;
11890 ISEQ_MBITS_SET(mark_offset_bits, code_index);
11891 needs_bitmap =
true;
11897 VALUE op = ibf_load_small_value(load, &reading_pos);
11898 VALUE arr = ibf_load_object(load, op);
11900 IC ic = &ISEQ_IS_IC_ENTRY(load_body, ic_index++);
11901 ic->
segments = array_to_idlist(arr);
11903 code[code_index] = (
VALUE)ic;
11910 unsigned int op = (
unsigned int)ibf_load_small_value(load, &reading_pos);
11912 ISE ic = ISEQ_IS_ENTRY_START(load_body, operand_type) + op;
11913 code[code_index] = (
VALUE)ic;
11915 if (operand_type == TS_IVC) {
11916 IVC cache = (IVC)ic;
11918 if (insn == BIN(setinstancevariable)) {
11919 ID iv_name = (
ID)code[code_index - 1];
11920 cache->iv_set_name = iv_name;
11923 cache->iv_set_name = 0;
11926 vm_ic_attr_index_initialize(cache, INVALID_SHAPE_ID);
11933 code[code_index] = (
VALUE)cd_entries++;
11938 VALUE op = ibf_load_small_value(load, &reading_pos);
11939 code[code_index] = ibf_load_id(load, (
ID)(
VALUE)op);
11946 code[code_index] = (
VALUE)ibf_load_builtin(load, &reading_pos);
11949 code[code_index] = ibf_load_small_value(load, &reading_pos);
11953 if (insn_len(insn) != op_index+1) {
11958 load_body->iseq_encoded = code;
11959 load_body->iseq_size = code_index;
11961 if (ISEQ_MBITS_BUFLEN(load_body->iseq_size) == 1) {
11962 load_body->mark_bits.single = mark_offset_bits[0];
11965 if (needs_bitmap) {
11966 load_body->mark_bits.list = mark_offset_bits;
11969 load_body->mark_bits.list = 0;
11970 ruby_xfree(mark_offset_bits);
11974 assert(code_index == iseq_size);
11975 assert(reading_pos == bytecode_offset + bytecode_size);
11980ibf_dump_param_opt_table(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
11982 int opt_num = ISEQ_BODY(iseq)->param.opt_num;
11985 IBF_W_ALIGN(
VALUE);
11986 return ibf_dump_write(dump, ISEQ_BODY(iseq)->param.opt_table,
sizeof(
VALUE) * (opt_num + 1));
11989 return ibf_dump_pos(dump);
11994ibf_load_param_opt_table(
const struct ibf_load *load, ibf_offset_t opt_table_offset,
int opt_num)
11998 MEMCPY(table, load->current_buffer->buff + opt_table_offset,
VALUE, opt_num+1);
12007ibf_dump_param_keyword(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
12009 const struct rb_iseq_param_keyword *kw = ISEQ_BODY(iseq)->param.keyword;
12012 struct rb_iseq_param_keyword dump_kw = *kw;
12013 int dv_num = kw->num - kw->required_num;
12018 for (i=0; i<kw->num; i++) ids[i] = (
ID)ibf_dump_id(dump, kw->table[i]);
12019 for (i=0; i<dv_num; i++) dvs[i] = (
VALUE)ibf_dump_object(dump, kw->default_values[i]);
12021 dump_kw.table = IBF_W(ids,
ID, kw->num);
12022 dump_kw.default_values = IBF_W(dvs,
VALUE, dv_num);
12023 IBF_W_ALIGN(
struct rb_iseq_param_keyword);
12024 return ibf_dump_write(dump, &dump_kw,
sizeof(
struct rb_iseq_param_keyword) * 1);
12031static const struct rb_iseq_param_keyword *
12032ibf_load_param_keyword(
const struct ibf_load *load, ibf_offset_t param_keyword_offset)
12034 if (param_keyword_offset) {
12035 struct rb_iseq_param_keyword *kw = IBF_R(param_keyword_offset,
struct rb_iseq_param_keyword, 1);
12036 ID *ids = IBF_R(kw->table,
ID, kw->num);
12037 int dv_num = kw->num - kw->required_num;
12038 VALUE *dvs = IBF_R(kw->default_values,
VALUE, dv_num);
12041 for (i=0; i<kw->num; i++) {
12042 ids[i] = ibf_load_id(load, ids[i]);
12044 for (i=0; i<dv_num; i++) {
12045 dvs[i] = ibf_load_object(load, dvs[i]);
12049 kw->default_values = dvs;
12058ibf_dump_insns_info_body(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
12060 ibf_offset_t offset = ibf_dump_pos(dump);
12064 for (i = 0; i < ISEQ_BODY(iseq)->insns_info.size; i++) {
12065 ibf_dump_write_small_value(dump, entries[i].line_no);
12066#ifdef USE_ISEQ_NODE_ID
12067 ibf_dump_write_small_value(dump, entries[i].node_id);
12069 ibf_dump_write_small_value(dump, entries[i].events);
12076ibf_load_insns_info_body(
const struct ibf_load *load, ibf_offset_t body_offset,
unsigned int size)
12078 ibf_offset_t reading_pos = body_offset;
12082 for (i = 0; i < size; i++) {
12083 entries[i].line_no = (int)ibf_load_small_value(load, &reading_pos);
12084#ifdef USE_ISEQ_NODE_ID
12085 entries[i].node_id = (int)ibf_load_small_value(load, &reading_pos);
12087 entries[i].events = (
rb_event_flag_t)ibf_load_small_value(load, &reading_pos);
12094ibf_dump_insns_info_positions(
struct ibf_dump *dump,
const unsigned int *positions,
unsigned int size)
12096 ibf_offset_t offset = ibf_dump_pos(dump);
12098 unsigned int last = 0;
12100 for (i = 0; i < size; i++) {
12101 ibf_dump_write_small_value(dump, positions[i] - last);
12102 last = positions[i];
12108static unsigned int *
12109ibf_load_insns_info_positions(
const struct ibf_load *load, ibf_offset_t positions_offset,
unsigned int size)
12111 ibf_offset_t reading_pos = positions_offset;
12112 unsigned int *positions =
ALLOC_N(
unsigned int, size);
12114 unsigned int last = 0;
12116 for (i = 0; i < size; i++) {
12117 positions[i] = last + (
unsigned int)ibf_load_small_value(load, &reading_pos);
12118 last = positions[i];
12125ibf_dump_local_table(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
12128 const int size = body->local_table_size;
12132 for (i=0; i<size; i++) {
12133 table[i] = ibf_dump_id(dump, body->local_table[i]);
12137 return ibf_dump_write(dump, table,
sizeof(
ID) * size);
12141ibf_load_local_table(
const struct ibf_load *load, ibf_offset_t local_table_offset,
int size)
12144 ID *table = IBF_R(local_table_offset,
ID, size);
12147 for (i=0; i<size; i++) {
12148 table[i] = ibf_load_id(load, table[i]);
12158ibf_dump_catch_table(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
12163 int *iseq_indices =
ALLOCA_N(
int, table->size);
12166 for (i=0; i<table->size; i++) {
12167 iseq_indices[i] = ibf_dump_iseq(dump, table->entries[i].iseq);
12170 const ibf_offset_t offset = ibf_dump_pos(dump);
12172 for (i=0; i<table->size; i++) {
12173 ibf_dump_write_small_value(dump, iseq_indices[i]);
12174 ibf_dump_write_small_value(dump, table->entries[i].type);
12175 ibf_dump_write_small_value(dump, table->entries[i].start);
12176 ibf_dump_write_small_value(dump, table->entries[i].end);
12177 ibf_dump_write_small_value(dump, table->entries[i].cont);
12178 ibf_dump_write_small_value(dump, table->entries[i].sp);
12183 return ibf_dump_pos(dump);
12188ibf_load_catch_table(
const struct ibf_load *load, ibf_offset_t catch_table_offset,
unsigned int size)
12191 struct iseq_catch_table *table = ruby_xmalloc(iseq_catch_table_bytes(size));
12192 table->size = size;
12194 ibf_offset_t reading_pos = catch_table_offset;
12197 for (i=0; i<table->size; i++) {
12198 int iseq_index = (int)ibf_load_small_value(load, &reading_pos);
12199 table->entries[i].type = (
enum rb_catch_type)ibf_load_small_value(load, &reading_pos);
12200 table->entries[i].start = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12201 table->entries[i].end = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12202 table->entries[i].cont = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12203 table->entries[i].sp = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12205 table->entries[i].iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)iseq_index);
12215ibf_dump_ci_entries(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
12218 const unsigned int ci_size = body->ci_size;
12221 ibf_offset_t offset = ibf_dump_pos(dump);
12225 for (i = 0; i < ci_size; i++) {
12228 ibf_dump_write_small_value(dump, ibf_dump_id(dump, vm_ci_mid(ci)));
12229 ibf_dump_write_small_value(dump, vm_ci_flag(ci));
12230 ibf_dump_write_small_value(dump, vm_ci_argc(ci));
12234 int len = kwarg->keyword_len;
12235 ibf_dump_write_small_value(dump,
len);
12236 for (
int j=0; j<
len; j++) {
12237 VALUE keyword = ibf_dump_object(dump, kwarg->keywords[j]);
12238 ibf_dump_write_small_value(dump, keyword);
12242 ibf_dump_write_small_value(dump, 0);
12247 ibf_dump_write_small_value(dump, (
VALUE)-1);
12265static enum rb_id_table_iterator_result
12266store_outer_variable(
ID id,
VALUE val,
void *dump)
12271 pair->name = rb_id2str(
id);
12273 return ID_TABLE_CONTINUE;
12277outer_variable_cmp(
const void *a,
const void *b,
void *arg)
12285ibf_dump_outer_variables(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
12287 struct rb_id_table * ovs = ISEQ_BODY(iseq)->outer_variables;
12289 ibf_offset_t offset = ibf_dump_pos(dump);
12291 size_t size = ovs ? rb_id_table_size(ovs) : 0;
12292 ibf_dump_write_small_value(dump, (
VALUE)size);
12301 rb_id_table_foreach(ovs, store_outer_variable, ovlist);
12303 for (
size_t i = 0; i < size; ++i) {
12304 ID id = ovlist->pairs[i].id;
12305 ID val = ovlist->pairs[i].val;
12306 ibf_dump_write_small_value(dump, ibf_dump_id(dump,
id));
12307 ibf_dump_write_small_value(dump, val);
12316ibf_load_ci_entries(
const struct ibf_load *load,
12317 ibf_offset_t ci_entries_offset,
12318 unsigned int ci_size,
12321 ibf_offset_t reading_pos = ci_entries_offset;
12328 for (i = 0; i < ci_size; i++) {
12329 VALUE mid_index = ibf_load_small_value(load, &reading_pos);
12330 if (mid_index != (
VALUE)-1) {
12331 ID mid = ibf_load_id(load, mid_index);
12332 unsigned int flag = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12333 unsigned int argc = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12336 int kwlen = (int)ibf_load_small_value(load, &reading_pos);
12339 kwarg->references = 0;
12340 kwarg->keyword_len = kwlen;
12341 for (
int j=0; j<kwlen; j++) {
12342 VALUE keyword = ibf_load_small_value(load, &reading_pos);
12343 kwarg->keywords[j] = ibf_load_object(load, keyword);
12347 cds[i].ci = vm_ci_new(mid, flag, argc, kwarg);
12349 cds[i].cc = vm_cc_empty();
12360ibf_load_outer_variables(
const struct ibf_load * load, ibf_offset_t outer_variables_offset)
12362 ibf_offset_t reading_pos = outer_variables_offset;
12366 size_t table_size = (size_t)ibf_load_small_value(load, &reading_pos);
12368 if (table_size > 0) {
12369 tbl = rb_id_table_create(table_size);
12372 for (
size_t i = 0; i < table_size; i++) {
12373 ID key = ibf_load_id(load, (
ID)ibf_load_small_value(load, &reading_pos));
12374 VALUE value = ibf_load_small_value(load, &reading_pos);
12375 if (!key) key = rb_make_temporary_id(i);
12376 rb_id_table_insert(tbl, key, value);
12383ibf_dump_iseq_each(
struct ibf_dump *dump,
const rb_iseq_t *iseq)
12385 assert(dump->current_buffer == &dump->global_buffer);
12387 unsigned int *positions;
12391 const VALUE location_pathobj_index = ibf_dump_object(dump, body->location.pathobj);
12392 const VALUE location_base_label_index = ibf_dump_object(dump, body->location.base_label);
12393 const VALUE location_label_index = ibf_dump_object(dump, body->location.label);
12395#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12396 ibf_offset_t iseq_start = ibf_dump_pos(dump);
12401 buffer.obj_table = ibf_dump_object_table_new();
12402 dump->current_buffer = &buffer;
12405 const ibf_offset_t bytecode_offset = ibf_dump_code(dump, iseq);
12406 const ibf_offset_t bytecode_size = ibf_dump_pos(dump) - bytecode_offset;
12407 const ibf_offset_t param_opt_table_offset = ibf_dump_param_opt_table(dump, iseq);
12408 const ibf_offset_t param_keyword_offset = ibf_dump_param_keyword(dump, iseq);
12409 const ibf_offset_t insns_info_body_offset = ibf_dump_insns_info_body(dump, iseq);
12411 positions = rb_iseq_insns_info_decode_positions(ISEQ_BODY(iseq));
12412 const ibf_offset_t insns_info_positions_offset = ibf_dump_insns_info_positions(dump, positions, body->insns_info.size);
12413 ruby_xfree(positions);
12415 const ibf_offset_t local_table_offset = ibf_dump_local_table(dump, iseq);
12416 const unsigned int catch_table_size = body->catch_table ? body->catch_table->size : 0;
12417 const ibf_offset_t catch_table_offset = ibf_dump_catch_table(dump, iseq);
12418 const int parent_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->parent_iseq);
12419 const int local_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->local_iseq);
12420 const int mandatory_only_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->mandatory_only_iseq);
12421 const ibf_offset_t ci_entries_offset = ibf_dump_ci_entries(dump, iseq);
12422 const ibf_offset_t outer_variables_offset = ibf_dump_outer_variables(dump, iseq);
12424#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12425 ibf_offset_t local_obj_list_offset;
12426 unsigned int local_obj_list_size;
12428 ibf_dump_object_list(dump, &local_obj_list_offset, &local_obj_list_size);
12431 ibf_offset_t body_offset = ibf_dump_pos(dump);
12434 unsigned int param_flags =
12435 (body->
param.flags.has_lead << 0) |
12436 (body->
param.flags.has_opt << 1) |
12437 (body->
param.flags.has_rest << 2) |
12438 (body->
param.flags.has_post << 3) |
12439 (body->
param.flags.has_kw << 4) |
12440 (body->
param.flags.has_kwrest << 5) |
12441 (body->
param.flags.has_block << 6) |
12442 (body->
param.flags.ambiguous_param0 << 7) |
12443 (body->
param.flags.accepts_no_kwarg << 8) |
12444 (body->
param.flags.ruby2_keywords << 9);
12446#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12447# define IBF_BODY_OFFSET(x) (x)
12449# define IBF_BODY_OFFSET(x) (body_offset - (x))
12452 ibf_dump_write_small_value(dump, body->type);
12453 ibf_dump_write_small_value(dump, body->iseq_size);
12454 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(bytecode_offset));
12455 ibf_dump_write_small_value(dump, bytecode_size);
12456 ibf_dump_write_small_value(dump, param_flags);
12457 ibf_dump_write_small_value(dump, body->
param.size);
12458 ibf_dump_write_small_value(dump, body->
param.lead_num);
12459 ibf_dump_write_small_value(dump, body->
param.opt_num);
12460 ibf_dump_write_small_value(dump, body->
param.rest_start);
12461 ibf_dump_write_small_value(dump, body->
param.post_start);
12462 ibf_dump_write_small_value(dump, body->
param.post_num);
12463 ibf_dump_write_small_value(dump, body->
param.block_start);
12464 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(param_opt_table_offset));
12465 ibf_dump_write_small_value(dump, param_keyword_offset);
12466 ibf_dump_write_small_value(dump, location_pathobj_index);
12467 ibf_dump_write_small_value(dump, location_base_label_index);
12468 ibf_dump_write_small_value(dump, location_label_index);
12469 ibf_dump_write_small_value(dump, body->location.first_lineno);
12470 ibf_dump_write_small_value(dump, body->location.node_id);
12471 ibf_dump_write_small_value(dump, body->location.code_location.beg_pos.lineno);
12472 ibf_dump_write_small_value(dump, body->location.code_location.beg_pos.column);
12473 ibf_dump_write_small_value(dump, body->location.code_location.end_pos.lineno);
12474 ibf_dump_write_small_value(dump, body->location.code_location.end_pos.column);
12475 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(insns_info_body_offset));
12476 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(insns_info_positions_offset));
12477 ibf_dump_write_small_value(dump, body->insns_info.size);
12478 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(local_table_offset));
12479 ibf_dump_write_small_value(dump, catch_table_size);
12480 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(catch_table_offset));
12481 ibf_dump_write_small_value(dump, parent_iseq_index);
12482 ibf_dump_write_small_value(dump, local_iseq_index);
12483 ibf_dump_write_small_value(dump, mandatory_only_iseq_index);
12484 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(ci_entries_offset));
12485 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(outer_variables_offset));
12486 ibf_dump_write_small_value(dump, body->variable.flip_count);
12487 ibf_dump_write_small_value(dump, body->local_table_size);
12488 ibf_dump_write_small_value(dump, body->ivc_size);
12489 ibf_dump_write_small_value(dump, body->icvarc_size);
12490 ibf_dump_write_small_value(dump, body->ise_size);
12491 ibf_dump_write_small_value(dump, body->ic_size);
12492 ibf_dump_write_small_value(dump, body->ci_size);
12493 ibf_dump_write_small_value(dump, body->stack_max);
12494 ibf_dump_write_small_value(dump, body->builtin_attrs);
12496#undef IBF_BODY_OFFSET
12498#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12499 ibf_offset_t iseq_length_bytes = ibf_dump_pos(dump);
12501 dump->current_buffer = saved_buffer;
12502 ibf_dump_write(dump, RSTRING_PTR(buffer.str), iseq_length_bytes);
12504 ibf_offset_t offset = ibf_dump_pos(dump);
12505 ibf_dump_write_small_value(dump, iseq_start);
12506 ibf_dump_write_small_value(dump, iseq_length_bytes);
12507 ibf_dump_write_small_value(dump, body_offset);
12509 ibf_dump_write_small_value(dump, local_obj_list_offset);
12510 ibf_dump_write_small_value(dump, local_obj_list_size);
12512 st_free_table(buffer.obj_table);
12516 return body_offset;
12521ibf_load_location_str(
const struct ibf_load *load,
VALUE str_index)
12523 VALUE str = ibf_load_object(load, str_index);
12525 str = rb_fstring(str);
12531ibf_load_iseq_each(
struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
12535 ibf_offset_t reading_pos = offset;
12537#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12539 load->current_buffer = &load->global_buffer;
12541 const ibf_offset_t iseq_start = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12542 const ibf_offset_t iseq_length_bytes = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12543 const ibf_offset_t body_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12546 buffer.buff = load->global_buffer.buff + iseq_start;
12547 buffer.size = iseq_length_bytes;
12548 buffer.obj_list_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12549 buffer.obj_list_size = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12550 buffer.obj_list = pinned_list_new(buffer.obj_list_size);
12552 load->current_buffer = &buffer;
12553 reading_pos = body_offset;
12556#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12557# define IBF_BODY_OFFSET(x) (x)
12559# define IBF_BODY_OFFSET(x) (offset - (x))
12562 const unsigned int type = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12563 const unsigned int iseq_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12564 const ibf_offset_t bytecode_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12565 const ibf_offset_t bytecode_size = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12566 const unsigned int param_flags = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12567 const unsigned int param_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12568 const int param_lead_num = (int)ibf_load_small_value(load, &reading_pos);
12569 const int param_opt_num = (int)ibf_load_small_value(load, &reading_pos);
12570 const int param_rest_start = (int)ibf_load_small_value(load, &reading_pos);
12571 const int param_post_start = (int)ibf_load_small_value(load, &reading_pos);
12572 const int param_post_num = (int)ibf_load_small_value(load, &reading_pos);
12573 const int param_block_start = (int)ibf_load_small_value(load, &reading_pos);
12574 const ibf_offset_t param_opt_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12575 const ibf_offset_t param_keyword_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12576 const VALUE location_pathobj_index = ibf_load_small_value(load, &reading_pos);
12577 const VALUE location_base_label_index = ibf_load_small_value(load, &reading_pos);
12578 const VALUE location_label_index = ibf_load_small_value(load, &reading_pos);
12579 const int location_first_lineno = (int)ibf_load_small_value(load, &reading_pos);
12580 const int location_node_id = (int)ibf_load_small_value(load, &reading_pos);
12581 const int location_code_location_beg_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
12582 const int location_code_location_beg_pos_column = (int)ibf_load_small_value(load, &reading_pos);
12583 const int location_code_location_end_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
12584 const int location_code_location_end_pos_column = (int)ibf_load_small_value(load, &reading_pos);
12585 const ibf_offset_t insns_info_body_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12586 const ibf_offset_t insns_info_positions_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12587 const unsigned int insns_info_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12588 const ibf_offset_t local_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12589 const unsigned int catch_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12590 const ibf_offset_t catch_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12591 const int parent_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
12592 const int local_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
12593 const int mandatory_only_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
12594 const ibf_offset_t ci_entries_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12595 const ibf_offset_t outer_variables_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12596 const rb_snum_t variable_flip_count = (rb_snum_t)ibf_load_small_value(load, &reading_pos);
12597 const unsigned int local_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12599 const unsigned int ivc_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12600 const unsigned int icvarc_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12601 const unsigned int ise_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12602 const unsigned int ic_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12604 const unsigned int ci_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12605 const unsigned int stack_max = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12606 const unsigned int builtin_attrs = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12609 VALUE path = ibf_load_object(load, location_pathobj_index);
12614 realpath = path = rb_fstring(path);
12616 else if (RB_TYPE_P(path,
T_ARRAY)) {
12617 VALUE pathobj = path;
12623 if (!
NIL_P(realpath)) {
12624 if (!RB_TYPE_P(realpath,
T_STRING)) {
12625 rb_raise(rb_eArgError,
"unexpected realpath %"PRIxVALUE
12626 "(%x), path=%+"PRIsVALUE,
12627 realpath,
TYPE(realpath), path);
12629 realpath = rb_fstring(realpath);
12635 rb_iseq_pathobj_set(iseq, path, realpath);
12639 rb_execution_context_t *ec = GET_EC();
12640 VALUE dummy_frame = rb_vm_push_frame_fname(ec, path);
12642#undef IBF_BODY_OFFSET
12644 load_body->type =
type;
12645 load_body->stack_max = stack_max;
12646 load_body->
param.flags.has_lead = (param_flags >> 0) & 1;
12647 load_body->
param.flags.has_opt = (param_flags >> 1) & 1;
12648 load_body->
param.flags.has_rest = (param_flags >> 2) & 1;
12649 load_body->
param.flags.has_post = (param_flags >> 3) & 1;
12650 load_body->
param.flags.has_kw = FALSE;
12651 load_body->
param.flags.has_kwrest = (param_flags >> 5) & 1;
12652 load_body->
param.flags.has_block = (param_flags >> 6) & 1;
12653 load_body->
param.flags.ambiguous_param0 = (param_flags >> 7) & 1;
12654 load_body->
param.flags.accepts_no_kwarg = (param_flags >> 8) & 1;
12655 load_body->
param.flags.ruby2_keywords = (param_flags >> 9) & 1;
12656 load_body->
param.size = param_size;
12657 load_body->
param.lead_num = param_lead_num;
12658 load_body->
param.opt_num = param_opt_num;
12659 load_body->
param.rest_start = param_rest_start;
12660 load_body->
param.post_start = param_post_start;
12661 load_body->
param.post_num = param_post_num;
12662 load_body->
param.block_start = param_block_start;
12663 load_body->local_table_size = local_table_size;
12664 load_body->ci_size = ci_size;
12665 load_body->insns_info.size = insns_info_size;
12667 ISEQ_COVERAGE_SET(iseq,
Qnil);
12668 ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
12669 load_body->variable.flip_count = variable_flip_count;
12670 load_body->variable.script_lines =
Qnil;
12672 load_body->location.first_lineno = location_first_lineno;
12673 load_body->location.node_id = location_node_id;
12674 load_body->location.code_location.beg_pos.lineno = location_code_location_beg_pos_lineno;
12675 load_body->location.code_location.beg_pos.column = location_code_location_beg_pos_column;
12676 load_body->location.code_location.end_pos.lineno = location_code_location_end_pos_lineno;
12677 load_body->location.code_location.end_pos.column = location_code_location_end_pos_column;
12678 load_body->builtin_attrs = builtin_attrs;
12680 load_body->ivc_size = ivc_size;
12681 load_body->icvarc_size = icvarc_size;
12682 load_body->ise_size = ise_size;
12683 load_body->ic_size = ic_size;
12685 if (ISEQ_IS_SIZE(load_body)) {
12689 load_body->is_entries = NULL;
12691 ibf_load_ci_entries(load, ci_entries_offset, ci_size, &load_body->call_data);
12692 load_body->outer_variables = ibf_load_outer_variables(load, outer_variables_offset);
12693 load_body->
param.opt_table = ibf_load_param_opt_table(load, param_opt_table_offset, param_opt_num);
12694 load_body->
param.keyword = ibf_load_param_keyword(load, param_keyword_offset);
12695 load_body->
param.flags.has_kw = (param_flags >> 4) & 1;
12696 load_body->insns_info.body = ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size);
12697 load_body->insns_info.positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size);
12698 load_body->local_table = ibf_load_local_table(load, local_table_offset, local_table_size);
12699 load_body->catch_table = ibf_load_catch_table(load, catch_table_offset, catch_table_size);
12700 load_body->parent_iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)parent_iseq_index);
12701 load_body->local_iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)local_iseq_index);
12702 load_body->mandatory_only_iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)mandatory_only_iseq_index);
12704 ibf_load_code(load, iseq, bytecode_offset, bytecode_size, iseq_size);
12705#if VM_INSN_INFO_TABLE_IMPL == 2
12706 rb_iseq_insns_info_encode_positions(iseq);
12709 rb_iseq_translate_threaded_code(iseq);
12711#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12712 load->current_buffer = &load->global_buffer;
12715 RB_OBJ_WRITE(iseq, &load_body->location.base_label, ibf_load_location_str(load, location_base_label_index));
12716 RB_OBJ_WRITE(iseq, &load_body->location.label, ibf_load_location_str(load, location_label_index));
12718#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12719 load->current_buffer = saved_buffer;
12721 verify_call_cache(iseq);
12724 rb_vm_pop_frame_no_int(ec);
12734ibf_dump_iseq_list_i(st_data_t key, st_data_t val, st_data_t ptr)
12736 const rb_iseq_t *iseq = (
const rb_iseq_t *)key;
12739 ibf_offset_t offset = ibf_dump_iseq_each(args->dump, iseq);
12740 rb_ary_push(args->offset_list,
UINT2NUM(offset));
12742 return ST_CONTINUE;
12748 VALUE offset_list = rb_ary_hidden_new(dump->iseq_table->num_entries);
12752 args.offset_list = offset_list;
12754 st_foreach(dump->iseq_table, ibf_dump_iseq_list_i, (st_data_t)&args);
12757 st_index_t size = dump->iseq_table->num_entries;
12758 ibf_offset_t *offsets =
ALLOCA_N(ibf_offset_t, size);
12760 for (i = 0; i < size; i++) {
12764 ibf_dump_align(dump,
sizeof(ibf_offset_t));
12765 header->iseq_list_offset = ibf_dump_write(dump, offsets,
sizeof(ibf_offset_t) * size);
12766 header->iseq_list_size = (
unsigned int)size;
12769#define IBF_OBJECT_INTERNAL FL_PROMOTED0
12778 unsigned int type: 5;
12779 unsigned int special_const: 1;
12780 unsigned int frozen: 1;
12781 unsigned int internal: 1;
12784enum ibf_object_class_index {
12785 IBF_OBJECT_CLASS_OBJECT,
12786 IBF_OBJECT_CLASS_ARRAY,
12787 IBF_OBJECT_CLASS_STANDARD_ERROR,
12788 IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR,
12789 IBF_OBJECT_CLASS_TYPE_ERROR,
12790 IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR,
12800 long keyval[FLEX_ARY_LEN];
12813 BDIGIT digits[FLEX_ARY_LEN];
12816enum ibf_object_data_type {
12817 IBF_OBJECT_DATA_ENCODING,
12828#define IBF_ALIGNED_OFFSET(align, offset) \
12829 ((((offset) - 1) / (align) + 1) * (align))
12830#define IBF_OBJBODY(type, offset) (const type *)\
12831 ibf_load_check_offset(load, IBF_ALIGNED_OFFSET(RUBY_ALIGNOF(type), offset))
12834ibf_load_check_offset(
const struct ibf_load *load,
size_t offset)
12836 if (offset >= load->current_buffer->size) {
12837 rb_raise(
rb_eIndexError,
"object offset out of range: %"PRIdSIZE, offset);
12839 return load->current_buffer->buff + offset;
12842NORETURN(
static void ibf_dump_object_unsupported(
struct ibf_dump *dump,
VALUE obj));
12845ibf_dump_object_unsupported(
struct ibf_dump *dump,
VALUE obj)
12848 rb_raw_obj_info(buff,
sizeof(buff), obj);
12857 rb_raise(rb_eArgError,
"unsupported");
12864 enum ibf_object_class_index cindex;
12865 if (obj == rb_cObject) {
12866 cindex = IBF_OBJECT_CLASS_OBJECT;
12869 cindex = IBF_OBJECT_CLASS_ARRAY;
12872 cindex = IBF_OBJECT_CLASS_STANDARD_ERROR;
12875 cindex = IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR;
12878 cindex = IBF_OBJECT_CLASS_TYPE_ERROR;
12881 cindex = IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR;
12884 rb_obj_info_dump(obj);
12886 rb_bug(
"unsupported class");
12888 ibf_dump_write_small_value(dump, (
VALUE)cindex);
12894 enum ibf_object_class_index cindex = (
enum ibf_object_class_index)ibf_load_small_value(load, &offset);
12897 case IBF_OBJECT_CLASS_OBJECT:
12899 case IBF_OBJECT_CLASS_ARRAY:
12901 case IBF_OBJECT_CLASS_STANDARD_ERROR:
12903 case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR:
12905 case IBF_OBJECT_CLASS_TYPE_ERROR:
12907 case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR:
12911 rb_raise(rb_eArgError,
"ibf_load_object_class: unknown class (%d)", (
int)cindex);
12919 (void)IBF_W(&dbl,
double, 1);
12925 const double *dblp = IBF_OBJBODY(
double, offset);
12932 long encindex = (long)rb_enc_get_index(obj);
12933 long len = RSTRING_LEN(obj);
12934 const char *ptr = RSTRING_PTR(obj);
12936 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
12937 rb_encoding *enc = rb_enc_from_index((
int)encindex);
12938 const char *enc_name = rb_enc_name(enc);
12939 encindex = RUBY_ENCINDEX_BUILTIN_MAX + ibf_dump_object(dump,
rb_str_new2(enc_name));
12942 ibf_dump_write_small_value(dump, encindex);
12943 ibf_dump_write_small_value(dump,
len);
12944 IBF_WP(ptr,
char,
len);
12950 ibf_offset_t reading_pos = offset;
12952 int encindex = (int)ibf_load_small_value(load, &reading_pos);
12953 const long len = (long)ibf_load_small_value(load, &reading_pos);
12954 const char *ptr = load->current_buffer->buff + reading_pos;
12956 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
12957 VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX);
12958 encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str));
12962 if (header->frozen && !header->internal) {
12966 str = rb_enc_str_new(ptr,
len, rb_enc_from_index(encindex));
12968 if (header->internal) rb_obj_hide(str);
12969 if (header->frozen) str = rb_fstring(str);
12980 regexp.srcstr = (long)ibf_dump_object(dump, srcstr);
12982 ibf_dump_write_byte(dump, (
unsigned char)regexp.option);
12983 ibf_dump_write_small_value(dump, regexp.srcstr);
12990 regexp.option = ibf_load_byte(load, &offset);
12991 regexp.srcstr = ibf_load_small_value(load, &offset);
12993 VALUE srcstr = ibf_load_object(load, regexp.srcstr);
12994 VALUE reg = rb_reg_compile(srcstr, (
int)regexp.option, NULL, 0);
12996 if (header->internal) rb_obj_hide(reg);
12997 if (header->frozen) rb_obj_freeze(reg);
13006 ibf_dump_write_small_value(dump,
len);
13007 for (i=0; i<
len; i++) {
13008 long index = (long)ibf_dump_object(dump,
RARRAY_AREF(obj, i));
13009 ibf_dump_write_small_value(dump, index);
13016 ibf_offset_t reading_pos = offset;
13018 const long len = (long)ibf_load_small_value(load, &reading_pos);
13020 VALUE ary = header->internal ? rb_ary_hidden_new(
len) : rb_ary_new_capa(
len);
13023 for (i=0; i<
len; i++) {
13024 const VALUE index = ibf_load_small_value(load, &reading_pos);
13025 rb_ary_push(ary, ibf_load_object(load, index));
13028 if (header->frozen) rb_obj_freeze(ary);
13034ibf_dump_object_hash_i(st_data_t key, st_data_t val, st_data_t ptr)
13038 VALUE key_index = ibf_dump_object(dump, (
VALUE)key);
13039 VALUE val_index = ibf_dump_object(dump, (
VALUE)val);
13041 ibf_dump_write_small_value(dump, key_index);
13042 ibf_dump_write_small_value(dump, val_index);
13043 return ST_CONTINUE;
13050 ibf_dump_write_small_value(dump, (
VALUE)
len);
13058 long len = (long)ibf_load_small_value(load, &offset);
13059 VALUE obj = rb_hash_new_with_size(
len);
13062 for (i = 0; i <
len; i++) {
13063 VALUE key_index = ibf_load_small_value(load, &offset);
13064 VALUE val_index = ibf_load_small_value(load, &offset);
13066 VALUE key = ibf_load_object(load, key_index);
13067 VALUE val = ibf_load_object(load, val_index);
13068 rb_hash_aset(obj, key, val);
13070 rb_hash_rehash(obj);
13072 if (header->internal) rb_obj_hide(obj);
13073 if (header->frozen) rb_obj_freeze(obj);
13086 range.class_index = 0;
13089 range.beg = (long)ibf_dump_object(dump, beg);
13090 range.end = (long)ibf_dump_object(dump, end);
13096 rb_raise(
rb_eNotImpError,
"ibf_dump_object_struct: unsupported class %"PRIsVALUE,
13105 VALUE beg = ibf_load_object(load, range->beg);
13106 VALUE end = ibf_load_object(load, range->end);
13108 if (header->internal) rb_obj_hide(obj);
13109 if (header->frozen) rb_obj_freeze(obj);
13116 ssize_t
len = BIGNUM_LEN(obj);
13117 ssize_t slen = BIGNUM_SIGN(obj) > 0 ?
len :
len * -1;
13118 BDIGIT *d = BIGNUM_DIGITS(obj);
13120 (void)IBF_W(&slen, ssize_t, 1);
13121 IBF_WP(d, BDIGIT,
len);
13128 int sign = bignum->slen > 0;
13129 ssize_t
len = sign > 0 ? bignum->slen : -1 * bignum->slen;
13130 const int big_unpack_flags =
13133 VALUE obj = rb_integer_unpack(bignum->digits,
len,
sizeof(BDIGIT), 0,
13136 if (header->internal) rb_obj_hide(obj);
13137 if (header->frozen) rb_obj_freeze(obj);
13144 if (rb_data_is_encoding(obj)) {
13145 rb_encoding *enc = rb_to_encoding(obj);
13146 const char *name = rb_enc_name(enc);
13147 long len = strlen(name) + 1;
13149 data[0] = IBF_OBJECT_DATA_ENCODING;
13151 (void)IBF_W(data,
long, 2);
13152 IBF_WP(name,
char,
len);
13155 ibf_dump_object_unsupported(dump, obj);
13162 const long *body = IBF_OBJBODY(
long, offset);
13163 const enum ibf_object_data_type
type = (
enum ibf_object_data_type)body[0];
13165 const char *data = (
const char *)&body[2];
13168 case IBF_OBJECT_DATA_ENCODING:
13170 VALUE encobj = rb_enc_from_encoding(rb_enc_find(data));
13175 return ibf_load_object_unsupported(load, header, offset);
13179ibf_dump_object_complex_rational(
struct ibf_dump *dump,
VALUE obj)
13182 data[0] = (long)ibf_dump_object(dump, RCOMPLEX(obj)->real);
13183 data[1] = (long)ibf_dump_object(dump, RCOMPLEX(obj)->imag);
13185 (void)IBF_W(data,
long, 2);
13189ibf_load_object_complex_rational(
const struct ibf_load *load,
const struct ibf_object_header *header, ibf_offset_t offset)
13192 VALUE a = ibf_load_object(load, nums->a);
13193 VALUE b = ibf_load_object(load, nums->b);
13195 rb_complex_new(a, b) : rb_rational_new(a, b);
13197 if (header->internal) rb_obj_hide(obj);
13198 if (header->frozen) rb_obj_freeze(obj);
13205 ibf_dump_object_string(dump,
rb_sym2str(obj));
13211 ibf_offset_t reading_pos = offset;
13213 int encindex = (int)ibf_load_small_value(load, &reading_pos);
13214 const long len = (long)ibf_load_small_value(load, &reading_pos);
13215 const char *ptr = load->current_buffer->buff + reading_pos;
13217 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
13218 VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX);
13219 encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str));
13222 ID id = rb_intern3(ptr,
len, rb_enc_from_index(encindex));
13226typedef void (*ibf_dump_object_function)(
struct ibf_dump *dump,
VALUE obj);
13227static const ibf_dump_object_function dump_object_functions[
RUBY_T_MASK+1] = {
13228 ibf_dump_object_unsupported,
13229 ibf_dump_object_unsupported,
13230 ibf_dump_object_class,
13231 ibf_dump_object_unsupported,
13232 ibf_dump_object_float,
13233 ibf_dump_object_string,
13234 ibf_dump_object_regexp,
13235 ibf_dump_object_array,
13236 ibf_dump_object_hash,
13237 ibf_dump_object_struct,
13238 ibf_dump_object_bignum,
13239 ibf_dump_object_unsupported,
13240 ibf_dump_object_data,
13241 ibf_dump_object_unsupported,
13242 ibf_dump_object_complex_rational,
13243 ibf_dump_object_complex_rational,
13244 ibf_dump_object_unsupported,
13245 ibf_dump_object_unsupported,
13246 ibf_dump_object_unsupported,
13247 ibf_dump_object_unsupported,
13248 ibf_dump_object_symbol,
13249 ibf_dump_object_unsupported,
13250 ibf_dump_object_unsupported,
13251 ibf_dump_object_unsupported,
13252 ibf_dump_object_unsupported,
13253 ibf_dump_object_unsupported,
13254 ibf_dump_object_unsupported,
13255 ibf_dump_object_unsupported,
13256 ibf_dump_object_unsupported,
13257 ibf_dump_object_unsupported,
13258 ibf_dump_object_unsupported,
13259 ibf_dump_object_unsupported,
13265 unsigned char byte =
13266 (header.type << 0) |
13267 (header.special_const << 5) |
13268 (header.frozen << 6) |
13269 (header.internal << 7);
13275ibf_load_object_object_header(const struct
ibf_load *load, ibf_offset_t *offset)
13277 unsigned char byte = ibf_load_byte(load, offset);
13280 header.type = (
byte >> 0) & 0x1f;
13281 header.special_const = (
byte >> 5) & 0x01;
13282 header.frozen = (
byte >> 6) & 0x01;
13283 header.internal = (
byte >> 7) & 0x01;
13292 ibf_offset_t current_offset;
13293 IBF_ZERO(obj_header);
13294 obj_header.type =
TYPE(obj);
13296 IBF_W_ALIGN(ibf_offset_t);
13297 current_offset = ibf_dump_pos(dump);
13302 obj_header.special_const = TRUE;
13303 obj_header.frozen = TRUE;
13304 obj_header.internal = TRUE;
13305 ibf_dump_object_object_header(dump, obj_header);
13306 ibf_dump_write_small_value(dump, obj);
13310 obj_header.special_const = FALSE;
13312 ibf_dump_object_object_header(dump, obj_header);
13313 (*dump_object_functions[obj_header.type])(dump, obj);
13316 return current_offset;
13320static const ibf_load_object_function load_object_functions[
RUBY_T_MASK+1] = {
13321 ibf_load_object_unsupported,
13322 ibf_load_object_unsupported,
13323 ibf_load_object_class,
13324 ibf_load_object_unsupported,
13325 ibf_load_object_float,
13326 ibf_load_object_string,
13327 ibf_load_object_regexp,
13328 ibf_load_object_array,
13329 ibf_load_object_hash,
13330 ibf_load_object_struct,
13331 ibf_load_object_bignum,
13332 ibf_load_object_unsupported,
13333 ibf_load_object_data,
13334 ibf_load_object_unsupported,
13335 ibf_load_object_complex_rational,
13336 ibf_load_object_complex_rational,
13337 ibf_load_object_unsupported,
13338 ibf_load_object_unsupported,
13339 ibf_load_object_unsupported,
13340 ibf_load_object_unsupported,
13341 ibf_load_object_symbol,
13342 ibf_load_object_unsupported,
13343 ibf_load_object_unsupported,
13344 ibf_load_object_unsupported,
13345 ibf_load_object_unsupported,
13346 ibf_load_object_unsupported,
13347 ibf_load_object_unsupported,
13348 ibf_load_object_unsupported,
13349 ibf_load_object_unsupported,
13350 ibf_load_object_unsupported,
13351 ibf_load_object_unsupported,
13352 ibf_load_object_unsupported,
13356ibf_load_object(
const struct ibf_load *load,
VALUE object_index)
13358 if (object_index == 0) {
13362 VALUE obj = pinned_list_fetch(load->current_buffer->obj_list, (
long)object_index);
13364 ibf_offset_t *offsets = (ibf_offset_t *)(load->current_buffer->obj_list_offset + load->current_buffer->buff);
13365 ibf_offset_t offset = offsets[object_index];
13366 const struct ibf_object_header header = ibf_load_object_object_header(load, &offset);
13369 fprintf(stderr,
"ibf_load_object: list=%#x offsets=%p offset=%#x\n",
13370 load->current_buffer->obj_list_offset, (
void *)offsets, offset);
13371 fprintf(stderr,
"ibf_load_object: type=%#x special=%d frozen=%d internal=%d\n",
13372 header.type, header.special_const, header.frozen, header.internal);
13374 if (offset >= load->current_buffer->size) {
13375 rb_raise(
rb_eIndexError,
"object offset out of range: %u", offset);
13378 if (header.special_const) {
13379 ibf_offset_t reading_pos = offset;
13381 obj = ibf_load_small_value(load, &reading_pos);
13384 obj = (*load_object_functions[header.type])(load, &header, offset);
13387 pinned_list_store(load->current_buffer->obj_list, (
long)object_index, obj);
13390 fprintf(stderr,
"ibf_load_object: index=%#"PRIxVALUE
" obj=%#"PRIxVALUE
"\n",
13391 object_index, obj);
13404ibf_dump_object_list_i(st_data_t key, st_data_t val, st_data_t ptr)
13409 ibf_offset_t offset = ibf_dump_object_object(args->dump, obj);
13410 rb_ary_push(args->offset_list,
UINT2NUM(offset));
13412 return ST_CONTINUE;
13416ibf_dump_object_list(
struct ibf_dump *dump, ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size)
13418 st_table *obj_table = dump->current_buffer->obj_table;
13419 VALUE offset_list = rb_ary_hidden_new(obj_table->num_entries);
13423 args.offset_list = offset_list;
13425 st_foreach(obj_table, ibf_dump_object_list_i, (st_data_t)&args);
13427 IBF_W_ALIGN(ibf_offset_t);
13428 *obj_list_offset = ibf_dump_pos(dump);
13430 st_index_t size = obj_table->num_entries;
13433 for (i=0; i<size; i++) {
13438 *obj_list_size = (
unsigned int)size;
13442ibf_dump_mark(
void *ptr)
13445 rb_gc_mark(dump->global_buffer.str);
13447 rb_mark_set(dump->global_buffer.obj_table);
13448 rb_mark_set(dump->iseq_table);
13452ibf_dump_free(
void *ptr)
13455 if (dump->global_buffer.obj_table) {
13456 st_free_table(dump->global_buffer.obj_table);
13457 dump->global_buffer.obj_table = 0;
13459 if (dump->iseq_table) {
13460 st_free_table(dump->iseq_table);
13461 dump->iseq_table = 0;
13466ibf_dump_memsize(
const void *ptr)
13470 if (dump->iseq_table) size += st_memsize(dump->iseq_table);
13471 if (dump->global_buffer.obj_table) size += st_memsize(dump->global_buffer.obj_table);
13477 {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
13478 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE
13484 dump->global_buffer.obj_table = NULL;
13485 dump->iseq_table = NULL;
13488 dump->global_buffer.obj_table = ibf_dump_object_table_new();
13489 dump->iseq_table = st_init_numtable();
13491 dump->current_buffer = &dump->global_buffer;
13495rb_iseq_ibf_dump(
const rb_iseq_t *iseq,
VALUE opt)
13502 if (ISEQ_BODY(iseq)->parent_iseq != NULL ||
13503 ISEQ_BODY(iseq)->local_iseq != iseq) {
13506 if (
RTEST(ISEQ_COVERAGE(iseq))) {
13511 ibf_dump_setup(dump, dump_obj);
13513 ibf_dump_write(dump, &header,
sizeof(header));
13514 ibf_dump_iseq(dump, iseq);
13516 header.magic[0] =
'Y';
13517 header.magic[1] =
'A';
13518 header.magic[2] =
'R';
13519 header.magic[3] =
'B';
13520 header.major_version = IBF_MAJOR_VERSION;
13521 header.minor_version = IBF_MINOR_VERSION;
13522 header.endian = IBF_ENDIAN_MARK;
13524 ibf_dump_iseq_list(dump, &header);
13525 ibf_dump_object_list(dump, &header.global_object_list_offset, &header.global_object_list_size);
13526 header.size = ibf_dump_pos(dump);
13529 VALUE opt_str = opt;
13532 ibf_dump_write(dump, ptr, header.extra_size);
13535 header.extra_size = 0;
13538 ibf_dump_overwrite(dump, &header,
sizeof(header), 0);
13540 str = dump->global_buffer.str;
13545static const ibf_offset_t *
13546ibf_iseq_list(
const struct ibf_load *load)
13548 return (
const ibf_offset_t *)(load->global_buffer.buff + load->header->iseq_list_offset);
13552rb_ibf_load_iseq_complete(rb_iseq_t *iseq)
13555 rb_iseq_t *prev_src_iseq = load->iseq;
13556 ibf_offset_t offset = ibf_iseq_list(load)[iseq->aux.loader.index];
13559 fprintf(stderr,
"rb_ibf_load_iseq_complete: index=%#x offset=%#x size=%#x\n",
13560 iseq->aux.loader.index, offset,
13561 load->header->size);
13563 ibf_load_iseq_each(load, iseq, offset);
13564 ISEQ_COMPILE_DATA_CLEAR(iseq);
13566 rb_iseq_init_trace(iseq);
13567 load->iseq = prev_src_iseq;
13572rb_iseq_complete(
const rb_iseq_t *iseq)
13574 rb_ibf_load_iseq_complete((rb_iseq_t *)iseq);
13580ibf_load_iseq(
const struct ibf_load *load,
const rb_iseq_t *index_iseq)
13582 int iseq_index = (int)(
VALUE)index_iseq;
13585 fprintf(stderr,
"ibf_load_iseq: index_iseq=%p iseq_list=%p\n",
13586 (
void *)index_iseq, (
void *)load->iseq_list);
13588 if (iseq_index == -1) {
13592 VALUE iseqv = pinned_list_fetch(load->iseq_list, iseq_index);
13595 fprintf(stderr,
"ibf_load_iseq: iseqv=%p\n", (
void *)iseqv);
13598 return (rb_iseq_t *)iseqv;
13601 rb_iseq_t *iseq = iseq_imemo_alloc();
13603 fprintf(stderr,
"ibf_load_iseq: new iseq=%p\n", (
void *)iseq);
13606 iseq->aux.loader.obj = load->loader_obj;
13607 iseq->aux.loader.index = iseq_index;
13609 fprintf(stderr,
"ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n",
13610 (
void *)iseq, (
void *)load->loader_obj, iseq_index);
13612 pinned_list_store(load->iseq_list, iseq_index, (
VALUE)iseq);
13614 if (!USE_LAZY_LOAD || GET_VM()->builtin_function_table) {
13616 fprintf(stderr,
"ibf_load_iseq: loading iseq=%p\n", (
void *)iseq);
13618 rb_ibf_load_iseq_complete(iseq);
13622 fprintf(stderr,
"ibf_load_iseq: iseq=%p loaded %p\n",
13623 (
void *)iseq, (
void *)load->iseq);
13631ibf_load_setup_bytes(
struct ibf_load *load,
VALUE loader_obj,
const char *bytes,
size_t size)
13634 load->loader_obj = loader_obj;
13635 load->global_buffer.buff = bytes;
13636 load->header = header;
13637 load->global_buffer.size = header->size;
13638 load->global_buffer.obj_list_offset = header->global_object_list_offset;
13639 load->global_buffer.obj_list_size = header->global_object_list_size;
13640 RB_OBJ_WRITE(loader_obj, &load->iseq_list, pinned_list_new(header->iseq_list_size));
13641 RB_OBJ_WRITE(loader_obj, &load->global_buffer.obj_list, pinned_list_new(load->global_buffer.obj_list_size));
13644 load->current_buffer = &load->global_buffer;
13646 if (size < header->size) {
13649 if (strncmp(header->magic,
"YARB", 4) != 0) {
13652 if (header->major_version != IBF_MAJOR_VERSION ||
13653 header->minor_version != IBF_MINOR_VERSION) {
13655 header->major_version, header->minor_version, IBF_MAJOR_VERSION, IBF_MINOR_VERSION);
13657 if (header->endian != IBF_ENDIAN_MARK) {
13663 if (header->iseq_list_offset %
RUBY_ALIGNOF(ibf_offset_t)) {
13664 rb_raise(rb_eArgError,
"unaligned iseq list offset: %u",
13665 header->iseq_list_offset);
13667 if (load->global_buffer.obj_list_offset %
RUBY_ALIGNOF(ibf_offset_t)) {
13668 rb_raise(rb_eArgError,
"unaligned object list offset: %u",
13669 load->global_buffer.obj_list_offset);
13680 if (USE_LAZY_LOAD) {
13681 str =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
13684 ibf_load_setup_bytes(load, loader_obj,
StringValuePtr(str), RSTRING_LEN(str));
13689ibf_loader_mark(
void *ptr)
13692 rb_gc_mark(load->str);
13693 rb_gc_mark(load->iseq_list);
13694 rb_gc_mark(load->global_buffer.obj_list);
13698ibf_loader_free(
void *ptr)
13705ibf_loader_memsize(
const void *ptr)
13712 {ibf_loader_mark, ibf_loader_free, ibf_loader_memsize,},
13713 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
13717rb_iseq_ibf_load(
VALUE str)
13723 ibf_load_setup(load, loader_obj, str);
13724 iseq = ibf_load_iseq(load, 0);
13731rb_iseq_ibf_load_bytes(
const char *bytes,
size_t size)
13737 ibf_load_setup_bytes(load, loader_obj, bytes, size);
13738 iseq = ibf_load_iseq(load, 0);
13745rb_iseq_ibf_load_extra_data(
VALUE str)
13751 ibf_load_setup(load, loader_obj, str);
13752 extra_str =
rb_str_new(load->global_buffer.buff + load->header->size, load->header->extra_size);
13757#include "prism_compile.c"
#define RUBY_ASSERT(expr)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_ALIGNOF
Wraps (or simulates) alignof.
#define RUBY_EVENT_END
Encountered an end of a class clause.
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
#define RUBY_EVENT_B_RETURN
Encountered a next statement.
#define RUBY_EVENT_CLASS
Encountered a new class.
#define RUBY_EVENT_NONE
No events.
#define RUBY_EVENT_LINE
Encountered a new line.
#define RUBY_EVENT_RETURN
Encountered a return statement.
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
#define RUBY_EVENT_B_CALL
Encountered an yield statement.
uint32_t rb_event_flag_t
Represents event(s).
#define RUBY_EVENT_CALL
A method, written in Ruby, is called.
#define RUBY_EVENT_RESCUE
Encountered a rescue statement.
#define rb_str_new2
Old name of rb_str_new_cstr.
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
#define TYPE(_)
Old name of rb_type.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define NUM2LL
Old name of RB_NUM2LL.
#define REALLOC_N
Old name of RB_REALLOC_N.
#define ALLOCV
Old name of RB_ALLOCV.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define T_STRING
Old name of RUBY_T_STRING.
#define xfree
Old name of ruby_xfree.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define T_NIL
Old name of RUBY_T_NIL.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define T_FLOAT
Old name of RUBY_T_FLOAT.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SYM2ID
Old name of RB_SYM2ID.
#define FIX2UINT
Old name of RB_FIX2UINT.
#define ZALLOC
Old name of RB_ZALLOC.
#define CLASS_OF
Old name of rb_class_of.
#define FIXABLE
Old name of RB_FIXABLE.
#define xmalloc
Old name of ruby_xmalloc.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2INT
Old name of RB_FIX2INT.
#define NUM2UINT
Old name of RB_NUM2UINT.
#define ZALLOC_N
Old name of RB_ZALLOC_N.
#define ASSUME
Old name of RBIMPL_ASSUME.
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
#define T_HASH
Old name of RUBY_T_HASH.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define FL_SET
Old name of RB_FL_SET.
#define Qtrue
Old name of RUBY_Qtrue.
#define NUM2INT
Old name of RB_NUM2INT.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
#define DBL2NUM
Old name of rb_float_new.
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
#define FL_TEST
Old name of RB_FL_TEST.
#define FL_FREEZE
Old name of RUBY_FL_FREEZE.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FL_UNSET
Old name of RB_FL_UNSET.
#define UINT2NUM
Old name of RB_UINT2NUM.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define CONST_ID
Old name of RUBY_CONST_ID.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
#define T_REGEXP
Old name of RUBY_T_REGEXP.
#define ruby_debug
This variable controls whether the interpreter is in debug mode.
VALUE rb_eNotImpError
NotImplementedError exception.
VALUE rb_eStandardError
StandardError exception.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eNoMatchingPatternError
NoMatchingPatternError exception.
void rb_exc_fatal(VALUE mesg)
Raises a fatal error in the current thread.
VALUE rb_eRuntimeError
RuntimeError exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
VALUE rb_eNoMatchingPatternKeyError
NoMatchingPatternKeyError exception.
VALUE rb_eIndexError
IndexError exception.
VALUE rb_eSyntaxError
SyntaxError exception.
VALUE rb_cArray
Array class.
VALUE rb_cNumeric
Numeric class.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_cRange
Range class.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it returns a "f"string.
#define INTEGER_PACK_NATIVE_BYTE_ORDER
Means either INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST, depending on the host processor'...
#define INTEGER_PACK_NEGATIVE
Interprets the input as a signed negative number (unpack only).
#define INTEGER_PACK_LSWORD_FIRST
Stores/interprets the least significant word as the first word.
int rb_is_const_id(ID id)
Classifies the given ID, then sees if it is a constant.
int rb_is_attrset_id(ID id)
Classifies the given ID, then sees if it is an attribute writer.
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Deconstructs a range into its components.
VALUE rb_range_new(VALUE beg, VALUE end, int excl)
Creates a new Range.
int rb_reg_options(VALUE re)
Queries the options of the passed regular expression.
VALUE rb_sym_to_s(VALUE sym)
This is an rb_sym2str() + rb_str_dup() combo.
VALUE rb_str_tmp_new(long len)
Allocates a "temporary" string.
int rb_str_hash_cmp(VALUE str1, VALUE str2)
Compares two strings.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
st_index_t rb_str_hash(VALUE str)
Calculates a hash value of a string.
int rb_str_cmp(VALUE lhs, VALUE rhs)
Compares two strings, as in strcmp(3).
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
VALUE rb_str_freeze(VALUE str)
This is the implementation of String#freeze.
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
VALUE rb_sym2str(VALUE id)
Identical to rb_id2str(), except it takes an instance of rb_cSymbol rather than an ID.
ID rb_sym2id(VALUE obj)
Converts an instance of rb_cSymbol into an ID.
int len
Length of the buffer.
#define DECIMAL_SIZE_OF(expr)
An approximation of decimal representation size.
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
#define rb_long2int
Just another name of rb_long2int_inline.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define ALLOCA_N(type, n)
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define RB_ALLOCV(v, n)
Identical to RB_ALLOCV_N(), except that it allocates a number of bytes and returns a void* .
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_hash_foreach(VALUE q, int_type *w, VALUE e)
Iteration over the given hash.
#define RBIMPL_ATTR_NORETURN()
Wraps (or simulates) [[noreturn]]
struct pm_parser pm_parser_t
The parser used to parse Ruby source.
#define RARRAY_LEN
Just another name of rb_array_len.
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
#define RARRAY_AREF(a, i)
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
#define Data_Wrap_Struct(klass, mark, free, sval)
Converts sval, a pointer to your struct, into a Ruby object.
#define DATA_PTR(obj)
Convenient getter macro.
#define RUBY_DEFAULT_FREE
This is a value you can set to RData::dfree.
#define RHASH_SIZE(h)
Queries the size of the hash.
static VALUE RREGEXP_SRC(VALUE rexp)
Convenient getter function.
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
static int RSTRING_LENINT(VALUE str)
Identical to RSTRING_LEN(), except it differs for the return type.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#define RTYPEDDATA_DATA(v)
Convenient getter macro.
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
struct rb_data_type_struct rb_data_type_t
This is the struct that holds necessary info for a struct.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
void rb_p(VALUE obj)
Inspects an object.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Internal header for Complex.
Internal header for Rational.
const ID * segments
A null-terminated list of ids, used to represent a constant's path idNULL is used to represent the ::...
struct rb_iseq_constant_body::@000024342312237062266020177166377106262102236123 param
parameter information
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
@ RUBY_T_MASK
Bitmask of ruby_value_type.