12#include "ruby/internal/config.h"
22#include "internal/array.h"
23#include "internal/compile.h"
24#include "internal/coverage.h"
25#include "internal/complex.h"
26#include "internal/encoding.h"
27#include "internal/error.h"
28#include "internal/gc.h"
29#include "internal/hash.h"
30#include "internal/io.h"
31#include "internal/numeric.h"
32#include "internal/object.h"
33#include "internal/rational.h"
34#include "internal/re.h"
35#include "internal/ruby_parser.h"
36#include "internal/symbol.h"
37#include "internal/thread.h"
38#include "internal/variable.h"
44#include "vm_callinfo.h"
50#include "insns_info.inc"
52#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
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))
217#define NEW_CHILD_ISEQ_WITH_CALLBACK(callback_func, name, type, line_no) \
218 new_child_iseq_with_callback(iseq, (callback_func), (name), iseq, (type), (line_no))
221#define ADD_SEQ(seq1, seq2) \
222 APPEND_LIST((seq1), (seq2))
225#define ADD_INSN(seq, line_node, insn) \
226 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 0))
229#define ADD_SYNTHETIC_INSN(seq, line_no, node_id, insn) \
230 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line_no), (node_id), BIN(insn), 0))
233#define INSERT_BEFORE_INSN(next, line_no, node_id, insn) \
234 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, line_no, node_id, BIN(insn), 0))
237#define INSERT_AFTER_INSN(prev, line_no, node_id, insn) \
238 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, line_no, node_id, BIN(insn), 0))
241#define ADD_INSN1(seq, line_node, insn, op1) \
242 ADD_ELEM((seq), (LINK_ELEMENT *) \
243 new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 1, (VALUE)(op1)))
246#define INSERT_BEFORE_INSN1(next, line_no, node_id, insn, op1) \
247 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) \
248 new_insn_body(iseq, line_no, node_id, BIN(insn), 1, (VALUE)(op1)))
251#define INSERT_AFTER_INSN1(prev, line_no, node_id, insn, op1) \
252 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) \
253 new_insn_body(iseq, line_no, node_id, BIN(insn), 1, (VALUE)(op1)))
255#define LABEL_REF(label) ((label)->refcnt++)
258#define ADD_INSNL(seq, line_node, insn, label) (ADD_INSN1(seq, line_node, insn, label), LABEL_REF(label))
260#define ADD_INSN2(seq, line_node, insn, op1, op2) \
261 ADD_ELEM((seq), (LINK_ELEMENT *) \
262 new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
264#define ADD_INSN3(seq, line_node, insn, op1, op2, op3) \
265 ADD_ELEM((seq), (LINK_ELEMENT *) \
266 new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
269#define ADD_SEND(seq, line_node, id, argc) \
270 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL)
272#define ADD_SEND_WITH_FLAG(seq, line_node, id, argc, flag) \
273 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)(flag), NULL)
275#define ADD_SEND_WITH_BLOCK(seq, line_node, id, argc, block) \
276 ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(0), NULL)
278#define ADD_CALL_RECEIVER(seq, line_node) \
279 ADD_INSN((seq), (line_node), putself)
281#define ADD_CALL(seq, line_node, id, argc) \
282 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
284#define ADD_CALL_WITH_BLOCK(seq, line_node, id, argc, block) \
285 ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
287#define ADD_SEND_R(seq, line_node, id, argc, block, flag, keywords) \
288 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, nd_line(line_node), nd_node_id(line_node), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
290#define ADD_TRACE(seq, event) \
291 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), 0))
292#define ADD_TRACE_WITH_DATA(seq, event, data) \
293 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), (data)))
295static void iseq_add_getlocal(
rb_iseq_t *iseq,
LINK_ANCHOR *
const seq,
const NODE *
const line_node,
int idx,
int level);
296static void iseq_add_setlocal(
rb_iseq_t *iseq,
LINK_ANCHOR *
const seq,
const NODE *
const line_node,
int idx,
int level);
298#define ADD_GETLOCAL(seq, line_node, idx, level) iseq_add_getlocal(iseq, (seq), (line_node), (idx), (level))
299#define ADD_SETLOCAL(seq, line_node, idx, level) iseq_add_setlocal(iseq, (seq), (line_node), (idx), (level))
302#define ADD_LABEL(seq, label) \
303 ADD_ELEM((seq), (LINK_ELEMENT *) (label))
305#define APPEND_LABEL(seq, before, label) \
306 APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label))
308#define ADD_ADJUST(seq, line_node, label) \
309 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), nd_line(line_node)))
311#define ADD_ADJUST_RESTORE(seq, label) \
312 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1))
314#define LABEL_UNREMOVABLE(label) \
315 ((label) ? (LABEL_REF(label), (label)->unremovable=1) : 0)
316#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \
317 VALUE _e = rb_ary_new3(5, (type), \
318 (VALUE)(ls) | 1, (VALUE)(le) | 1, \
319 (VALUE)(iseqv), (VALUE)(lc) | 1); \
320 LABEL_UNREMOVABLE(ls); \
323 if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) \
324 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, rb_ary_hidden_new(3)); \
325 rb_ary_push(ISEQ_COMPILE_DATA(iseq)->catch_table_ary, freeze_hide_obj(_e)); \
329#define COMPILE(anchor, desc, node) \
330 (debug_compile("== " desc "\n", \
331 iseq_compile_each(iseq, (anchor), (node), 0)))
334#define COMPILE_POPPED(anchor, desc, node) \
335 (debug_compile("== " desc "\n", \
336 iseq_compile_each(iseq, (anchor), (node), 1)))
339#define COMPILE_(anchor, desc, node, popped) \
340 (debug_compile("== " desc "\n", \
341 iseq_compile_each(iseq, (anchor), (node), (popped))))
343#define COMPILE_RECV(anchor, desc, node, recv) \
344 (private_recv_p(node) ? \
345 (ADD_INSN(anchor, node, putself), VM_CALL_FCALL) : \
346 COMPILE(anchor, desc, recv) ? 0 : -1)
348#define OPERAND_AT(insn, idx) \
349 (((INSN*)(insn))->operands[(idx)])
351#define INSN_OF(insn) \
352 (((INSN*)(insn))->insn_id)
354#define IS_INSN(link) ((link)->type == ISEQ_ELEMENT_INSN)
355#define IS_LABEL(link) ((link)->type == ISEQ_ELEMENT_LABEL)
356#define IS_ADJUST(link) ((link)->type == ISEQ_ELEMENT_ADJUST)
357#define IS_TRACE(link) ((link)->type == ISEQ_ELEMENT_TRACE)
358#define IS_INSN_ID(iobj, insn) (INSN_OF(iobj) == BIN(insn))
359#define IS_NEXT_INSN_ID(link, insn) \
360 ((link)->next && IS_INSN((link)->next) && IS_INSN_ID((link)->next, insn))
365 if (!IS_INSN(link)) {
369 enum ruby_vminsn_type
type = INSN_OF(link);
372 type == BIN(putobject) ||
373 type == BIN(putspecialobject) ||
374 type == BIN(putnil) ||
375 type == BIN(putself) ||
376 type == BIN(duphash) ||
377 type == BIN(getinstancevariable) ||
378 type == BIN(getlocal) ||
379 type == BIN(getlocal_WC_0) ||
380 type == BIN(getlocal_WC_1) ||
381 type == BIN(putobject_INT2FIX_0_) ||
382 type == BIN(putobject_INT2FIX_1_) ||
383 type == BIN(opt_getconstant_path)
393append_compile_error(const
rb_iseq_t *iseq,
int line, const
char *fmt, ...)
395 VALUE err_info = ISEQ_COMPILE_DATA(iseq)->err_info;
396 VALUE file = rb_iseq_path(iseq);
401 err = rb_syntax_error_append(err, file, line, -1, NULL, fmt, args);
403 if (
NIL_P(err_info)) {
404 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err);
407 else if (!err_info) {
418compile_bug(
rb_iseq_t *iseq,
int line,
const char *fmt, ...)
422 rb_report_bug_valist(rb_iseq_path(iseq), line, fmt, args);
428#define COMPILE_ERROR append_compile_error
430#define ERROR_ARGS_AT(n) iseq, nd_line(n),
431#define ERROR_ARGS ERROR_ARGS_AT(node)
433#define EXPECT_NODE(prefix, node, ndtype, errval) \
435 const NODE *error_node = (node); \
436 enum node_type error_type = nd_type(error_node); \
437 if (error_type != (ndtype)) { \
438 COMPILE_ERROR(ERROR_ARGS_AT(error_node) \
439 prefix ": " #ndtype " is expected, but %s", \
440 ruby_node_name(error_type)); \
445#define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval) \
447 COMPILE_ERROR(ERROR_ARGS_AT(parent) \
448 prefix ": must be " #ndtype ", but 0"); \
452#define UNKNOWN_NODE(prefix, node, errval) \
454 const NODE *error_node = (node); \
455 COMPILE_ERROR(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \
456 ruby_node_name(nd_type(error_node))); \
463#define CHECK(sub) if (!(sub)) {BEFORE_RETURN;return COMPILE_NG;}
464#define NO_CHECK(sub) (void)(sub)
467#define DECL_ANCHOR(name) \
468 LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},&name[0].anchor}}
469#define INIT_ANCHOR(name) \
470 ((name->last = &name->anchor)->next = NULL)
473freeze_hide_obj(
VALUE obj)
476 RBASIC_CLEAR_CLASS(obj);
480#include "optinsn.inc"
481#if OPT_INSTRUCTIONS_UNIFICATION
482#include "optunifs.inc"
487#define ISEQ_ARG iseq,
488#define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
491#define ISEQ_ARG_DECLARE
495#define gl_node_level ISEQ_COMPILE_DATA(iseq)->node_level
501static int insn_data_length(
INSN *iobj);
502static int calc_sp_depth(
int depth,
INSN *iobj);
504static INSN *new_insn_body(
rb_iseq_t *iseq,
int line_no,
int node_id,
enum ruby_vminsn_type insn_id,
int argc, ...);
517static int iseq_set_exception_local_table(
rb_iseq_t *iseq);
521static int iseq_set_exception_table(
rb_iseq_t *iseq);
522static int iseq_set_optargs_table(
rb_iseq_t *iseq);
523static int iseq_set_parameters_lvar_state(
const rb_iseq_t *iseq);
526static int compile_hash(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *node,
int method_call_keywords,
int popped);
533verify_list(ISEQ_ARG_DECLARE
const char *info,
LINK_ANCHOR *
const anchor)
539 if (!compile_debug)
return;
541 list = anchor->anchor.next;
542 plist = &anchor->anchor;
544 if (plist != list->prev) {
551 if (anchor->last != plist && anchor->last != 0) {
556 rb_bug(
"list verify error: %08x (%s)", flag, info);
561#define verify_list(info, anchor) verify_list(iseq, (info), (anchor))
568 VALUE *original = rb_iseq_original_iseq(iseq);
570 while (i < ISEQ_BODY(iseq)->iseq_size) {
571 VALUE insn = original[i];
572 const char *types = insn_op_types(insn);
574 for (
int j=0; types[j]; j++) {
575 if (types[j] == TS_CALLDATA) {
579 if (cc != vm_cc_empty()) {
581 rb_bug(
"call cache is not initialized by vm_cc_empty()");
588 for (
unsigned int i=0; i<ISEQ_BODY(iseq)->ci_size; i++) {
589 struct rb_call_data *cd = &ISEQ_BODY(iseq)->call_data[i];
592 if (cc != NULL && cc != vm_cc_empty()) {
594 rb_bug(
"call cache is not initialized by vm_cc_empty()");
606 elem->prev = anchor->last;
607 anchor->last->next = elem;
609 verify_list(
"add", anchor);
619 elem->next = before->next;
620 elem->next->prev = elem;
622 if (before == anchor->last) anchor->last = elem;
623 verify_list(
"add", anchor);
626#define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem))
627#define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem))
631branch_coverage_valid_p(
rb_iseq_t *iseq,
int first_line)
633 if (!ISEQ_COVERAGE(iseq))
return 0;
634 if (!ISEQ_BRANCH_COVERAGE(iseq))
return 0;
635 if (first_line <= 0)
return 0;
642 const int first_lineno = loc->beg_pos.lineno, first_column = loc->beg_pos.column;
643 const int last_lineno = loc->end_pos.lineno, last_column = loc->end_pos.column;
646 rb_hash_aset(structure, key, branch);
658 if (!branch_coverage_valid_p(iseq, loc->beg_pos.lineno))
return Qundef;
671 uint64_t source_hash = ISEQ_BODY(iseq)->source_hash;
672 VALUE key = rb_ary_new_from_args(4,
673 ULONG2NUM((
unsigned long)(source_hash >> 32)),
674 ULONG2NUM((
unsigned long)(source_hash & 0xffffffff)),
680 VALUE branch_base = rb_hash_aref(structure, key);
683 if (
NIL_P(branch_base)) {
684 branch_base = setup_branch(loc,
type, structure, key);
685 branches = rb_hash_new();
697generate_dummy_line_node(
int lineno,
int node_id)
700 nd_set_line(&dummy, lineno);
701 nd_set_node_id(&dummy, node_id);
708 if (!branch_coverage_valid_p(iseq, loc->beg_pos.lineno))
return;
719 VALUE branch = rb_hash_aref(branches, key);
723 branch = setup_branch(loc,
type, branches, key);
733 ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx);
734 ADD_SYNTHETIC_INSN(seq, loc->end_pos.lineno, node_id, nop);
737#define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line)
740validate_label(st_data_t name, st_data_t label, st_data_t arg)
744 if (!lobj->link.next) {
746 COMPILE_ERROR(iseq, lobj->position,
747 "%"PRIsVALUE
": undefined label",
757 st_foreach(labels_table, validate_label, (st_data_t)iseq);
758 st_free_table(labels_table);
762get_nd_recv(
const NODE *node)
764 switch (nd_type(node)) {
766 return RNODE_CALL(node)->nd_recv;
768 return RNODE_OPCALL(node)->nd_recv;
772 return RNODE_QCALL(node)->nd_recv;
776 return RNODE_ATTRASGN(node)->nd_recv;
778 return RNODE_OP_ASGN1(node)->nd_recv;
780 return RNODE_OP_ASGN2(node)->nd_recv;
782 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
787get_node_call_nd_mid(
const NODE *node)
789 switch (nd_type(node)) {
791 return RNODE_CALL(node)->nd_mid;
793 return RNODE_OPCALL(node)->nd_mid;
795 return RNODE_FCALL(node)->nd_mid;
797 return RNODE_QCALL(node)->nd_mid;
799 return RNODE_VCALL(node)->nd_mid;
801 return RNODE_ATTRASGN(node)->nd_mid;
803 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
808get_nd_args(
const NODE *node)
810 switch (nd_type(node)) {
812 return RNODE_CALL(node)->nd_args;
814 return RNODE_OPCALL(node)->nd_args;
816 return RNODE_FCALL(node)->nd_args;
818 return RNODE_QCALL(node)->nd_args;
822 return RNODE_ATTRASGN(node)->nd_args;
824 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
829get_node_colon_nd_mid(
const NODE *node)
831 switch (nd_type(node)) {
833 return RNODE_COLON2(node)->nd_mid;
835 return RNODE_COLON3(node)->nd_mid;
837 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
842get_nd_vid(
const NODE *node)
844 switch (nd_type(node)) {
846 return RNODE_LASGN(node)->nd_vid;
848 return RNODE_DASGN(node)->nd_vid;
850 return RNODE_IASGN(node)->nd_vid;
852 return RNODE_CVASGN(node)->nd_vid;
854 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
859get_nd_value(
const NODE *node)
861 switch (nd_type(node)) {
863 return RNODE_LASGN(node)->nd_value;
865 return RNODE_DASGN(node)->nd_value;
867 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
872get_string_value(
const NODE *node)
874 switch (nd_type(node)) {
880 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
890 (*ifunc->func)(iseq, ret, ifunc->data);
892 ADD_SYNTHETIC_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, -1, leave);
894 CHECK(iseq_setup_insn(iseq, ret));
895 return iseq_setup(iseq, ret);
898static bool drop_unreachable_return(
LINK_ANCHOR *ret);
907 NO_CHECK(COMPILE(ret,
"nil", node));
908 iseq_set_local_table(iseq, 0, 0);
911 else if (nd_type_p(node, NODE_SCOPE)) {
913 iseq_set_local_table(iseq, RNODE_SCOPE(node)->nd_tbl, (
NODE *)RNODE_SCOPE(node)->nd_args);
914 iseq_set_arguments(iseq, ret, (
NODE *)RNODE_SCOPE(node)->nd_args);
915 iseq_set_parameters_lvar_state(iseq);
917 switch (ISEQ_BODY(iseq)->
type) {
918 case ISEQ_TYPE_BLOCK:
920 LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(0);
921 LABEL *end = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(0);
923 start->rescued = LABEL_RESCUE_BEG;
924 end->rescued = LABEL_RESCUE_END;
927 ADD_SYNTHETIC_INSN(ret, ISEQ_BODY(iseq)->location.first_lineno, -1, nop);
928 ADD_LABEL(ret, start);
929 CHECK(COMPILE(ret,
"block body", RNODE_SCOPE(node)->nd_body));
932 ISEQ_COMPILE_DATA(iseq)->last_line = ISEQ_BODY(iseq)->location.code_location.end_pos.lineno;
935 ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
936 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
939 case ISEQ_TYPE_CLASS:
942 CHECK(COMPILE(ret,
"scoped node", RNODE_SCOPE(node)->nd_body));
944 ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
947 case ISEQ_TYPE_METHOD:
949 ISEQ_COMPILE_DATA(iseq)->root_node = RNODE_SCOPE(node)->nd_body;
951 CHECK(COMPILE(ret,
"scoped node", RNODE_SCOPE(node)->nd_body));
952 ISEQ_COMPILE_DATA(iseq)->root_node = RNODE_SCOPE(node)->nd_body;
954 ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
958 CHECK(COMPILE(ret,
"scoped node", RNODE_SCOPE(node)->nd_body));
965#define INVALID_ISEQ_TYPE(type) \
966 ISEQ_TYPE_##type: m = #type; goto invalid_iseq_type
967 switch (ISEQ_BODY(iseq)->
type) {
968 case INVALID_ISEQ_TYPE(
METHOD);
969 case INVALID_ISEQ_TYPE(CLASS);
970 case INVALID_ISEQ_TYPE(BLOCK);
971 case INVALID_ISEQ_TYPE(EVAL);
972 case INVALID_ISEQ_TYPE(MAIN);
973 case INVALID_ISEQ_TYPE(TOP);
974#undef INVALID_ISEQ_TYPE
975 case ISEQ_TYPE_RESCUE:
976 iseq_set_exception_local_table(iseq);
977 CHECK(COMPILE(ret,
"rescue", node));
979 case ISEQ_TYPE_ENSURE:
980 iseq_set_exception_local_table(iseq);
981 CHECK(COMPILE_POPPED(ret,
"ensure", node));
983 case ISEQ_TYPE_PLAIN:
984 CHECK(COMPILE(ret,
"ensure", node));
987 COMPILE_ERROR(ERROR_ARGS
"unknown scope: %d", ISEQ_BODY(iseq)->
type);
990 COMPILE_ERROR(ERROR_ARGS
"compile/ISEQ_TYPE_%s should not be reached", m);
995 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE || ISEQ_BODY(iseq)->
type == ISEQ_TYPE_ENSURE) {
996 NODE dummy_line_node = generate_dummy_line_node(0, -1);
997 ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
998 ADD_INSN1(ret, &dummy_line_node,
throw,
INT2FIX(0) );
1000 else if (!drop_unreachable_return(ret)) {
1001 ADD_SYNTHETIC_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, -1, leave);
1005 if (ISEQ_COMPILE_DATA(iseq)->labels_table) {
1006 st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
1007 ISEQ_COMPILE_DATA(iseq)->labels_table = 0;
1008 validate_labels(iseq, labels_table);
1011 CHECK(iseq_setup_insn(iseq, ret));
1012 return iseq_setup(iseq, ret);
1016rb_iseq_translate_threaded_code(
rb_iseq_t *iseq)
1018#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
1019 const void *
const *table = rb_vm_get_insns_address_table();
1021 VALUE *encoded = (
VALUE *)ISEQ_BODY(iseq)->iseq_encoded;
1023 for (i = 0; i < ISEQ_BODY(iseq)->iseq_size; ) {
1024 int insn = (int)ISEQ_BODY(iseq)->iseq_encoded[i];
1025 int len = insn_len(insn);
1026 encoded[i] = (
VALUE)table[insn];
1033 rb_yjit_live_iseq_count++;
1034 rb_yjit_iseq_alloc_count++;
1041rb_iseq_original_iseq(
const rb_iseq_t *iseq)
1046 if (original_code)
return original_code;
1047 original_code =
ALLOC_N(
VALUE, ISEQ_BODY(iseq)->iseq_size);
1048 MEMCPY(original_code, ISEQ_BODY(iseq)->iseq_encoded,
VALUE, ISEQ_BODY(iseq)->iseq_size);
1053 for (i = 0; i < ISEQ_BODY(iseq)->iseq_size; ) {
1054 const void *addr = (
const void *)original_code[i];
1055 const int insn = rb_vm_insn_addr2insn(addr);
1057 original_code[i] = insn;
1058 i += insn_len(insn);
1064 v = rb_iseq_variable_ensure((
rb_iseq_t *)iseq);
1065 VALUE *prev = ATOMIC_PTR_CAS(v->original_iseq,
1066 NULL, original_code);
1068 SIZED_FREE_N(original_code, ISEQ_BODY(iseq)->iseq_size);
1071 return original_code;
1078#if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE
1079# define ALIGNMENT_SIZE SIZEOF_LONG_LONG
1081# define ALIGNMENT_SIZE SIZEOF_VALUE
1083#define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1))
1085#define ALIGNMENT_SIZE_OF(type) alignment_size_assert(RUBY_ALIGNOF(type), #type)
1088alignment_size_assert(
size_t align,
const char *
type)
1091 "ALIGNMENT_SIZE_OF(%s):%zd == (2 ** N) is expected",
type, align);
1097calc_padding(
void *ptr,
size_t align)
1102 mis = (size_t)ptr & (align - 1);
1104 padding = align - mis;
1115 size_t padding = calc_padding((
void *)&storage->buff[storage->pos], align);
1117 if (size >= INT_MAX - padding) rb_memerror();
1118 if (storage->pos + size + padding > storage->size) {
1119 unsigned int alloc_size = storage->size;
1121 while (alloc_size < size + PADDING_SIZE_MAX) {
1122 if (alloc_size >= INT_MAX / 2) rb_memerror();
1125 storage->next = (
void *)
ALLOC_N(
char, alloc_size +
1127 storage = *arena = storage->next;
1130 storage->size = alloc_size;
1131 padding = calc_padding((
void *)&storage->buff[storage->pos], align);
1134 storage->pos += (int)padding;
1136 ptr = (
void *)&storage->buff[storage->pos];
1137 storage->pos += (int)size;
1142compile_data_alloc(
rb_iseq_t *iseq,
size_t size,
size_t align)
1145 return compile_data_alloc_with_arena(arena, size, align);
1148#define compile_data_alloc_type(iseq, type) \
1149 (type *)compile_data_alloc(iseq, sizeof(type), ALIGNMENT_SIZE_OF(type))
1152compile_data_alloc2(
rb_iseq_t *iseq,
size_t elsize,
size_t num,
size_t align)
1155 return compile_data_alloc(iseq, size, align);
1158#define compile_data_alloc2_type(iseq, type, num) \
1159 (type *)compile_data_alloc2(iseq, sizeof(type), num, ALIGNMENT_SIZE_OF(type))
1162compile_data_calloc2(
rb_iseq_t *iseq,
size_t elsize,
size_t num,
size_t align)
1165 void *p = compile_data_alloc(iseq, size, align);
1170#define compile_data_calloc2_type(iseq, type, num) \
1171 (type *)compile_data_calloc2(iseq, sizeof(type), num, ALIGNMENT_SIZE_OF(type))
1177 return (
INSN *)compile_data_alloc_with_arena(arena,
sizeof(
INSN), ALIGNMENT_SIZE_OF(
INSN));
1181compile_data_alloc_label(
rb_iseq_t *iseq)
1183 return compile_data_alloc_type(iseq,
LABEL);
1187compile_data_alloc_adjust(
rb_iseq_t *iseq)
1189 return compile_data_alloc_type(iseq,
ADJUST);
1193compile_data_alloc_trace(
rb_iseq_t *iseq)
1195 return compile_data_alloc_type(iseq,
TRACE);
1204 elem2->next = elem1->next;
1205 elem2->prev = elem1;
1206 elem1->next = elem2;
1208 elem2->next->prev = elem2;
1218 elem2->prev = elem1->prev;
1219 elem2->next = elem1;
1220 elem1->prev = elem2;
1222 elem2->prev->next = elem2;
1232 elem2->prev = elem1->prev;
1233 elem2->next = elem1->next;
1235 elem1->prev->next = elem2;
1238 elem1->next->prev = elem2;
1245 elem->prev->next = elem->next;
1247 elem->next->prev = elem->prev;
1260 first->prev->next = second;
1261 second->next->prev = first;
1263 first->next = second->next;
1264 second->next = first;
1266 second->prev = first->prev;
1267 first->prev = second;
1269 if (IS_INSN(first) && IS_INSN(second)) {
1275 if (first_insn->insn_info.line_no == second_insn->insn_info.line_no) {
1279 first_insn->insn_info.events = (first_insn->insn_info.events & ~mask) | second_events;
1280 second_insn->insn_info.events = (second_insn->insn_info.events & ~mask) | first_events;
1288 return anchor->anchor.next;
1294 return anchor->last;
1301 switch (elem->type) {
1302 case ISEQ_ELEMENT_INSN:
1303 case ISEQ_ELEMENT_ADJUST:
1313LIST_INSN_SIZE_ONE(
const LINK_ANCHOR *
const anchor)
1315 LINK_ELEMENT *first_insn = ELEM_FIRST_INSN(FIRST_ELEMENT(anchor));
1316 if (first_insn != NULL &&
1317 ELEM_FIRST_INSN(first_insn->next) == NULL) {
1326LIST_INSN_SIZE_ZERO(
const LINK_ANCHOR *
const anchor)
1328 if (ELEM_FIRST_INSN(FIRST_ELEMENT(anchor)) == NULL) {
1346 if (anc2->anchor.next) {
1349 anc1->last->next = anc2->anchor.next;
1350 anc2->anchor.next->prev = anc1->last;
1351 anc1->last = anc2->last;
1356 verify_list(
"append", anc1);
1359#define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
1368 printf(
"anch: %p, frst: %p, last: %p\n", (
void *)&anchor->anchor,
1369 (
void *)anchor->anchor.next, (
void *)anchor->last);
1371 printf(
"curr: %p, next: %p, prev: %p, type: %d\n", (
void *)list, (
void *)list->next,
1372 (
void *)list->prev, (
int)list->type);
1377 dump_disasm_list_with_cursor(anchor->anchor.next, cur, 0);
1378 verify_list(
"debug list", anchor);
1381#define debug_list(anc, cur) debug_list(iseq, (anc), (cur))
1384#define debug_list(anc, cur) ((void)0)
1390 TRACE *trace = compile_data_alloc_trace(iseq);
1392 trace->link.type = ISEQ_ELEMENT_TRACE;
1393 trace->link.next = NULL;
1394 trace->event = event;
1401new_label_body(
rb_iseq_t *iseq,
long line)
1403 LABEL *labelobj = compile_data_alloc_label(iseq);
1405 labelobj->link.type = ISEQ_ELEMENT_LABEL;
1406 labelobj->link.next = 0;
1408 labelobj->label_no = ISEQ_COMPILE_DATA(iseq)->label_no++;
1409 labelobj->sc_state = 0;
1411 labelobj->refcnt = 0;
1413 labelobj->rescued = LABEL_RESCUE_NONE;
1414 labelobj->unremovable = 0;
1415 labelobj->position = -1;
1422 ADJUST *adjust = compile_data_alloc_adjust(iseq);
1423 adjust->link.type = ISEQ_ELEMENT_ADJUST;
1424 adjust->link.next = 0;
1425 adjust->label = label;
1426 adjust->line_no = line;
1427 LABEL_UNREMOVABLE(label);
1434 const char *types = insn_op_types(insn->insn_id);
1435 for (
int j = 0; types[j]; j++) {
1436 char type = types[j];
1443 func(&OPERAND_AT(insn, j), data);
1452iseq_insn_each_object_write_barrier(
VALUE * obj,
VALUE iseq)
1461new_insn_core(
rb_iseq_t *iseq,
int line_no,
int node_id,
int insn_id,
int argc,
VALUE *argv)
1463 INSN *iobj = compile_data_alloc_insn(iseq);
1467 iobj->link.type = ISEQ_ELEMENT_INSN;
1468 iobj->link.next = 0;
1469 iobj->insn_id = insn_id;
1470 iobj->insn_info.line_no = line_no;
1471 iobj->insn_info.node_id = node_id;
1472 iobj->insn_info.events = 0;
1473 iobj->operands = argv;
1474 iobj->operand_size = argc;
1477 iseq_insn_each_markable_object(iobj, iseq_insn_each_object_write_barrier, (
VALUE)iseq);
1483new_insn_body(
rb_iseq_t *iseq,
int line_no,
int node_id,
enum ruby_vminsn_type insn_id,
int argc, ...)
1485 VALUE *operands = 0;
1489 va_start(argv, argc);
1490 operands = compile_data_alloc2_type(iseq,
VALUE, argc);
1491 for (i = 0; i < argc; i++) {
1497 return new_insn_core(iseq, line_no, node_id, insn_id, argc, operands);
1501insn_replace_with_operands(
rb_iseq_t *iseq,
INSN *iobj,
enum ruby_vminsn_type insn_id,
int argc, ...)
1503 VALUE *operands = 0;
1507 va_start(argv, argc);
1508 operands = compile_data_alloc2_type(iseq,
VALUE, argc);
1509 for (i = 0; i < argc; i++) {
1516 iobj->insn_id = insn_id;
1517 iobj->operand_size = argc;
1518 iobj->operands = operands;
1519 iseq_insn_each_markable_object(iobj, iseq_insn_each_object_write_barrier, (
VALUE)iseq);
1527 VM_ASSERT(argc >= 0);
1530 flag |= VM_CALL_KWARG;
1531 argc += kw_arg->keyword_len;
1534 if (!(flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KWARG | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING))
1535 && !has_blockiseq) {
1536 flag |= VM_CALL_ARGS_SIMPLE;
1539 ISEQ_BODY(iseq)->ci_size++;
1540 const struct rb_callinfo *ci = vm_ci_new(mid, flag, argc, kw_arg);
1548 VALUE *operands = compile_data_calloc2_type(iseq,
VALUE, 2);
1551 operands[1] = (
VALUE)blockiseq;
1558 if (vm_ci_flag((
struct rb_callinfo *)ci) & VM_CALL_FORWARDING) {
1559 insn = new_insn_core(iseq, line_no, node_id, BIN(sendforward), 2, operands);
1562 insn = new_insn_core(iseq, line_no, node_id, BIN(send), 2, operands);
1575 VALUE ast_value = rb_ruby_ast_new(node);
1579 if (ISEQ_BODY(iseq)->source_hash) {
1580 rb_ast_t *child_ast = rb_ruby_ast_data_get(ast_value);
1581 child_ast->body.source_hash = ISEQ_BODY(iseq)->source_hash;
1582 child_ast->body.has_source_hash = 1;
1585 debugs(
"[new_child_iseq]> ---------------------------------------\n");
1586 int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
1587 ret_iseq = rb_iseq_new_with_opt(ast_value, name,
1588 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
1590 isolated_depth ? isolated_depth + 1 : 0,
1591 type, ISEQ_COMPILE_DATA(iseq)->option,
1592 ISEQ_SCRIPT_LINES(iseq));
1593 debugs(
"[new_child_iseq]< ---------------------------------------\n");
1603 debugs(
"[new_child_iseq_with_callback]> ---------------------------------------\n");
1604 ret_iseq = rb_iseq_new_with_callback(ifunc, name,
1605 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
1606 line_no, parent,
type, ISEQ_COMPILE_DATA(iseq)->option);
1607 debugs(
"[new_child_iseq_with_callback]< ---------------------------------------\n");
1615 ISEQ_COMPILE_DATA(iseq)->catch_except_p =
true;
1616 if (ISEQ_BODY(iseq)->parent_iseq != NULL) {
1617 if (ISEQ_COMPILE_DATA(ISEQ_BODY(iseq)->parent_iseq)) {
1618 set_catch_except_p((
rb_iseq_t *) ISEQ_BODY(iseq)->parent_iseq);
1641 while (pos < body->iseq_size) {
1642 insn = rb_vm_insn_decode(body->iseq_encoded[pos]);
1643 if (insn == BIN(
throw)) {
1644 set_catch_except_p(iseq);
1647 pos += insn_len(insn);
1653 for (i = 0; i < ct->size; i++) {
1655 UNALIGNED_MEMBER_PTR(ct, entries[i]);
1656 if (entry->type != CATCH_TYPE_BREAK
1657 && entry->type != CATCH_TYPE_NEXT
1658 && entry->type != CATCH_TYPE_REDO) {
1660 ISEQ_COMPILE_DATA(iseq)->catch_except_p =
true;
1667iseq_insert_nop_between_end_and_cont(
rb_iseq_t *iseq)
1669 VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
1670 if (
NIL_P(catch_table_ary))
return;
1671 unsigned int i, tlen = (
unsigned int)
RARRAY_LEN(catch_table_ary);
1673 for (i = 0; i < tlen; i++) {
1679 enum rb_catch_type ct = (
enum rb_catch_type)(ptr[0] & 0xffff);
1681 if (ct != CATCH_TYPE_BREAK
1682 && ct != CATCH_TYPE_NEXT
1683 && ct != CATCH_TYPE_REDO) {
1685 for (e = end; e && (IS_LABEL(e) || IS_TRACE(e)); e = e->next) {
1687 INSN *nop = new_insn_core(iseq, 0, -1, BIN(nop), 0, 0);
1688 ELEM_INSERT_NEXT(end, &nop->link);
1701 if (
RTEST(ISEQ_COMPILE_DATA(iseq)->err_info))
1706 if (compile_debug > 5)
1707 dump_disasm_list(FIRST_ELEMENT(anchor));
1709 debugs(
"[compile step 3.1 (iseq_optimize)]\n");
1710 iseq_optimize(iseq, anchor);
1712 if (compile_debug > 5)
1713 dump_disasm_list(FIRST_ELEMENT(anchor));
1715 if (ISEQ_COMPILE_DATA(iseq)->option->instructions_unification) {
1716 debugs(
"[compile step 3.2 (iseq_insns_unification)]\n");
1717 iseq_insns_unification(iseq, anchor);
1718 if (compile_debug > 5)
1719 dump_disasm_list(FIRST_ELEMENT(anchor));
1722 debugs(
"[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n");
1723 iseq_insert_nop_between_end_and_cont(iseq);
1724 if (compile_debug > 5)
1725 dump_disasm_list(FIRST_ELEMENT(anchor));
1733 if (
RTEST(ISEQ_COMPILE_DATA(iseq)->err_info))
1736 debugs(
"[compile step 4.1 (iseq_set_sequence)]\n");
1737 if (!iseq_set_sequence(iseq, anchor))
return COMPILE_NG;
1738 if (compile_debug > 5)
1739 dump_disasm_list(FIRST_ELEMENT(anchor));
1741 debugs(
"[compile step 4.2 (iseq_set_exception_table)]\n");
1742 if (!iseq_set_exception_table(iseq))
return COMPILE_NG;
1744 debugs(
"[compile step 4.3 (set_optargs_table)] \n");
1745 if (!iseq_set_optargs_table(iseq))
return COMPILE_NG;
1747 debugs(
"[compile step 5 (iseq_translate_threaded_code)] \n");
1748 if (!rb_iseq_translate_threaded_code(iseq))
return COMPILE_NG;
1750 debugs(
"[compile step 6 (update_catch_except_flags)] \n");
1752 update_catch_except_flags(iseq, ISEQ_BODY(iseq));
1754 debugs(
"[compile step 6.1 (remove unused catch tables)] \n");
1756 if (!ISEQ_COMPILE_DATA(iseq)->catch_except_p && ISEQ_BODY(iseq)->catch_table) {
1757 ruby_xfree_sized(ISEQ_BODY(iseq)->catch_table, iseq_catch_table_bytes(ISEQ_BODY(iseq)->catch_table->size));
1758 ISEQ_BODY(iseq)->catch_table = NULL;
1761#if VM_INSN_INFO_TABLE_IMPL == 2
1762 debugs(
"[compile step 7 (rb_iseq_insns_info_encode_positions)] \n");
1763 rb_iseq_insns_info_encode_positions(iseq);
1766 if (compile_debug > 1) {
1767 VALUE str = rb_iseq_disasm(iseq);
1770 verify_call_cache(iseq);
1771 debugs(
"[compile step: finish]\n");
1777iseq_set_exception_local_table(
rb_iseq_t *iseq)
1779 ISEQ_BODY(iseq)->local_table_size = numberof(rb_iseq_shared_exc_local_tbl);
1780 ISEQ_BODY(iseq)->local_table = rb_iseq_shared_exc_local_tbl;
1781 ISEQ_BODY(iseq)->lvar_states.list = NULL;
1789 while (iseq != ISEQ_BODY(iseq)->local_iseq) {
1791 iseq = ISEQ_BODY(iseq)->parent_iseq;
1797get_dyna_var_idx_at_raw(
const rb_iseq_t *iseq,
ID id)
1801 for (i = 0; i < ISEQ_BODY(iseq)->local_table_size; i++) {
1802 if (ISEQ_BODY(iseq)->local_table[i] == id) {
1812 int idx = get_dyna_var_idx_at_raw(ISEQ_BODY(iseq)->local_iseq,
id);
1815 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
1816 "get_local_var_idx: %d", idx);
1823get_dyna_var_idx(
const rb_iseq_t *iseq,
ID id,
int *level,
int *ls)
1825 int lv = 0, idx = -1;
1826 const rb_iseq_t *
const topmost_iseq = iseq;
1829 idx = get_dyna_var_idx_at_raw(iseq,
id);
1833 iseq = ISEQ_BODY(iseq)->parent_iseq;
1838 COMPILE_ERROR(topmost_iseq, ISEQ_LAST_LINE(topmost_iseq),
1839 "get_dyna_var_idx: -1");
1843 *ls = ISEQ_BODY(iseq)->local_table_size;
1848iseq_local_block_param_p(
const rb_iseq_t *iseq,
unsigned int idx,
unsigned int level)
1852 iseq = ISEQ_BODY(iseq)->parent_iseq;
1855 body = ISEQ_BODY(iseq);
1856 if (body->local_iseq == iseq &&
1857 body->param.flags.has_block &&
1858 body->local_table_size - body->param.block_start == idx) {
1867iseq_block_param_id_p(
const rb_iseq_t *iseq,
ID id,
int *pidx,
int *plevel)
1870 int idx = get_dyna_var_idx(iseq,
id, &level, &ls);
1871 if (iseq_local_block_param_p(iseq, ls - idx, level)) {
1882access_outer_variables(
const rb_iseq_t *iseq,
int level,
ID id,
bool write)
1884 int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
1886 if (isolated_depth && level >= isolated_depth) {
1887 if (
id == rb_intern(
"yield")) {
1888 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
"can not yield from isolated Proc");
1891 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
"can not access variable '%s' from isolated Proc", rb_id2name(
id));
1895 for (
int i=0; i<level; i++) {
1897 struct rb_id_table *ovs = ISEQ_BODY(iseq)->outer_variables;
1900 ovs = ISEQ_BODY(iseq)->outer_variables = rb_id_table_create(8);
1903 if (rb_id_table_lookup(ISEQ_BODY(iseq)->outer_variables,
id, &val)) {
1904 if (write && !val) {
1905 rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables,
id,
Qtrue);
1909 rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables,
id, RBOOL(write));
1912 iseq = ISEQ_BODY(iseq)->parent_iseq;
1917iseq_lvar_id(
const rb_iseq_t *iseq,
int idx,
int level)
1919 for (
int i=0; i<level; i++) {
1920 iseq = ISEQ_BODY(iseq)->parent_iseq;
1923 ID id = ISEQ_BODY(iseq)->local_table[ISEQ_BODY(iseq)->local_table_size - idx];
1929update_lvar_state(
const rb_iseq_t *iseq,
int level,
int idx)
1931 for (
int i=0; i<level; i++) {
1932 iseq = ISEQ_BODY(iseq)->parent_iseq;
1935 uint8_t *states = iseq_lvar_states(ISEQ_BODY(iseq));
1936 int table_idx = ISEQ_BODY(iseq)->local_table_size - idx;
1937 switch (iseq_lvar_state_get(states, table_idx)) {
1938 case lvar_uninitialized:
1939 iseq_lvar_state_set(states, table_idx, lvar_initialized);
1941 case lvar_initialized:
1942 iseq_lvar_state_set(states, table_idx, lvar_reassigned);
1944 case lvar_reassigned:
1948 rb_bug(
"unreachable");
1953iseq_set_parameters_lvar_state(
const rb_iseq_t *iseq)
1955 uint8_t *states = iseq_lvar_states(ISEQ_BODY(iseq));
1957 for (
unsigned int i=0; i<ISEQ_BODY(iseq)->param.size; i++) {
1958 iseq_lvar_state_set(states, i, lvar_initialized);
1961 int lead_num = ISEQ_BODY(iseq)->param.lead_num;
1962 int opt_num = ISEQ_BODY(iseq)->param.opt_num;
1963 for (
int i=0; i<opt_num; i++) {
1964 iseq_lvar_state_set(states, lead_num + i, lvar_uninitialized);
1973 if (iseq_local_block_param_p(iseq, idx, level)) {
1974 ADD_INSN2(seq, line_node, getblockparam,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1977 ADD_INSN2(seq, line_node, getlocal,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1979 if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level),
Qfalse);
1985 if (iseq_local_block_param_p(iseq, idx, level)) {
1986 ADD_INSN2(seq, line_node, setblockparam,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1989 ADD_INSN2(seq, line_node, setlocal,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1991 update_lvar_state(iseq, level, idx);
1992 if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level),
Qtrue);
2001 if (body->param.flags.has_opt ||
2002 body->param.flags.has_post ||
2003 body->param.flags.has_rest ||
2004 body->param.flags.has_block ||
2005 body->param.flags.has_kw ||
2006 body->param.flags.has_kwrest) {
2008 if (body->param.flags.has_block) {
2009 body->param.size = body->param.block_start + 1;
2011 else if (body->param.flags.has_kwrest) {
2012 body->param.size = body->param.keyword->rest_start + 1;
2014 else if (body->param.flags.has_kw) {
2015 body->param.size = body->param.keyword->bits_start + 1;
2017 else if (body->param.flags.has_post) {
2018 body->param.size = body->param.post_start + body->param.post_num;
2020 else if (body->param.flags.has_rest) {
2021 body->param.size = body->param.rest_start + 1;
2023 else if (body->param.flags.has_opt) {
2024 body->param.size = body->param.lead_num + body->param.opt_num;
2031 body->param.size = body->param.lead_num;
2041 struct rb_iseq_param_keyword *keyword;
2044 int kw = 0, rkw = 0, di = 0, i;
2046 body->param.flags.has_kw = TRUE;
2047 body->param.keyword = keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
2051 node = node->nd_next;
2053 if (kw > VM_CALL_KW_LEN_MAX) {
2054 COMPILE_ERROR(ERROR_ARGS_AT(RNODE(args->kw_args))
"too many keyword parameters (%d, maximum is %d)",
2055 kw, (
int)VM_CALL_KW_LEN_MAX);
2058 keyword->bits_start = arg_size++;
2060 node = args->kw_args;
2062 const NODE *val_node = get_nd_value(node->nd_body);
2065 if (val_node == NODE_SPECIAL_REQUIRED_KEYWORD) {
2069 switch (nd_type(val_node)) {
2071 dv = rb_node_sym_string_val(val_node);
2074 dv = rb_node_regx_string_val(val_node);
2077 dv = rb_node_line_lineno_val(val_node);
2080 dv = rb_node_integer_literal_val(val_node);
2083 dv = rb_node_float_literal_val(val_node);
2086 dv = rb_node_rational_literal_val(val_node);
2088 case NODE_IMAGINARY:
2089 dv = rb_node_imaginary_literal_val(val_node);
2092 dv = rb_node_encoding_val(val_node);
2104 NO_CHECK(COMPILE_POPPED(optargs,
"kwarg", RNODE(node)));
2108 keyword->num = ++di;
2112 node = node->nd_next;
2117 if (RNODE_DVAR(args->kw_rest_arg)->nd_vid != 0) {
2118 ID kw_id = ISEQ_BODY(iseq)->local_table[arg_size];
2119 keyword->rest_start = arg_size++;
2120 body->param.flags.has_kwrest = TRUE;
2122 if (kw_id == idPow) body->param.flags.anon_kwrest = TRUE;
2124 keyword->required_num = rkw;
2125 keyword->table = &body->local_table[keyword->bits_start - keyword->num];
2130 for (i = 0; i <
RARRAY_LEN(default_values); i++) {
2132 if (dv == complex_mark) dv =
Qundef;
2137 keyword->default_values = dvs;
2146 if (!body->param.flags.use_block) {
2147 body->param.flags.use_block = 1;
2152 st_data_t key = (st_data_t)rb_intern_str(body->location.label);
2153 set_insert(&vm->unused_block_warning_table, key);
2161 debugs(
"iseq_set_arguments: %s\n", node_args ?
"" :
"0");
2165 const struct rb_args_info *
const args = &RNODE_ARGS(node_args)->nd_ainfo;
2171 EXPECT_NODE(
"iseq_set_arguments", node_args, NODE_ARGS, COMPILE_NG);
2173 body->param.lead_num = arg_size = (int)args->pre_args_num;
2174 if (body->param.lead_num > 0) body->param.flags.has_lead = TRUE;
2175 debugs(
" - argc: %d\n", body->param.lead_num);
2177 rest_id = args->rest_arg;
2178 if (rest_id == NODE_SPECIAL_EXCESSIVE_COMMA) {
2182 block_id = args->block_arg;
2184 bool optimized_forward = (args->forwarding && args->pre_args_num == 0 && !args->opt_args);
2186 if (optimized_forward) {
2191 if (args->opt_args) {
2199 label = NEW_LABEL(nd_line(RNODE(node)));
2201 ADD_LABEL(optargs, label);
2202 NO_CHECK(COMPILE_POPPED(optargs,
"optarg", node->nd_body));
2203 node = node->nd_next;
2208 label = NEW_LABEL(nd_line(node_args));
2210 ADD_LABEL(optargs, label);
2215 for (j = 0; j < i+1; j++) {
2220 body->param.flags.has_opt = TRUE;
2221 body->param.opt_num = i;
2222 body->param.opt_table = opt_table;
2227 body->param.rest_start = arg_size++;
2228 body->param.flags.has_rest = TRUE;
2229 if (rest_id ==
'*') body->param.flags.anon_rest = TRUE;
2233 if (args->first_post_arg) {
2234 body->param.post_start = arg_size;
2235 body->param.post_num = args->post_args_num;
2236 body->param.flags.has_post = TRUE;
2237 arg_size += args->post_args_num;
2239 if (body->param.flags.has_rest) {
2240 body->param.post_start = body->param.rest_start + 1;
2244 if (args->kw_args) {
2245 arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size);
2247 else if (args->kw_rest_arg && !optimized_forward) {
2248 ID kw_id = ISEQ_BODY(iseq)->local_table[arg_size];
2249 struct rb_iseq_param_keyword *keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
2250 keyword->rest_start = arg_size++;
2251 body->param.keyword = keyword;
2252 body->param.flags.has_kwrest = TRUE;
2254 static ID anon_kwrest = 0;
2255 if (!anon_kwrest) anon_kwrest = rb_intern(
"**");
2256 if (kw_id == anon_kwrest) body->param.flags.anon_kwrest = TRUE;
2258 else if (args->no_kwarg) {
2259 body->param.flags.accepts_no_kwarg = TRUE;
2262 if (args->no_blockarg) {
2263 body->param.flags.accepts_no_block = TRUE;
2265 else if (block_id) {
2266 body->param.block_start = arg_size++;
2267 body->param.flags.has_block = TRUE;
2268 iseq_set_use_block(iseq);
2272 if (optimized_forward) {
2273 body->param.flags.use_block = 1;
2274 body->param.flags.forwardable = TRUE;
2278 iseq_calc_param_size(iseq);
2279 body->param.size = arg_size;
2281 if (args->pre_init) {
2282 NO_CHECK(COMPILE_POPPED(optargs,
"init arguments (m)", args->pre_init));
2284 if (args->post_init) {
2285 NO_CHECK(COMPILE_POPPED(optargs,
"init arguments (p)", args->post_init));
2288 if (body->type == ISEQ_TYPE_BLOCK) {
2289 if (body->param.flags.has_opt == FALSE &&
2290 body->param.flags.has_post == FALSE &&
2291 body->param.flags.has_rest == FALSE &&
2292 body->param.flags.has_kw == FALSE &&
2293 body->param.flags.has_kwrest == FALSE) {
2295 if (body->param.lead_num == 1 && last_comma == 0) {
2297 body->param.flags.ambiguous_param0 = TRUE;
2309 unsigned int size = tbl ? tbl->size : 0;
2310 unsigned int offset = 0;
2313 struct rb_args_info *args = &RNODE_ARGS(node_args)->nd_ainfo;
2318 if (args->forwarding && args->pre_args_num == 0 && !args->opt_args) {
2327 MEMCPY(ids, tbl->ids + offset,
ID, size);
2328 ISEQ_BODY(iseq)->local_table = ids;
2330 if (ISEQ_LVAR_STATES_EMBED_P(size)) {
2332 memset(ISEQ_BODY(iseq)->lvar_states.single, 0,
sizeof(ISEQ_BODY(iseq)->lvar_states.single));
2335 ISEQ_BODY(iseq)->lvar_states.list =
ZALLOC_N(uint8_t, ISEQ_LVAR_STATES_BUFLEN(size));
2338 ISEQ_BODY(iseq)->local_table_size = size;
2340 debugs(
"iseq_set_local_table: %u\n", ISEQ_BODY(iseq)->local_table_size);
2352 else if ((tlit = OBJ_BUILTIN_TYPE(lit)) == -1) {
2355 else if ((tval = OBJ_BUILTIN_TYPE(val)) == -1) {
2358 else if (tlit != tval) {
2368 long x =
FIX2LONG(rb_big_cmp(lit, val));
2376 return rb_float_cmp(lit, val);
2379 const struct RRational *rat1 = RRATIONAL(val);
2380 const struct RRational *rat2 = RRATIONAL(lit);
2381 return rb_iseq_cdhash_cmp(rat1->num, rat2->num) || rb_iseq_cdhash_cmp(rat1->den, rat2->den);
2384 const struct RComplex *comp1 = RCOMPLEX(val);
2385 const struct RComplex *comp2 = RCOMPLEX(lit);
2386 return rb_iseq_cdhash_cmp(comp1->real, comp2->real) || rb_iseq_cdhash_cmp(comp1->imag, comp2->imag);
2389 return rb_reg_equal(val, lit) ? 0 : -1;
2397rb_iseq_cdhash_hash(
VALUE a)
2399 switch (OBJ_BUILTIN_TYPE(a)) {
2402 return (st_index_t)a;
2410 return rb_rational_hash(a);
2412 return rb_complex_hash(a);
2422 rb_iseq_cdhash_hash,
2426cdhash_new(
size_t size)
2428 VALUE cdhash = rb_imemo_cdhash_new(size, &cdhash_type);
2436 st_table *tbl = rb_imemo_cdhash_tbl(cdhash);
2437 st_insert(tbl, key, val);
2444 st_table *tbl = rb_imemo_cdhash_tbl(cdhash);
2446 if (!st_lookup(tbl, key, &dontcare)) {
2447 st_insert(tbl, key, val);
2459cdhash_set_label_check_i(st_data_t key, st_data_t value, st_data_t argp,
int error)
2465cdhash_set_label_replace_i(st_data_t *key, st_data_t *value, st_data_t ptr,
int existing)
2469 *value = lobj->position - (data->pos+data->len);
2476 return INT2FIX(ISEQ_BODY(iseq)->ivc_size++);
2483 struct rb_id_table *tbl = ISEQ_COMPILE_DATA(iseq)->ivar_cache_table;
2485 if (rb_id_table_lookup(tbl,
id,&val)) {
2490 tbl = rb_id_table_create(1);
2491 ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
2493 val =
INT2FIX(ISEQ_BODY(iseq)->icvarc_size++);
2494 rb_id_table_insert(tbl,
id,val);
2498#define BADINSN_DUMP(anchor, list, dest) \
2499 dump_disasm_list_with_cursor(FIRST_ELEMENT(anchor), list, dest)
2501#define BADINSN_ERROR \
2502 (SIZED_FREE_N(generated_iseq, generated_iseq_size), \
2503 SIZED_FREE_N(insns_info, insns_info_size), \
2504 BADINSN_DUMP(anchor, list, NULL), \
2510 int stack_max = 0, sp = 0, line = 0;
2513 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2514 if (IS_LABEL(list)) {
2520 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2521 switch (list->type) {
2522 case ISEQ_ELEMENT_INSN:
2530 sp = calc_sp_depth(sp, iobj);
2532 BADINSN_DUMP(anchor, list, NULL);
2533 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2534 "argument stack underflow (%d)", sp);
2537 if (sp > stack_max) {
2541 line = iobj->insn_info.line_no;
2543 operands = iobj->operands;
2544 insn = iobj->insn_id;
2545 types = insn_op_types(insn);
2546 len = insn_len(insn);
2549 if (iobj->operand_size !=
len - 1) {
2551 BADINSN_DUMP(anchor, list, NULL);
2552 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2553 "operand size miss! (%d for %d)",
2554 iobj->operand_size,
len - 1);
2558 for (j = 0; types[j]; j++) {
2559 if (types[j] == TS_OFFSET) {
2563 BADINSN_DUMP(anchor, list, NULL);
2564 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2565 "unknown label: "LABEL_FORMAT, lobj->label_no);
2568 if (lobj->sp == -1) {
2571 else if (lobj->sp != sp) {
2572 VALUE path = rb_iseq_path(iseq);
2573 debugs(
"%.*s:%d: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2575 lobj->label_no, lobj->sp, sp);
2581 case ISEQ_ELEMENT_LABEL:
2584 if (lobj->sp == -1) {
2588 if (lobj->sp != sp) {
2589 VALUE path = rb_iseq_path(iseq);
2590 debugs(
"%.*s:%d: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2592 lobj->label_no, lobj->sp, sp);
2598 case ISEQ_ELEMENT_TRACE:
2603 case ISEQ_ELEMENT_ADJUST:
2608 sp = adjust->label ? adjust->label->sp : 0;
2609 if (adjust->line_no != -1 && orig_sp - sp < 0) {
2610 BADINSN_DUMP(anchor, list, NULL);
2611 COMPILE_ERROR(iseq, adjust->line_no,
2612 "iseq_set_sequence: adjust bug %d < %d",
2619 BADINSN_DUMP(anchor, list, NULL);
2620 COMPILE_ERROR(iseq, line,
"unknown list type: %d", list->type);
2627#ifdef USE_ISEQ_NODE_ID
2629add_node_id(uint8_t *node_ids,
unsigned int *node_ids_size,
int node_id,
int *prev_node_id)
2631 int delta = node_id - *prev_node_id;
2632 uint32_t zz = ((uint32_t)delta << 1) ^ (uint32_t)(delta >> 31);
2633 *prev_node_id = node_id;
2635 uint8_t
byte = zz & 0x7f;
2637 node_ids[(*node_ids_size)++] = zz ? (
byte | 0x80) : byte;
2644 int insns_info_index,
int code_index,
const INSN *iobj)
2646 if (insns_info_index == 0 ||
2647 insns_info[insns_info_index-1].line_no != iobj->insn_info.line_no ||
2648 insns_info[insns_info_index-1].events != iobj->insn_info.events) {
2649 insns_info[insns_info_index].line_no = iobj->insn_info.line_no;
2650 insns_info[insns_info_index].events = iobj->insn_info.events;
2651 positions[insns_info_index] = code_index;
2659 int insns_info_index,
int code_index,
const ADJUST *adjust)
2661 insns_info[insns_info_index].line_no = adjust->line_no;
2662 insns_info[insns_info_index].events = 0;
2663 positions[insns_info_index] = code_index;
2668array_to_idlist(
VALUE arr)
2673 for (
rb_len_t i = 0; i < size; i++) {
2682idlist_to_array(
const ID *ids)
2699 unsigned int *positions;
2701 VALUE *generated_iseq;
2705 int insn_num, code_index, insns_info_index, sp = 0;
2706 int stack_max = fix_sp_depth(iseq, anchor);
2708 if (stack_max < 0)
return COMPILE_NG;
2711 insn_num = code_index = 0;
2712 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2713 switch (list->type) {
2714 case ISEQ_ELEMENT_INSN:
2718 sp = calc_sp_depth(sp, iobj);
2720 events = iobj->insn_info.events |= events;
2721 if (ISEQ_COVERAGE(iseq)) {
2722 if (ISEQ_LINE_COVERAGE(iseq) && (events & RUBY_EVENT_COVERAGE_LINE) &&
2723 !(rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES)) {
2724 int line = iobj->insn_info.line_no - 1;
2725 if (line >= 0 && line <
RARRAY_LEN(ISEQ_LINE_COVERAGE(iseq))) {
2729 if (ISEQ_BRANCH_COVERAGE(iseq) && (events & RUBY_EVENT_COVERAGE_BRANCH)) {
2730 while (
RARRAY_LEN(ISEQ_PC2BRANCHINDEX(iseq)) <= code_index) {
2736 code_index += insn_data_length(iobj);
2741 case ISEQ_ELEMENT_LABEL:
2744 lobj->position = code_index;
2745 if (lobj->sp != sp) {
2746 VALUE path = rb_iseq_path(iseq);
2747 debugs(
"%.*s: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2749 lobj->label_no, lobj->sp, sp);
2754 case ISEQ_ELEMENT_TRACE:
2757 events |= trace->event;
2758 if (trace->event & RUBY_EVENT_COVERAGE_BRANCH) data = trace->data;
2761 case ISEQ_ELEMENT_ADJUST:
2764 if (adjust->line_no != -1) {
2766 sp = adjust->label ? adjust->label->sp : 0;
2767 if (orig_sp - sp > 0) {
2768 if (orig_sp - sp > 1) code_index++;
2780 const int generated_iseq_size = code_index;
2783 const int insns_info_size = insn_num;
2786 const int positions_size = insn_num;
2787 positions =
ALLOC_N(
unsigned int, insn_num);
2788#ifdef USE_ISEQ_NODE_ID
2789 uint8_t *node_ids =
ALLOC_N(uint8_t, (
size_t)insn_num * 5);
2790 unsigned int node_ids_size = 0;
2791 int prev_node_id = 0;
2793 if (ISEQ_IS_SIZE(body)) {
2797 body->is_entries = NULL;
2800 if (body->ci_size) {
2804 body->call_data = NULL;
2806 ISEQ_COMPILE_DATA(iseq)->ci_index = 0;
2813 iseq_bits_t * mark_offset_bits;
2814 int code_size = code_index;
2816 bool needs_bitmap =
false;
2818 const size_t mark_offset_bits_size = ISEQ_MBITS_BUFLEN(code_index);
2819 if (mark_offset_bits_size == 1) {
2820 mark_offset_bits = &ISEQ_COMPILE_DATA(iseq)->mark_bits.single;
2821 ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit =
true;
2824 mark_offset_bits =
ZALLOC_N(iseq_bits_t, mark_offset_bits_size);
2825 ISEQ_COMPILE_DATA(iseq)->mark_bits.list = mark_offset_bits;
2826 ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit =
false;
2829 ISEQ_COMPILE_DATA(iseq)->iseq_encoded = (
void *)generated_iseq;
2830 ISEQ_COMPILE_DATA(iseq)->iseq_size = code_index;
2832 list = FIRST_ELEMENT(anchor);
2833 insns_info_index = code_index = sp = 0;
2836 switch (list->type) {
2837 case ISEQ_ELEMENT_INSN:
2845 sp = calc_sp_depth(sp, iobj);
2847 operands = iobj->operands;
2848 insn = iobj->insn_id;
2849 generated_iseq[code_index] = insn;
2850 types = insn_op_types(insn);
2851 len = insn_len(insn);
2853 for (j = 0; types[j]; j++) {
2854 char type = types[j];
2862 generated_iseq[code_index + 1 + j] = lobj->position - (code_index +
len);
2867 VALUE map = operands[j];
2870 data.pos = code_index;
2872 st_foreach_with_replace(rb_imemo_cdhash_tbl(map), cdhash_set_label_check_i, cdhash_set_label_replace_i, (
VALUE)&data);
2874 generated_iseq[code_index + 1 + j] = map;
2875 ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
2877 needs_bitmap =
true;
2882 generated_iseq[code_index + 1 + j] =
FIX2INT(operands[j]);
2887 VALUE v = operands[j];
2888 generated_iseq[code_index + 1 + j] = v;
2892 ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
2893 needs_bitmap =
true;
2900 unsigned int ic_index = ISEQ_COMPILE_DATA(iseq)->ic_index++;
2901 IC ic = &ISEQ_IS_ENTRY_START(body,
type)[ic_index].ic_cache;
2902 if (UNLIKELY(ic_index >= body->ic_size)) {
2903 BADINSN_DUMP(anchor, &iobj->link, 0);
2904 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2905 "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
2906 ic_index, ISEQ_IS_SIZE(body));
2909 ic->
segments = array_to_idlist(operands[j]);
2911 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
2916 unsigned int ic_index =
FIX2UINT(operands[j]);
2918 IVC cache = ((
IVC)&body->is_entries[ic_index]);
2920 if (insn == BIN(setinstancevariable)) {
2921 cache->iv_set_name =
SYM2ID(operands[j - 1]);
2922 cache->value = IVAR_CACHE_INIT;
2925 cache->iv_set_name = 0;
2926 cache->value = rb_getivar_cache_pack(ROOT_SHAPE_ID, ATTR_INDEX_NOT_SET);
2932 unsigned int ic_index =
FIX2UINT(operands[j]);
2933 IC ic = &ISEQ_IS_ENTRY_START(body,
type)[ic_index].ic_cache;
2934 if (UNLIKELY(ic_index >= ISEQ_IS_SIZE(body))) {
2935 BADINSN_DUMP(anchor, &iobj->link, 0);
2936 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2937 "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
2938 ic_index, ISEQ_IS_SIZE(body));
2940 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
2947 RUBY_ASSERT(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size);
2948 struct rb_call_data *cd = &body->call_data[ISEQ_COMPILE_DATA(iseq)->ci_index++];
2950 cd->cc = vm_cc_empty();
2951 generated_iseq[code_index + 1 + j] = (
VALUE)cd;
2955 generated_iseq[code_index + 1 + j] =
SYM2ID(operands[j]);
2958 generated_iseq[code_index + 1 + j] = operands[j];
2961 generated_iseq[code_index + 1 + j] = operands[j];
2964 BADINSN_ERROR(iseq, iobj->insn_info.line_no,
2965 "unknown operand type: %c",
type);
2969 if (add_insn_info(insns_info, positions, insns_info_index, code_index, iobj)) insns_info_index++;
2970#ifdef USE_ISEQ_NODE_ID
2971 add_node_id(node_ids, &node_ids_size, iobj->insn_info.node_id, &prev_node_id);
2976 case ISEQ_ELEMENT_LABEL:
2979 if (lobj->sp != sp) {
2980 VALUE path = rb_iseq_path(iseq);
2981 debugs(
"%.*s: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2983 lobj->label_no, lobj->sp, sp);
2988 case ISEQ_ELEMENT_ADJUST:
2993 if (adjust->label) {
2994 sp = adjust->label->sp;
3000 if (adjust->line_no != -1) {
3001 const int diff = orig_sp - sp;
3003 if (insns_info_index == 0) {
3004 COMPILE_ERROR(iseq, adjust->line_no,
3005 "iseq_set_sequence: adjust bug (ISEQ_ELEMENT_ADJUST must not be the first in iseq)");
3007 if (add_adjust_info(insns_info, positions, insns_info_index, code_index, adjust)) insns_info_index++;
3008#ifdef USE_ISEQ_NODE_ID
3009 add_node_id(node_ids, &node_ids_size, -1, &prev_node_id);
3013 generated_iseq[code_index++] = BIN(adjuststack);
3014 generated_iseq[code_index++] = orig_sp - sp;
3016 else if (diff == 1) {
3017 generated_iseq[code_index++] = BIN(pop);
3019 else if (diff < 0) {
3020 int label_no = adjust->label ? adjust->label->label_no : -1;
3021 SIZED_FREE_N(generated_iseq, generated_iseq_size);
3022 SIZED_FREE_N(insns_info, insns_info_size);
3023 SIZED_FREE_N(positions, positions_size);
3024#ifdef USE_ISEQ_NODE_ID
3025 SIZED_FREE_N(node_ids, (
size_t)insns_info_size * 5);
3027 if (ISEQ_MBITS_BUFLEN(code_size) > 1) {
3028 SIZED_FREE_N(mark_offset_bits, ISEQ_MBITS_BUFLEN(code_index));
3030 debug_list(anchor, list);
3031 COMPILE_ERROR(iseq, adjust->line_no,
3032 "iseq_set_sequence: adjust bug to %d %d < %d",
3033 label_no, orig_sp, sp);
3046 body->iseq_encoded = (
void *)generated_iseq;
3047 body->iseq_size = code_index;
3048 body->stack_max = stack_max;
3050 if (ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit) {
3051 body->mark_bits.single = ISEQ_COMPILE_DATA(iseq)->mark_bits.single;
3055 body->mark_bits.list = mark_offset_bits;
3058 body->mark_bits.list = NULL;
3059 ISEQ_COMPILE_DATA(iseq)->mark_bits.list = NULL;
3060 SIZED_FREE_N(mark_offset_bits, mark_offset_bits_size);
3065 body->insns_info.body = insns_info;
3066 body->insns_info.positions_or_succ_index_table.positions = positions;
3067#ifdef USE_ISEQ_NODE_ID
3068 body->insns_info.node_ids = node_ids;
3072 body->insns_info.body = insns_info;
3073 SIZED_REALLOC_N(positions,
unsigned int, insns_info_index, positions_size);
3074 body->insns_info.positions_or_succ_index_table.positions = positions;
3075 body->insns_info.size = insns_info_index;
3076#ifdef USE_ISEQ_NODE_ID
3077 SIZED_REALLOC_N(node_ids, uint8_t, node_ids_size, (
size_t)insns_info_size * 5);
3078 body->insns_info.node_ids = node_ids;
3079 body->insns_info.node_ids_size = node_ids_size;
3086label_get_position(
LABEL *lobj)
3088 return lobj->position;
3092label_get_sp(
LABEL *lobj)
3098iseq_set_exception_table(
rb_iseq_t *iseq)
3100 const VALUE *tptr, *ptr;
3101 unsigned int tlen, i, table_size = 0;
3104 ISEQ_BODY(iseq)->catch_table = NULL;
3106 VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
3107 if (
NIL_P(catch_table_ary))
return COMPILE_OK;
3115 for (i = 0; i < table->size; i++) {
3117 int start = label_get_position((
LABEL *)(ptr[1] & ~1));
3118 int end = label_get_position((
LABEL *)(ptr[2] & ~1));
3121 if (start < 0 || end < 0) {
3122 if ((ptr[0] & 0xffff) != CATCH_TYPE_ENSURE)
continue;
3123 if (start < 0) start = 0;
3124 if (end < 0) end = 0;
3128 cont = label_get_position(lobj);
3129 if (cont < 0)
continue;
3130 sp = label_get_sp(lobj);
3133 entry = UNALIGNED_MEMBER_PTR(table, entries[table_size++]);
3134 entry->type = (
enum rb_catch_type)(ptr[0] & 0xffff);
3135 entry->start = (
unsigned int)start;
3136 entry->end = (
unsigned int)end;
3142 entry->cont = (
unsigned int)cont;
3146 if (entry->type == CATCH_TYPE_RESCUE ||
3147 entry->type == CATCH_TYPE_BREAK ||
3148 entry->type == CATCH_TYPE_NEXT) {
3157 table->size = table_size;
3158 if (table_size == 0) {
3159 ruby_xfree_sized(table, iseq_catch_table_bytes(tlen));
3162 else if (table_size < tlen) {
3163 table = ruby_xrealloc(table, iseq_catch_table_bytes(table_size));
3165 ISEQ_BODY(iseq)->catch_table = table;
3166 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0);
3187 VALUE *opt_table = (
VALUE *)ISEQ_BODY(iseq)->param.opt_table;
3189 if (ISEQ_BODY(iseq)->param.flags.has_opt) {
3190 for (i = 0; i < ISEQ_BODY(iseq)->param.opt_num + 1; i++) {
3191 opt_table[i] = label_get_position((
LABEL *)opt_table[i]);
3198get_destination_insn(
INSN *iobj)
3204 list = lobj->link.next;
3206 switch (list->type) {
3207 case ISEQ_ELEMENT_INSN:
3208 case ISEQ_ELEMENT_ADJUST:
3210 case ISEQ_ELEMENT_LABEL:
3213 case ISEQ_ELEMENT_TRACE:
3216 events |= trace->event;
3224 if (list && IS_INSN(list)) {
3226 iobj->insn_info.events |= events;
3232get_next_insn(
INSN *iobj)
3237 if (IS_INSN(list) || IS_ADJUST(list)) {
3246get_prev_insn(
INSN *iobj)
3251 if (IS_INSN(list) || IS_ADJUST(list)) {
3260unref_destination(
INSN *iobj,
int pos)
3262 LABEL *lobj = (
LABEL *)OPERAND_AT(iobj, pos);
3264 if (!lobj->refcnt) ELEM_REMOVE(&lobj->link);
3268replace_destination(
INSN *dobj,
INSN *nobj)
3270 VALUE n = OPERAND_AT(nobj, 0);
3273 if (dl == nl)
return false;
3276 OPERAND_AT(dobj, 0) = n;
3277 if (!dl->refcnt) ELEM_REMOVE(&dl->link);
3282find_destination(
INSN *i)
3284 int pos,
len = insn_len(i->insn_id);
3285 for (pos = 0; pos <
len; ++pos) {
3286 if (insn_op_types(i->insn_id)[pos] == TS_OFFSET) {
3287 return (
LABEL *)OPERAND_AT(i, pos);
3294 const unsigned int capacity;
3297 unsigned int *stamps;
3303 unsigned int no = (
unsigned int)lab->label_no;
3304 return unref->stamps[no] == unref->gen ? unref->counts[no] : 0;
3310 unsigned int no = (
unsigned int)lab->label_no;
3311 if (unref->stamps[no] != unref->gen) {
3312 unref->stamps[no] = unref->gen;
3313 unref->counts[no] = 0;
3315 unref->counts[no]++;
3321 LINK_ELEMENT *first = i, *end, *scan, *pending_end = 0;
3325 if (++unref->gen == 0) {
3327 MEMZERO(unref->stamps,
unsigned int, unref->capacity);
3335 if (IS_INSN(scan)) {
3336 if (IS_INSN_ID(scan, leave)) {
3341 else if ((lab = find_destination((
INSN *)scan)) != 0) {
3342 unreachable_unref_increment(unref, lab);
3343 if (lab == pending && lab->refcnt <= unreachable_unref_count(unref, lab)) {
3348 else if (IS_LABEL(scan)) {
3349 lab = (
LABEL *)scan;
3350 if (lab->unremovable) {
3354 if (lab->refcnt > unreachable_unref_count(unref, lab)) {
3357 pending_end = (scan == first) ? 0 : end;
3361 else if (IS_ADJUST(scan)) {
3365 if (!pending) end = scan;
3366 }
while ((scan = scan->next) != 0);
3369 if (!pending_end)
return 0;
3376 VALUE insn = INSN_OF(i);
3377 int pos,
len = insn_len(insn);
3378 for (pos = 0; pos <
len; ++pos) {
3379 switch (insn_op_types(insn)[pos]) {
3381 unref_destination((
INSN *)i, pos);
3390 }
while ((i != end) && (i = i->next) != 0);
3397 switch (OPERAND_AT(iobj, 0)) {
3399 ELEM_REMOVE(&iobj->link);
3402 ELEM_REMOVE(&iobj->link);
3405 iobj->insn_id = BIN(adjuststack);
3411is_frozen_putstring(
INSN *insn,
VALUE *op)
3413 if (IS_INSN_ID(insn, dupstring) || IS_INSN_ID(insn, dupchilledstring)) {
3414 *op = OPERAND_AT(insn, 0);
3417 else if (IS_INSN_ID(insn, putobject)) {
3418 *op = OPERAND_AT(insn, 0);
3429 if (prev->type == ISEQ_ELEMENT_LABEL) {
3431 if (label->refcnt > 0) {
3435 else if (prev->type == ISEQ_ELEMENT_INSN) {
3468 INSN *niobj, *ciobj, *dup = 0;
3472 switch (INSN_OF(iobj)) {
3473 case BIN(dupstring):
3474 case BIN(dupchilledstring):
3480 case BIN(putobject):
3483 default:
return FALSE;
3486 ciobj = (
INSN *)get_next_insn(iobj);
3487 if (IS_INSN_ID(ciobj, jump)) {
3488 ciobj = (
INSN *)get_next_insn((
INSN*)OPERAND_AT(ciobj, 0));
3490 if (IS_INSN_ID(ciobj, dup)) {
3491 ciobj = (
INSN *)get_next_insn(dup = ciobj);
3493 if (!ciobj || !IS_INSN_ID(ciobj, checktype))
return FALSE;
3494 niobj = (
INSN *)get_next_insn(ciobj);
3499 switch (INSN_OF(niobj)) {
3501 if (OPERAND_AT(ciobj, 0) ==
type) {
3502 dest = (
LABEL *)OPERAND_AT(niobj, 0);
3505 case BIN(branchunless):
3506 if (OPERAND_AT(ciobj, 0) !=
type) {
3507 dest = (
LABEL *)OPERAND_AT(niobj, 0);
3513 line = ciobj->insn_info.line_no;
3514 node_id = ciobj->insn_info.node_id;
3516 if (niobj->link.next && IS_LABEL(niobj->link.next)) {
3517 dest = (
LABEL *)niobj->link.next;
3520 dest = NEW_LABEL(line);
3521 ELEM_INSERT_NEXT(&niobj->link, &dest->link);
3524 INSERT_AFTER_INSN1(iobj, line, node_id, jump, dest);
3526 if (!dup) INSERT_AFTER_INSN(iobj, line, node_id, pop);
3533 const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
3534 vm_ci_flag(ci) | add,
3544 const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
3552#define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)
3555iseq_reg_compile(
rb_iseq_t *iseq,
VALUE str,
int options,
const char *sourcefile,
int sourceline)
3557 VALUE errinfo = rb_errinfo();
3558 VALUE re = rb_reg_compile(str, options, sourcefile, sourceline);
3560 VALUE message = rb_attr_get(rb_errinfo(), idMesg);
3561 rb_set_errinfo(errinfo);
3562 COMPILE_ERROR(iseq, sourceline,
"%" PRIsVALUE, message);
3576 optimize_checktype(iseq, iobj);
3578 if (IS_INSN_ID(iobj, jump)) {
3579 INSN *niobj, *diobj, *piobj;
3580 diobj = (
INSN *)get_destination_insn(iobj);
3581 niobj = (
INSN *)get_next_insn(iobj);
3583 if (diobj == niobj) {
3590 unref_destination(iobj, 0);
3591 ELEM_REMOVE(&iobj->link);
3594 else if (iobj != diobj && IS_INSN(&diobj->link) &&
3595 IS_INSN_ID(diobj, jump) &&
3596 OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0) &&
3597 diobj->insn_info.events == 0) {
3608 if (replace_destination(iobj, diobj)) {
3609 remove_unreachable_chunk(iseq, unref, iobj->link.next);
3613 else if (IS_INSN_ID(diobj, leave)) {
3626 unref_destination(iobj, 0);
3627 iobj->insn_id = BIN(leave);
3628 iobj->operand_size = 0;
3629 iobj->insn_info = diobj->insn_info;
3632 else if (IS_INSN(iobj->link.prev) &&
3633 (piobj = (
INSN *)iobj->link.prev) &&
3634 (IS_INSN_ID(piobj, branchif) ||
3635 IS_INSN_ID(piobj, branchunless))) {
3636 INSN *pdiobj = (
INSN *)get_destination_insn(piobj);
3637 if (niobj == pdiobj) {
3638 int refcnt = IS_LABEL(piobj->link.next) ?
3639 ((
LABEL *)piobj->link.next)->refcnt : 0;
3654 piobj->insn_id = (IS_INSN_ID(piobj, branchif))
3655 ? BIN(branchunless) : BIN(branchif);
3656 if (replace_destination(piobj, iobj) && refcnt <= 1) {
3657 ELEM_REMOVE(&iobj->link);
3664 else if (diobj == pdiobj) {
3678 INSN *popiobj = new_insn_core(iseq, iobj->insn_info.line_no, iobj->insn_info.node_id, BIN(pop), 0, 0);
3679 ELEM_REPLACE(&piobj->link, &popiobj->link);
3682 if (remove_unreachable_chunk(iseq, unref, iobj->link.next)) {
3696 if (IS_INSN_ID(iobj, newrange)) {
3697 INSN *
const range = iobj;
3699 VALUE str_beg, str_end;
3701 if ((end = (
INSN *)get_prev_insn(range)) != 0 &&
3702 is_frozen_putstring(end, &str_end) &&
3703 (beg = (
INSN *)get_prev_insn(end)) != 0 &&
3704 is_frozen_putstring(beg, &str_beg) &&
3705 !(insn_has_label_before(&beg->link) || insn_has_label_before(&end->link))) {
3706 int excl =
FIX2INT(OPERAND_AT(range, 0));
3709 ELEM_REMOVE(&beg->link);
3710 ELEM_REMOVE(&end->link);
3711 range->insn_id = BIN(putobject);
3712 OPERAND_AT(range, 0) = lit_range;
3717 if (IS_INSN_ID(iobj, leave)) {
3718 remove_unreachable_chunk(iseq, unref, iobj->link.next);
3730 if (IS_INSN_ID(iobj, duparray)) {
3732 if (IS_INSN(next) && (IS_INSN_ID(next, concatarray) || IS_INSN_ID(next, concattoarray))) {
3733 iobj->insn_id = BIN(putobject);
3743 if (IS_INSN_ID(iobj, duparray)) {
3745 if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
3749 if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
3750 VALUE ary = iobj->operands[0];
3753 insn_replace_with_operands(iseq, iobj, BIN(opt_ary_freeze), 2, ary, (
VALUE)ci);
3765 if (IS_INSN_ID(iobj, duphash)) {
3767 if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
3771 if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
3772 VALUE hash = iobj->operands[0];
3776 insn_replace_with_operands(iseq, iobj, BIN(opt_hash_freeze), 2, hash, (
VALUE)ci);
3788 if (IS_INSN_ID(iobj, newarray) && iobj->operands[0] ==
INT2FIX(0)) {
3790 if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
3794 if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
3795 insn_replace_with_operands(iseq, iobj, BIN(opt_ary_freeze), 2, rb_cArray_empty_frozen, (
VALUE)ci);
3807 if (IS_INSN_ID(iobj, newhash) && iobj->operands[0] ==
INT2FIX(0)) {
3809 if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
3813 if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
3814 insn_replace_with_operands(iseq, iobj, BIN(opt_hash_freeze), 2, rb_cHash_empty_frozen, (
VALUE)ci);
3820 if (IS_INSN_ID(iobj, branchif) ||
3821 IS_INSN_ID(iobj, branchnil) ||
3822 IS_INSN_ID(iobj, branchunless)) {
3831 INSN *nobj = (
INSN *)get_destination_insn(iobj);
3846 int stop_optimization =
3847 nobj->link.type == ISEQ_ELEMENT_INSN &&
3848 (nobj->insn_info.events & (
RUBY_EVENT_LINE | RUBY_EVENT_COVERAGE_LINE));
3849 if (!stop_optimization) {
3850 INSN *pobj = (
INSN *)iobj->link.prev;
3853 if (!IS_INSN(&pobj->link))
3855 else if (IS_INSN_ID(pobj, dup))
3860 if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) {
3861 if (!replace_destination(iobj, nobj))
break;
3863 else if (prev_dup && IS_INSN(&nobj->link) && IS_INSN_ID(nobj, dup) &&
3864 !!(nobj = (
INSN *)nobj->link.next) &&
3865 IS_INSN(&nobj->link) &&
3867 nobj->insn_id == iobj->insn_id) {
3883 if (!replace_destination(iobj, nobj))
break;
3911 if (prev_dup && IS_INSN(pobj->link.prev)) {
3912 pobj = (
INSN *)pobj->link.prev;
3914 if (IS_INSN_ID(pobj, putobject)) {
3915 cond = (IS_INSN_ID(iobj, branchif) ?
3916 OPERAND_AT(pobj, 0) !=
Qfalse :
3917 IS_INSN_ID(iobj, branchunless) ?
3918 OPERAND_AT(pobj, 0) ==
Qfalse :
3921 else if (IS_INSN_ID(pobj, dupstring) ||
3922 IS_INSN_ID(pobj, duparray) ||
3923 IS_INSN_ID(pobj, newarray)) {
3924 cond = IS_INSN_ID(iobj, branchif);
3926 else if (IS_INSN_ID(pobj, putnil)) {
3927 cond = !IS_INSN_ID(iobj, branchif);
3930 if (prev_dup || !IS_INSN_ID(pobj, newarray)) {
3931 ELEM_REMOVE(iobj->link.prev);
3933 else if (!iseq_pop_newarray(iseq, pobj)) {
3934 pobj = new_insn_core(iseq, pobj->insn_info.line_no, pobj->insn_info.node_id, BIN(pop), 0, NULL);
3935 ELEM_INSERT_PREV(&iobj->link, &pobj->link);
3939 pobj = new_insn_core(iseq, pobj->insn_info.line_no, pobj->insn_info.node_id, BIN(putnil), 0, NULL);
3940 ELEM_INSERT_NEXT(&iobj->link, &pobj->link);
3942 iobj->insn_id = BIN(jump);
3946 unref_destination(iobj, 0);
3947 ELEM_REMOVE(&iobj->link);
3954 if (!dest || !IS_INSN(dest))
break;
3955 nobj = (
INSN *)dest;
3961 if (IS_INSN_ID(iobj, pop)) {
3969 if (IS_INSN(prev)) {
3970 enum ruby_vminsn_type previ = ((
INSN *)prev)->insn_id;
3971 if (previ == BIN(putobject) || previ == BIN(putnil) ||
3972 previ == BIN(putself) || previ == BIN(dupstring) ||
3973 previ == BIN(dupchilledstring) ||
3974 previ == BIN(dup) ||
3975 previ == BIN(getlocal) ||
3976 previ == BIN(getblockparam) ||
3977 previ == BIN(getblockparamproxy) ||
3978 previ == BIN(getinstancevariable) ||
3979 previ == BIN(duparray)) {
3983 ELEM_REMOVE(&iobj->link);
3985 else if (previ == BIN(newarray) && iseq_pop_newarray(iseq, (
INSN*)prev)) {
3986 ELEM_REMOVE(&iobj->link);
3988 else if (previ == BIN(concatarray)) {
3990 INSERT_BEFORE_INSN1(piobj, piobj->insn_info.line_no, piobj->insn_info.node_id, splatarray,
Qfalse);
3991 INSN_OF(piobj) = BIN(pop);
3993 else if (previ == BIN(concatstrings)) {
3994 if (OPERAND_AT(prev, 0) ==
INT2FIX(1)) {
3998 ELEM_REMOVE(&iobj->link);
3999 INSN_OF(prev) = BIN(adjuststack);
4005 if (IS_INSN_ID(iobj, newarray) ||
4006 IS_INSN_ID(iobj, duparray) ||
4007 IS_INSN_ID(iobj, concatarray) ||
4008 IS_INSN_ID(iobj, splatarray) ||
4018 if (IS_INSN(next) && IS_INSN_ID(next, splatarray)) {
4024 if (IS_INSN_ID(iobj, newarray)) {
4026 if (IS_INSN(next) && IS_INSN_ID(next, expandarray) &&
4027 OPERAND_AT(next, 1) ==
INT2FIX(0)) {
4029 op1 = OPERAND_AT(iobj, 0);
4030 op2 = OPERAND_AT(next, 0);
4041 INSN_OF(iobj) = BIN(swap);
4042 iobj->operand_size = 0;
4051 INSN_OF(iobj) = BIN(opt_reverse);
4056 INSN_OF(iobj) = BIN(opt_reverse);
4057 OPERAND_AT(iobj, 0) = OPERAND_AT(next, 0);
4067 for (; diff > 0; diff--) {
4068 INSERT_BEFORE_INSN(iobj, iobj->insn_info.line_no, iobj->insn_info.node_id, pop);
4079 for (; diff < 0; diff++) {
4080 INSERT_BEFORE_INSN(iobj, iobj->insn_info.line_no, iobj->insn_info.node_id, putnil);
4087 if (IS_INSN_ID(iobj, duparray)) {
4096 if (IS_INSN(next) && IS_INSN_ID(next, expandarray)) {
4097 INSN_OF(iobj) = BIN(putobject);
4101 if (IS_INSN_ID(iobj, anytostring)) {
4109 if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) &&
4110 OPERAND_AT(next, 0) ==
INT2FIX(1)) {
4115 if (IS_INSN_ID(iobj, dupstring) || IS_INSN_ID(iobj, dupchilledstring) ||
4123 if (IS_NEXT_INSN_ID(&iobj->link, concatstrings) &&
4124 RSTRING_LEN(OPERAND_AT(iobj, 0)) == 0) {
4125 INSN *next = (
INSN *)iobj->link.next;
4126 if ((OPERAND_AT(next, 0) = FIXNUM_INC(OPERAND_AT(next, 0), -1)) ==
INT2FIX(1)) {
4127 ELEM_REMOVE(&next->link);
4129 ELEM_REMOVE(&iobj->link);
4131 if (IS_NEXT_INSN_ID(&iobj->link, toregexp)) {
4132 INSN *next = (
INSN *)iobj->link.next;
4133 if (OPERAND_AT(next, 1) ==
INT2FIX(1)) {
4134 VALUE src = OPERAND_AT(iobj, 0);
4135 int opt = (int)
FIX2LONG(OPERAND_AT(next, 0));
4136 VALUE path = rb_iseq_path(iseq);
4137 int line = iobj->insn_info.line_no;
4138 VALUE re = iseq_reg_compile(iseq, src, opt, RSTRING_PTR(path), line);
4143 iobj->insn_id = BIN(putobject);
4145 ELEM_REMOVE(iobj->link.next);
4150 if (IS_INSN_ID(iobj, concatstrings)) {
4159 if (IS_INSN(next) && IS_INSN_ID(next, jump))
4160 next = get_destination_insn(jump = (
INSN *)next);
4161 if (IS_INSN(next) && IS_INSN_ID(next, concatstrings)) {
4162 int n =
FIX2INT(OPERAND_AT(iobj, 0)) +
FIX2INT(OPERAND_AT(next, 0)) - 1;
4163 OPERAND_AT(iobj, 0) =
INT2FIX(n);
4165 LABEL *label = ((
LABEL *)OPERAND_AT(jump, 0));
4166 if (!--label->refcnt) {
4167 ELEM_REMOVE(&label->link);
4170 label = NEW_LABEL(0);
4171 OPERAND_AT(jump, 0) = (
VALUE)label;
4174 ELEM_INSERT_NEXT(next, &label->link);
4175 CHECK(iseq_peephole_optimize(iseq, unref, get_next_insn(jump), do_tailcallopt));
4183 if (do_tailcallopt &&
4184 (IS_INSN_ID(iobj, send) ||
4185 IS_INSN_ID(iobj, invokesuper))) {
4194 if (iobj->link.next) {
4197 if (!IS_INSN(next)) {
4201 switch (INSN_OF(next)) {
4210 next = get_destination_insn((
INSN *)next);
4224 if (IS_INSN_ID(piobj, send) ||
4225 IS_INSN_ID(piobj, invokesuper)) {
4226 if (OPERAND_AT(piobj, 1) == 0) {
4227 ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
4228 OPERAND_AT(piobj, 0) = (
VALUE)ci;
4233 ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
4234 OPERAND_AT(piobj, 0) = (
VALUE)ci;
4240 if (IS_INSN_ID(iobj, dup)) {
4241 if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) {
4252 if (IS_NEXT_INSN_ID(set1, setlocal)) {
4254 if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
4255 OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
4257 ELEM_REMOVE(&iobj->link);
4270 else if (IS_NEXT_INSN_ID(set1, dup) &&
4271 IS_NEXT_INSN_ID(set1->next, setlocal)) {
4272 set2 = set1->next->next;
4273 if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
4274 OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
4275 ELEM_REMOVE(set1->next);
4289 if (IS_INSN_ID(iobj, getlocal)) {
4291 if (IS_NEXT_INSN_ID(niobj, dup)) {
4292 niobj = niobj->next;
4294 if (IS_NEXT_INSN_ID(niobj, setlocal)) {
4296 if (OPERAND_AT(iobj, 0) == OPERAND_AT(set1, 0) &&
4297 OPERAND_AT(iobj, 1) == OPERAND_AT(set1, 1)) {
4313 if (IS_INSN_ID(iobj, opt_invokebuiltin_delegate)) {
4314 if (IS_TRACE(iobj->link.next)) {
4315 if (IS_NEXT_INSN_ID(iobj->link.next, leave)) {
4316 iobj->insn_id = BIN(opt_invokebuiltin_delegate_leave);
4318 if (iobj == (
INSN *)list && bf->argc == 0 && (ISEQ_BODY(iseq)->builtin_attrs & BUILTIN_ATTR_LEAF)) {
4319 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_LEAF;
4332 if (IS_INSN_ID(iobj, getblockparam)) {
4333 if (IS_NEXT_INSN_ID(&iobj->link, branchif) || IS_NEXT_INSN_ID(&iobj->link, branchunless)) {
4334 iobj->insn_id = BIN(getblockparamproxy);
4338 if (IS_INSN_ID(iobj, splatarray) && OPERAND_AT(iobj, 0) ==
false) {
4340 if (IS_NEXT_INSN_ID(niobj, duphash)) {
4341 niobj = niobj->next;
4343 unsigned int set_flags = 0, unset_flags = 0;
4356 if (IS_NEXT_INSN_ID(niobj, send)) {
4357 siobj = niobj->next;
4358 set_flags = VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT;
4359 unset_flags = VM_CALL_ARGS_BLOCKARG;
4374 else if ((IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
4375 IS_NEXT_INSN_ID(niobj, getblockparamproxy)) && (IS_NEXT_INSN_ID(niobj->next, send))) {
4376 siobj = niobj->next->next;
4377 set_flags = VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT|VM_CALL_ARGS_BLOCKARG;
4382 unsigned int flags = vm_ci_flag(ci);
4383 if ((flags & set_flags) == set_flags && !(flags & unset_flags)) {
4384 ((
INSN*)niobj)->insn_id = BIN(putobject);
4387 const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
4388 flags & ~VM_CALL_KW_SPLAT_MUT, vm_ci_argc(ci), vm_ci_kwarg(ci));
4390 OPERAND_AT(siobj, 0) = (
VALUE)nci;
4404 if (IS_NEXT_INSN_ID(&iobj->link, swap)) {
4409 if (IS_INDEPENDENT_INSN(first) && IS_INDEPENDENT_INSN(second)) {
4411 ELEM_SWAP(first, second);
4419insn_set_specialized_instruction(
rb_iseq_t *iseq,
INSN *iobj,
int insn_id)
4421 if (insn_id == BIN(opt_neq)) {
4422 VALUE original_ci = iobj->operands[0];
4423 VALUE new_ci = (
VALUE)new_callinfo(iseq, idEq, 1, 0, NULL, FALSE);
4424 insn_replace_with_operands(iseq, iobj, insn_id, 2, new_ci, original_ci);
4427 iobj->insn_id = insn_id;
4428 iobj->operand_size = insn_len(insn_id) - 1;
4438 if (IS_INSN_ID(iobj, newarray) && iobj->link.next &&
4439 IS_INSN(iobj->link.next)) {
4443 INSN *niobj = (
INSN *)iobj->link.next;
4444 if (IS_INSN_ID(niobj, send)) {
4446 if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0) {
4448 switch (vm_ci_mid(ci)) {
4450 method =
INT2FIX(VM_OPT_NEWARRAY_SEND_MAX);
4453 method =
INT2FIX(VM_OPT_NEWARRAY_SEND_MIN);
4456 method =
INT2FIX(VM_OPT_NEWARRAY_SEND_HASH);
4461 VALUE num = iobj->operands[0];
4462 insn_replace_with_operands(iseq, iobj, BIN(opt_newarray_send), 2, num, method);
4463 ELEM_REMOVE(&niobj->link);
4468 else if ((IS_INSN_ID(niobj, dupstring) || IS_INSN_ID(niobj, dupchilledstring) ||
4470 IS_NEXT_INSN_ID(&niobj->link, send)) {
4472 if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idPack) {
4473 VALUE num = iobj->operands[0];
4474 insn_replace_with_operands(iseq, iobj, BIN(opt_newarray_send), 2, FIXNUM_INC(num, 1),
INT2FIX(VM_OPT_NEWARRAY_SEND_PACK));
4475 ELEM_REMOVE(&iobj->link);
4476 ELEM_REMOVE(niobj->link.next);
4477 ELEM_INSERT_NEXT(&niobj->link, &iobj->link);
4483 else if ((IS_INSN_ID(niobj, dupstring) || IS_INSN_ID(niobj, dupchilledstring) ||
4485 IS_NEXT_INSN_ID(&niobj->link, getlocal) &&
4486 (niobj->link.next && IS_NEXT_INSN_ID(niobj->link.next, send))) {
4489 if (vm_ci_mid(ci) == idPack && vm_ci_argc(ci) == 2 &&
4490 (kwarg && kwarg->keyword_len == 1 && kwarg->keywords[0] ==
rb_id2sym(idBuffer))) {
4491 VALUE num = iobj->operands[0];
4492 insn_replace_with_operands(iseq, iobj, BIN(opt_newarray_send), 2, FIXNUM_INC(num, 2),
INT2FIX(VM_OPT_NEWARRAY_SEND_PACK_BUFFER));
4494 ELEM_REMOVE((niobj->link.next)->next);
4496 ELEM_REMOVE(&iobj->link);
4498 ELEM_INSERT_NEXT(niobj->link.next, &iobj->link);
4506 if ((IS_INSN_ID(niobj, dupstring) || IS_INSN_ID(niobj, dupchilledstring) ||
4507 IS_INSN_ID(niobj, putobject) ||
4508 IS_INSN_ID(niobj, putself) ||
4509 IS_INSN_ID(niobj, getlocal) ||
4510 IS_INSN_ID(niobj, getinstancevariable)) &&
4511 IS_NEXT_INSN_ID(&niobj->link, send)) {
4518 sendobj = sendobj->next;
4519 ci = (
struct rb_callinfo *)OPERAND_AT(sendobj, 0);
4520 }
while (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && IS_NEXT_INSN_ID(sendobj, send));
4523 if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idIncludeP) {
4524 VALUE num = iobj->operands[0];
4526 insn_replace_with_operands(iseq, sendins, BIN(opt_newarray_send), 2, FIXNUM_INC(num, 1),
INT2FIX(VM_OPT_NEWARRAY_SEND_INCLUDE_P));
4528 ELEM_REMOVE(&iobj->link);
4542 if (IS_INSN_ID(iobj, duparray) && iobj->link.next && IS_INSN(iobj->link.next)) {
4543 INSN *niobj = (
INSN *)iobj->link.next;
4544 if ((IS_INSN_ID(niobj, getlocal) ||
4545 IS_INSN_ID(niobj, getinstancevariable) ||
4546 IS_INSN_ID(niobj, putself) ||
4547 IS_INSN_ID(niobj, putobject) ||
4548 IS_INSN_ID(niobj, putnil)) &&
4549 IS_NEXT_INSN_ID(&niobj->link, send)) {
4556 sendobj = sendobj->next;
4557 ci = (
struct rb_callinfo *)OPERAND_AT(sendobj, 0);
4558 }
while (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && IS_NEXT_INSN_ID(sendobj, send));
4560 if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idIncludeP) {
4562 VALUE ary = iobj->operands[0];
4566 insn_replace_with_operands(iseq, sendins, BIN(opt_duparray_send), 3, ary,
rb_id2sym(idIncludeP),
INT2FIX(1));
4569 ELEM_REMOVE(&iobj->link);
4576 if (IS_INSN_ID(iobj, send)) {
4580#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
4581 if (vm_ci_simple(ci)) {
4582 switch (vm_ci_argc(ci)) {
4584 switch (vm_ci_mid(ci)) {
4585 case idLength: SP_INSN(length);
return COMPILE_OK;
4586 case idSize: SP_INSN(size);
return COMPILE_OK;
4587 case idEmptyP: SP_INSN(empty_p);
return COMPILE_OK;
4588 case idNilP: SP_INSN(nil_p);
return COMPILE_OK;
4589 case idSucc: SP_INSN(succ);
return COMPILE_OK;
4590 case idNot: SP_INSN(not);
return COMPILE_OK;
4594 switch (vm_ci_mid(ci)) {
4595 case idPLUS: SP_INSN(plus);
return COMPILE_OK;
4596 case idMINUS: SP_INSN(minus);
return COMPILE_OK;
4597 case idMULT: SP_INSN(mult);
return COMPILE_OK;
4598 case idDIV: SP_INSN(div);
return COMPILE_OK;
4599 case idMOD: SP_INSN(mod);
return COMPILE_OK;
4600 case idEq: SP_INSN(eq);
return COMPILE_OK;
4601 case idNeq: SP_INSN(neq);
return COMPILE_OK;
4602 case idEqTilde:SP_INSN(regexpmatch2);
return COMPILE_OK;
4603 case idLT: SP_INSN(lt);
return COMPILE_OK;
4604 case idLE: SP_INSN(le);
return COMPILE_OK;
4605 case idGT: SP_INSN(gt);
return COMPILE_OK;
4606 case idGE: SP_INSN(ge);
return COMPILE_OK;
4607 case idLTLT: SP_INSN(ltlt);
return COMPILE_OK;
4608 case idAREF: SP_INSN(aref);
return COMPILE_OK;
4609 case idAnd: SP_INSN(and);
return COMPILE_OK;
4610 case idOr: SP_INSN(or);
return COMPILE_OK;
4614 switch (vm_ci_mid(ci)) {
4615 case idASET: SP_INSN(aset);
return COMPILE_OK;
4621 if ((vm_ci_flag(ci) & (VM_CALL_ARGS_BLOCKARG | VM_CALL_FORWARDING)) == 0 && blockiseq == NULL) {
4622 iobj->insn_id = BIN(opt_send_without_block);
4623 iobj->operand_size = insn_len(iobj->insn_id) - 1;
4634 switch (ISEQ_BODY(iseq)->
type) {
4636 case ISEQ_TYPE_EVAL:
4637 case ISEQ_TYPE_MAIN:
4639 case ISEQ_TYPE_RESCUE:
4640 case ISEQ_TYPE_ENSURE:
4652 const int do_peepholeopt = ISEQ_COMPILE_DATA(iseq)->option->peephole_optimization;
4653 const int do_tailcallopt = tailcallable_p(iseq) &&
4654 ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization;
4655 const int do_si = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction;
4656 const int do_ou = ISEQ_COMPILE_DATA(iseq)->option->operands_unification;
4657 const int do_without_ints = ISEQ_BODY(iseq)->builtin_attrs & BUILTIN_ATTR_WITHOUT_INTERRUPTS;
4658 int rescue_level = 0;
4659 int tailcallopt = do_tailcallopt;
4661 list = FIRST_ELEMENT(anchor);
4663 int do_block_optimization = 0;
4664 LABEL * block_loop_label = NULL;
4666 int nlabels = ISEQ_COMPILE_DATA(iseq)->label_no;
4667 VALUE unref_counts_buf = 0, unref_stamps_buf = 0;
4669 .capacity = nlabels,
4671 .counts =
ALLOCV_N(
int, unref_counts_buf, nlabels),
4672 .stamps =
ALLOCV_N(
unsigned int, unref_stamps_buf, nlabels),
4678 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_BLOCK) {
4679 do_block_optimization = 1;
4684 if (IS_INSN(le) && IS_INSN_ID((
INSN *)le, nop) && IS_LABEL(le->next)) {
4685 block_loop_label = (
LABEL *)le->next;
4690 if (IS_INSN(list)) {
4691 if (do_peepholeopt) {
4695 iseq_specialized_instruction(iseq, (
INSN *)list);
4698 insn_operands_unification((
INSN *)list);
4701 if (do_without_ints) {
4703 if (IS_INSN_ID(item, jump)) {
4704 item->insn_id = BIN(jump_without_ints);
4706 else if (IS_INSN_ID(item, branchif)) {
4707 item->insn_id = BIN(branchif_without_ints);
4709 else if (IS_INSN_ID(item, branchunless)) {
4710 item->insn_id = BIN(branchunless_without_ints);
4712 else if (IS_INSN_ID(item, branchnil)) {
4713 item->insn_id = BIN(branchnil_without_ints);
4717 if (do_block_optimization) {
4720 if (IS_INSN_ID(item,
throw)) {
4721 do_block_optimization = 0;
4726 const char *types = insn_op_types(item->insn_id);
4727 for (
int j = 0; types[j]; j++) {
4728 if (types[j] == TS_OFFSET) {
4733 LABEL * target = (
LABEL *)OPERAND_AT(item, j);
4734 if (target == block_loop_label) {
4735 do_block_optimization = 0;
4742 if (IS_LABEL(list)) {
4743 switch (((
LABEL *)list)->rescued) {
4744 case LABEL_RESCUE_BEG:
4746 tailcallopt = FALSE;
4748 case LABEL_RESCUE_END:
4749 if (!--rescue_level) tailcallopt = do_tailcallopt;
4756 if (do_block_optimization) {
4758 if (IS_INSN(le) && IS_INSN_ID((
INSN *)le, nop)) {
4768#if OPT_INSTRUCTIONS_UNIFICATION
4776 VALUE *operands = 0, *ptr = 0;
4780 for (i = 0; i < size; i++) {
4781 iobj = (
INSN *)list;
4782 argc += iobj->operand_size;
4787 ptr = operands = compile_data_alloc2_type(iseq,
VALUE, argc);
4792 for (i = 0; i < size; i++) {
4793 iobj = (
INSN *)list;
4794 MEMCPY(ptr, iobj->operands,
VALUE, iobj->operand_size);
4795 ptr += iobj->operand_size;
4799 return new_insn_core(iseq, iobj->insn_info.line_no, iobj->insn_info.node_id, insn_id, argc, operands);
4811#if OPT_INSTRUCTIONS_UNIFICATION
4817 list = FIRST_ELEMENT(anchor);
4819 if (IS_INSN(list)) {
4820 iobj = (
INSN *)list;
4822 if (unified_insns_data[
id] != 0) {
4823 const int *
const *entry = unified_insns_data[id];
4824 for (j = 1; j < (intptr_t)entry[0]; j++) {
4825 const int *unified = entry[j];
4827 for (k = 2; k < unified[1]; k++) {
4829 ((
INSN *)li)->insn_id != unified[k]) {
4836 new_unified_insn(iseq, unified[0], unified[1] - 1,
4841 niobj->link.next = li;
4860all_string_result_p(
const NODE *node)
4862 if (!node)
return FALSE;
4863 switch (nd_type(node)) {
4864 case NODE_STR:
case NODE_DSTR:
case NODE_FILE:
4866 case NODE_IF:
case NODE_UNLESS:
4867 if (!RNODE_IF(node)->nd_body || !RNODE_IF(node)->nd_else)
return FALSE;
4868 if (all_string_result_p(RNODE_IF(node)->nd_body))
4869 return all_string_result_p(RNODE_IF(node)->nd_else);
4871 case NODE_AND:
case NODE_OR:
4872 if (!RNODE_AND(node)->nd_2nd)
4873 return all_string_result_p(RNODE_AND(node)->nd_1st);
4874 if (!all_string_result_p(RNODE_AND(node)->nd_1st))
4876 return all_string_result_p(RNODE_AND(node)->nd_2nd);
4886 const NODE *lit_node;
4894 VALUE s = rb_str_new_mutable_parser_string(str);
4896 VALUE error = rb_reg_check_preprocess(s);
4897 if (!
NIL_P(error)) {
4898 COMPILE_ERROR(args->iseq, nd_line(node),
"%" PRIsVALUE, error);
4902 if (
NIL_P(args->lit)) {
4904 args->lit_node = node;
4913flush_dstr_fragment(
struct dstr_ctxt *args)
4915 if (!
NIL_P(args->lit)) {
4917 VALUE lit = args->lit;
4919 lit = rb_fstring(lit);
4920 ADD_INSN1(args->ret, args->lit_node, putobject, lit);
4927compile_dstr_fragments_0(
struct dstr_ctxt *args,
const NODE *
const node)
4929 const struct RNode_LIST *list = RNODE_DSTR(node)->nd_next;
4933 CHECK(append_dstr_fragment(args, node, str));
4937 const NODE *
const head = list->nd_head;
4938 if (nd_type_p(head, NODE_STR)) {
4939 CHECK(append_dstr_fragment(args, node, RNODE_STR(head)->
string));
4941 else if (nd_type_p(head, NODE_DSTR)) {
4942 CHECK(compile_dstr_fragments_0(args, head));
4945 flush_dstr_fragment(args);
4947 CHECK(COMPILE(args->ret,
"each string", head));
4959 .iseq = iseq, .ret = ret,
4960 .lit =
Qnil, .lit_node = NULL,
4961 .cnt = 0, .dregx = dregx,
4963 CHECK(compile_dstr_fragments_0(&args, node));
4964 flush_dstr_fragment(&args);
4974 while (node && nd_type_p(node, NODE_BLOCK)) {
4975 CHECK(COMPILE_(ret,
"BLOCK body", RNODE_BLOCK(node)->nd_head,
4976 (RNODE_BLOCK(node)->nd_next ? 1 : popped)));
4977 node = RNODE_BLOCK(node)->nd_next;
4980 CHECK(COMPILE_(ret,
"BLOCK next", RNODE_BLOCK(node)->nd_next, popped));
4989 if (!RNODE_DSTR(node)->nd_next) {
4990 VALUE lit = rb_node_dstr_string_val(node);
4991 ADD_INSN1(ret, node, dupstring, lit);
4996 CHECK(compile_dstr_fragments(iseq, ret, node, &cnt, FALSE));
4997 ADD_INSN1(ret, node, concatstrings,
INT2FIX(cnt));
5006 int cflag = (int)RNODE_DREGX(node)->as.nd_cflag;
5008 if (!RNODE_DREGX(node)->nd_next) {
5010 VALUE src = rb_node_dregx_string_val(node);
5011 VALUE match = iseq_reg_compile(iseq, src, cflag, NULL, 0);
5012 ADD_INSN1(ret, node, putobject, match);
5018 CHECK(compile_dstr_fragments(iseq, ret, node, &cnt, TRUE));
5022 ADD_INSN(ret, node, pop);
5032 const int line = nd_line(node);
5033 LABEL *lend = NEW_LABEL(line);
5034 rb_num_t cnt = ISEQ_FLIP_CNT_INCREMENT(ISEQ_BODY(iseq)->local_iseq)
5035 + VM_SVAR_FLIPFLOP_START;
5038 ADD_INSN2(ret, node, getspecial, key,
INT2FIX(0));
5039 ADD_INSNL(ret, node, branchif, lend);
5042 CHECK(COMPILE(ret,
"flip2 beg", RNODE_FLIP2(node)->nd_beg));
5043 ADD_INSNL(ret, node, branchunless, else_label);
5044 ADD_INSN1(ret, node, putobject,
Qtrue);
5045 ADD_INSN1(ret, node, setspecial, key);
5047 ADD_INSNL(ret, node, jump, then_label);
5051 ADD_LABEL(ret, lend);
5052 CHECK(COMPILE(ret,
"flip2 end", RNODE_FLIP2(node)->nd_end));
5053 ADD_INSNL(ret, node, branchunless, then_label);
5054 ADD_INSN1(ret, node, putobject,
Qfalse);
5055 ADD_INSN1(ret, node, setspecial, key);
5056 ADD_INSNL(ret, node, jump, then_label);
5065#define COMPILE_SINGLE 2
5072 LABEL *label = NEW_LABEL(nd_line(cond));
5073 if (!then_label) then_label = label;
5074 else if (!else_label) else_label = label;
5076 CHECK(compile_branch_condition(iseq, seq, cond, then_label, else_label));
5078 if (LIST_INSN_SIZE_ONE(seq)) {
5079 INSN *insn = (
INSN *)ELEM_FIRST_INSN(FIRST_ELEMENT(seq));
5080 if (insn->insn_id == BIN(jump) && (
LABEL *)(insn->operands[0]) == label)
5083 if (!label->refcnt) {
5084 return COMPILE_SINGLE;
5086 ADD_LABEL(seq, label);
5096 DECL_ANCHOR(ignore);
5099 switch (nd_type(cond)) {
5101 CHECK(ok = compile_logical(iseq, ret, RNODE_AND(cond)->nd_1st, NULL, else_label));
5102 cond = RNODE_AND(cond)->nd_2nd;
5103 if (ok == COMPILE_SINGLE) {
5104 ADD_INSNL(ret, cond, jump, else_label);
5105 INIT_ANCHOR(ignore);
5107 then_label = NEW_LABEL(nd_line(cond));
5111 CHECK(ok = compile_logical(iseq, ret, RNODE_OR(cond)->nd_1st, then_label, NULL));
5112 cond = RNODE_OR(cond)->nd_2nd;
5113 if (ok == COMPILE_SINGLE) {
5114 ADD_INSNL(ret, cond, jump, then_label);
5115 INIT_ANCHOR(ignore);
5117 else_label = NEW_LABEL(nd_line(cond));
5127 case NODE_IMAGINARY:
5134 ADD_INSNL(ret, cond, jump, then_label);
5139 ADD_INSNL(ret, cond, jump, else_label);
5145 CHECK(COMPILE_POPPED(ret,
"branch condition", cond));
5146 ADD_INSNL(ret, cond, jump, then_label);
5149 CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label));
5152 CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
5155 CHECK(compile_defined_expr(iseq, ret, cond,
Qfalse, ret == ignore));
5159 DECL_ANCHOR(cond_seq);
5160 INIT_ANCHOR(cond_seq);
5162 CHECK(COMPILE(cond_seq,
"branch condition", cond));
5164 if (LIST_INSN_SIZE_ONE(cond_seq)) {
5165 INSN *insn = (
INSN *)ELEM_FIRST_INSN(FIRST_ELEMENT(cond_seq));
5166 if (insn->insn_id == BIN(putobject)) {
5167 if (
RTEST(insn->operands[0])) {
5168 ADD_INSNL(ret, cond, jump, then_label);
5173 ADD_INSNL(ret, cond, jump, else_label);
5178 ADD_SEQ(ret, cond_seq);
5183 ADD_INSNL(ret, cond, branchunless, else_label);
5184 ADD_INSNL(ret, cond, jump, then_label);
5191keyword_node_p(
const NODE *
const node)
5193 return nd_type_p(node, NODE_HASH) && (RNODE_HASH(node)->nd_brace & HASH_BRACE) != HASH_BRACE;
5199 switch (nd_type(node)) {
5201 return rb_node_sym_string_val(node);
5203 UNKNOWN_NODE(
"get_symbol_value", node,
Qnil);
5210 NODE *node = node_hash->nd_head;
5211 VALUE hash = rb_hash_new();
5214 for (
int i = 0; node != NULL; i++, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
5215 VALUE key = get_symbol_value(iseq, RNODE_LIST(node)->nd_head);
5216 VALUE idx = rb_hash_aref(hash, key);
5221 rb_hash_aset(hash, key,
INT2FIX(i));
5231 const NODE *
const root_node,
5239 if (RNODE_HASH(root_node)->nd_head && nd_type_p(RNODE_HASH(root_node)->nd_head, NODE_LIST)) {
5240 const NODE *node = RNODE_HASH(root_node)->nd_head;
5244 const NODE *key_node = RNODE_LIST(node)->nd_head;
5248 if (key_node && nd_type_p(key_node, NODE_SYM)) {
5253 *flag |= VM_CALL_KW_SPLAT;
5254 if (seen_nodes > 1 || RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
5259 *flag |= VM_CALL_KW_SPLAT_MUT;
5264 node = RNODE_LIST(node)->nd_next;
5265 node = RNODE_LIST(node)->nd_next;
5269 node = RNODE_HASH(root_node)->nd_head;
5272 VALUE key_index = node_hash_unique_key_index(iseq, RNODE_HASH(root_node), &
len);
5274 if (
len > VM_CALL_KW_LEN_MAX) {
5275 COMPILE_ERROR(ERROR_ARGS_AT(root_node)
"too many keyword arguments (%d, maximum is %d)",
5276 len, (
int)VM_CALL_KW_LEN_MAX);
5281 VALUE *keywords = kw_arg->keywords;
5284 kw_arg->references = 0;
5285 kw_arg->keyword_len =
len;
5287 *kw_arg_ptr = kw_arg;
5289 for (i=0; node != NULL; i++, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
5290 const NODE *key_node = RNODE_LIST(node)->nd_head;
5291 const NODE *val_node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head;
5294 keywords[j] = get_symbol_value(iseq, key_node);
5298 NO_CHECK(COMPILE_(ret,
"keyword values", val_node, popped));
5312 for (; node;
len++, node = RNODE_LIST(node)->nd_next) {
5314 EXPECT_NODE(
"compile_args", node, NODE_LIST, -1);
5317 if (RNODE_LIST(node)->nd_next == NULL && keyword_node_p(RNODE_LIST(node)->nd_head)) {
5318 *kwnode_ptr = RNODE_LIST(node)->nd_head;
5321 RUBY_ASSERT(!keyword_node_p(RNODE_LIST(node)->nd_head));
5322 NO_CHECK(COMPILE_(ret,
"array element", RNODE_LIST(node)->nd_head, FALSE));
5330frozen_string_literal_p(
const rb_iseq_t *iseq)
5332 return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal > 0;
5336static_literal_node_p(
const NODE *node,
const rb_iseq_t *iseq,
bool hash_key)
5338 switch (nd_type(node)) {
5346 case NODE_IMAGINARY:
5353 return hash_key || frozen_string_literal_p(iseq);
5362 switch (nd_type(node)) {
5365 VALUE lit = rb_node_integer_literal_val(node);
5371 VALUE lit = rb_node_float_literal_val(node);
5377 case NODE_IMAGINARY:
5386 return rb_node_sym_string_val(node);
5390 return rb_node_line_lineno_val(node);
5392 return rb_node_encoding_val(node);
5395 if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal ||
RTEST(
ruby_debug)) {
5396 VALUE lit = get_string_value(node);
5397 VALUE str = rb_str_with_debug_created_info(lit, rb_iseq_path(iseq), (
int)nd_line(node));
5402 return get_string_value(node);
5405 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
5412 const NODE *line_node = node;
5414 if (nd_type_p(node, NODE_ZLIST)) {
5416 ADD_INSN1(ret, line_node, newarray,
INT2FIX(0));
5421 EXPECT_NODE(
"compile_array", node, NODE_LIST, -1);
5424 for (; node; node = RNODE_LIST(node)->nd_next) {
5425 NO_CHECK(COMPILE_(ret,
"array element", RNODE_LIST(node)->nd_head, popped));
5467 const int max_stack_len = 0x100;
5468 const int min_tmp_ary_len = 0x40;
5472#define FLUSH_CHUNK \
5474 if (first_chunk) ADD_INSN1(ret, line_node, newarray, INT2FIX(stack_len)); \
5475 else ADD_INSN1(ret, line_node, pushtoarray, INT2FIX(stack_len)); \
5476 first_chunk = FALSE; \
5484 if (static_literal_node_p(RNODE_LIST(node)->nd_head, iseq,
false)) {
5486 const NODE *node_tmp = RNODE_LIST(node)->nd_next;
5487 for (; node_tmp && static_literal_node_p(RNODE_LIST(node_tmp)->nd_head, iseq,
false); node_tmp = RNODE_LIST(node_tmp)->nd_next)
5490 if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_ary_len) {
5495 for (; count; count--, node = RNODE_LIST(node)->nd_next)
5496 rb_ary_push(ary, static_literal_value(RNODE_LIST(node)->nd_head, iseq));
5502 ADD_INSN1(ret, line_node, duparray, ary);
5503 first_chunk = FALSE;
5506 ADD_INSN1(ret, line_node, putobject, ary);
5507 ADD_INSN(ret, line_node, concattoarray);
5515 for (; count; count--, node = RNODE_LIST(node)->nd_next) {
5517 EXPECT_NODE(
"compile_array", node, NODE_LIST, -1);
5520 if (!RNODE_LIST(node)->nd_next && keyword_node_p(RNODE_LIST(node)->nd_head)) {
5522 if (stack_len == 0 && first_chunk) {
5523 ADD_INSN1(ret, line_node, newarray,
INT2FIX(0));
5528 NO_CHECK(COMPILE_(ret,
"array element", RNODE_LIST(node)->nd_head, 0));
5529 ADD_INSN(ret, line_node, pushtoarraykwsplat);
5533 NO_CHECK(COMPILE_(ret,
"array element", RNODE_LIST(node)->nd_head, 0));
5538 if (stack_len >= max_stack_len) FLUSH_CHUNK;
5548static_literal_node_pair_p(
const NODE *node,
const rb_iseq_t *iseq)
5550 return RNODE_LIST(node)->nd_head && static_literal_node_p(RNODE_LIST(node)->nd_head, iseq,
true) && static_literal_node_p(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq,
false);
5556 const NODE *line_node = node;
5558 node = RNODE_HASH(node)->nd_head;
5560 if (!node || nd_type_p(node, NODE_ZLIST)) {
5562 ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
5567 EXPECT_NODE(
"compile_hash", node, NODE_LIST, -1);
5570 for (; node; node = RNODE_LIST(node)->nd_next) {
5571 NO_CHECK(COMPILE_(ret,
"hash element", RNODE_LIST(node)->nd_head, popped));
5594 const int max_stack_len = 0x100;
5595 const int min_tmp_hash_len = 0x800;
5597 int first_chunk = 1;
5598 DECL_ANCHOR(anchor);
5599 INIT_ANCHOR(anchor);
5602#define FLUSH_CHUNK() \
5604 if (first_chunk) { \
5605 APPEND_LIST(ret, anchor); \
5606 ADD_INSN1(ret, line_node, newhash, INT2FIX(stack_len)); \
5609 ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \
5610 ADD_INSN(ret, line_node, swap); \
5611 APPEND_LIST(ret, anchor); \
5612 ADD_SEND(ret, line_node, id_core_hash_merge_bang_ptr, INT2FIX(stack_len + 1)); \
5614 INIT_ANCHOR(anchor); \
5615 first_chunk = stack_len = 0; \
5622 if (static_literal_node_pair_p(node, iseq)) {
5624 const NODE *node_tmp = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next;
5625 for (; node_tmp && static_literal_node_pair_p(node_tmp, iseq); node_tmp = RNODE_LIST(RNODE_LIST(node_tmp)->nd_next)->nd_next)
5628 if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_hash_len) {
5633 for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
5635 elem[0] = static_literal_value(RNODE_LIST(node)->nd_head, iseq);
5637 elem[1] = static_literal_value(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq);
5649 ADD_INSN1(ret, line_node, duphash, hash);
5653 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5654 ADD_INSN(ret, line_node, swap);
5656 ADD_INSN1(ret, line_node, putobject, hash);
5658 ADD_SEND(ret, line_node, id_core_hash_merge_bang_kwd,
INT2FIX(2));
5665 for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
5668 EXPECT_NODE(
"compile_hash", node, NODE_LIST, -1);
5671 if (RNODE_LIST(node)->nd_head) {
5673 NO_CHECK(COMPILE_(anchor,
"hash key element", RNODE_LIST(node)->nd_head, 0));
5674 NO_CHECK(COMPILE_(anchor,
"hash value element", RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, 0));
5678 if (stack_len >= max_stack_len) FLUSH_CHUNK();
5684 const NODE *kw = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head;
5685 int empty_kw = nd_type_p(kw, NODE_HASH) && (!RNODE_HASH(kw)->nd_head);
5686 int first_kw = first_chunk && stack_len == 0;
5687 int last_kw = !RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next;
5688 int only_kw = last_kw && first_kw;
5690 empty_kw = empty_kw || nd_type_p(kw, NODE_NIL);
5692 if (only_kw && method_call_keywords) {
5700 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
5702 else if (first_kw) {
5706 ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
5713 if (only_kw && method_call_keywords) {
5719 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
5726 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5727 if (first_kw) ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
5728 else ADD_INSN(ret, line_node, swap);
5730 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
5732 ADD_SEND(ret, line_node, id_core_hash_merge_bang_kwd,
INT2FIX(2));
5747rb_node_case_when_optimizable_literal(
const NODE *
const node)
5749 switch (nd_type(node)) {
5751 return rb_node_integer_literal_val(node);
5753 VALUE v = rb_node_float_literal_val(node);
5762 case NODE_IMAGINARY:
5771 return rb_node_sym_string_val(node);
5773 return rb_node_line_lineno_val(node);
5775 return rb_node_str_string_val(node);
5777 return rb_node_file_path_val(node);
5784 LABEL *l1,
int only_special_literals,
VALUE literals)
5787 const NODE *val = RNODE_LIST(vals)->nd_head;
5788 VALUE lit = rb_node_case_when_optimizable_literal(val);
5791 only_special_literals = 0;
5794 cdhash_aset_if_missing(literals, lit, (
VALUE)(l1));
5797 if (nd_type_p(val, NODE_STR) || nd_type_p(val, NODE_FILE)) {
5798 debugp_param(
"nd_lit", get_string_value(val));
5799 lit = get_string_value(val);
5800 ADD_INSN1(cond_seq, val, putobject, lit);
5804 if (!COMPILE(cond_seq,
"when cond", val))
return -1;
5808 ADD_INSN1(cond_seq, vals, topn,
INT2FIX(1));
5809 ADD_CALL(cond_seq, vals, idEqq,
INT2FIX(1));
5810 ADD_INSNL(cond_seq, val, branchif, l1);
5811 vals = RNODE_LIST(vals)->nd_next;
5813 return only_special_literals;
5818 LABEL *l1,
int only_special_literals,
VALUE literals)
5820 const NODE *line_node = vals;
5822 switch (nd_type(vals)) {
5824 if (when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals) < 0)
5828 ADD_INSN (cond_seq, line_node, dup);
5829 CHECK(COMPILE(cond_seq,
"when splat", RNODE_SPLAT(vals)->nd_head));
5830 ADD_INSN1(cond_seq, line_node, splatarray,
Qfalse);
5831 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
5832 ADD_INSNL(cond_seq, line_node, branchif, l1);
5835 CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSCAT(vals)->nd_head, l1, only_special_literals, literals));
5836 CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSCAT(vals)->nd_body, l1, only_special_literals, literals));
5839 CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSPUSH(vals)->nd_head, l1, only_special_literals, literals));
5840 ADD_INSN (cond_seq, line_node, dup);
5841 CHECK(COMPILE(cond_seq,
"when argspush body", RNODE_ARGSPUSH(vals)->nd_body));
5842 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
5843 ADD_INSNL(cond_seq, line_node, branchif, l1);
5846 ADD_INSN (cond_seq, line_node, dup);
5847 CHECK(COMPILE(cond_seq,
"when val", vals));
5848 ADD_INSN1(cond_seq, line_node, splatarray,
Qfalse);
5849 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
5850 ADD_INSNL(cond_seq, line_node, branchif, l1);
5943 const NODE *line_node;
5958add_masgn_lhs_node(
struct masgn_state *state,
int lhs_pos,
const NODE *line_node,
int argc,
INSN *before_insn)
5961 rb_bug(
"no masgn_state");
5970 memo->before_insn = before_insn;
5971 memo->line_node = line_node;
5972 memo->argn = state->num_args + 1;
5973 memo->num_args = argc;
5974 state->num_args += argc;
5975 memo->lhs_pos = lhs_pos;
5977 if (!state->first_memo) {
5978 state->first_memo = memo;
5981 state->last_memo->next = memo;
5983 state->last_memo = memo;
5993 switch (nd_type(node)) {
5994 case NODE_ATTRASGN: {
5996 const NODE *line_node = node;
5998 CHECK(COMPILE_POPPED(pre,
"masgn lhs (NODE_ATTRASGN)", node));
6000 bool safenav_call =
false;
6002 iobj = (
INSN *)get_prev_insn((
INSN *)insn_element);
6004 ELEM_REMOVE(insn_element);
6005 if (!IS_INSN_ID(iobj, send)) {
6006 safenav_call =
true;
6007 iobj = (
INSN *)get_prev_insn(iobj);
6008 ELEM_INSERT_NEXT(&iobj->link, insn_element);
6010 (pre->last = iobj->link.prev)->next = 0;
6013 int argc = vm_ci_argc(ci) + 1;
6014 ci = ci_argc_set(iseq, ci, argc);
6015 OPERAND_AT(iobj, 0) = (
VALUE)ci;
6019 ADD_INSN(lhs, line_node, swap);
6022 ADD_INSN1(lhs, line_node, topn,
INT2FIX(argc));
6025 if (!add_masgn_lhs_node(state, lhs_pos, line_node, argc, (
INSN *)LAST_ELEMENT(lhs))) {
6029 iobj->link.prev = lhs->last;
6030 lhs->last->next = &iobj->link;
6031 for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next);
6032 if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
6033 int argc = vm_ci_argc(ci);
6034 bool dupsplat =
false;
6035 ci = ci_argc_set(iseq, ci, argc - 1);
6036 if (!(vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT_MUT)) {
6043 ci = ci_flag_set(iseq, ci, VM_CALL_ARGS_SPLAT_MUT);
6045 OPERAND_AT(iobj, 0) = (
VALUE)ci;
6054 int line_no = nd_line(line_node);
6055 int node_id = nd_node_id(line_node);
6058 INSERT_BEFORE_INSN(iobj, line_no, node_id, swap);
6059 INSERT_BEFORE_INSN1(iobj, line_no, node_id, splatarray,
Qtrue);
6060 INSERT_BEFORE_INSN(iobj, line_no, node_id, swap);
6062 INSERT_BEFORE_INSN1(iobj, line_no, node_id, pushtoarray,
INT2FIX(1));
6064 if (!safenav_call) {
6065 ADD_INSN(lhs, line_node, pop);
6067 ADD_INSN(lhs, line_node, pop);
6070 for (
int i=0; i < argc; i++) {
6071 ADD_INSN(post, line_node, pop);
6076 DECL_ANCHOR(nest_rhs);
6077 INIT_ANCHOR(nest_rhs);
6078 DECL_ANCHOR(nest_lhs);
6079 INIT_ANCHOR(nest_lhs);
6081 int prev_level = state->lhs_level;
6082 bool prev_nested = state->nested;
6084 state->lhs_level = lhs_pos - 1;
6085 CHECK(compile_massign0(iseq, pre, nest_rhs, nest_lhs, post, node, state, 1));
6086 state->lhs_level = prev_level;
6087 state->nested = prev_nested;
6089 ADD_SEQ(lhs, nest_rhs);
6090 ADD_SEQ(lhs, nest_lhs);
6094 if (!RNODE_CDECL(node)->nd_vid) {
6098 CHECK(COMPILE_POPPED(pre,
"masgn lhs (NODE_CDECL)", node));
6101 iobj = (
INSN *)insn_element;
6104 ELEM_REMOVE(insn_element);
6105 pre->last = iobj->link.prev;
6108 if (!add_masgn_lhs_node(state, lhs_pos, node, 1, (
INSN *)LAST_ELEMENT(lhs))) {
6112 ADD_INSN(post, node, pop);
6117 DECL_ANCHOR(anchor);
6118 INIT_ANCHOR(anchor);
6119 CHECK(COMPILE_POPPED(anchor,
"masgn lhs", node));
6120 ELEM_REMOVE(FIRST_ELEMENT(anchor));
6121 ADD_SEQ(lhs, anchor);
6132 CHECK(compile_massign_opt_lhs(iseq, ret, RNODE_LIST(lhsn)->nd_next));
6133 CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, RNODE_LIST(lhsn)->nd_head, NULL, 0));
6140 const NODE *rhsn,
const NODE *orig_lhsn)
6143 const int memsize = numberof(mem);
6145 int llen = 0, rlen = 0;
6147 const NODE *lhsn = orig_lhsn;
6149#define MEMORY(v) { \
6151 if (memindex == memsize) return 0; \
6152 for (i=0; i<memindex; i++) { \
6153 if (mem[i] == (v)) return 0; \
6155 mem[memindex++] = (v); \
6158 if (rhsn == 0 || !nd_type_p(rhsn, NODE_LIST)) {
6163 const NODE *ln = RNODE_LIST(lhsn)->nd_head;
6164 switch (nd_type(ln)) {
6169 MEMORY(get_nd_vid(ln));
6174 lhsn = RNODE_LIST(lhsn)->nd_next;
6180 NO_CHECK(COMPILE_POPPED(ret,
"masgn val (popped)", RNODE_LIST(rhsn)->nd_head));
6183 NO_CHECK(COMPILE(ret,
"masgn val", RNODE_LIST(rhsn)->nd_head));
6185 rhsn = RNODE_LIST(rhsn)->nd_next;
6190 for (i=0; i<llen-rlen; i++) {
6191 ADD_INSN(ret, orig_lhsn, putnil);
6195 compile_massign_opt_lhs(iseq, ret, orig_lhsn);
6202 const NODE *rhsn = RNODE_MASGN(node)->nd_value;
6203 const NODE *splatn = RNODE_MASGN(node)->nd_args;
6204 const NODE *lhsn = RNODE_MASGN(node)->nd_head;
6205 const NODE *lhsn_count = lhsn;
6206 int lhs_splat = (splatn && NODE_NAMED_REST_P(splatn)) ? 1 : 0;
6211 while (lhsn_count) {
6213 lhsn_count = RNODE_LIST(lhsn_count)->nd_next;
6216 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, RNODE_LIST(lhsn)->nd_head, state, (llen - lpos) + lhs_splat + state->lhs_level));
6218 lhsn = RNODE_LIST(lhsn)->nd_next;
6222 if (nd_type_p(splatn, NODE_POSTARG)) {
6224 const NODE *postn = RNODE_POSTARG(splatn)->nd_2nd;
6225 const NODE *restn = RNODE_POSTARG(splatn)->nd_1st;
6226 int plen = (int)RNODE_LIST(postn)->as.nd_alen;
6228 int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00);
6230 ADD_INSN2(lhs, splatn, expandarray,
INT2FIX(plen),
INT2FIX(flag));
6232 if (NODE_NAMED_REST_P(restn)) {
6233 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, restn, state, 1 + plen + state->lhs_level));
6236 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, RNODE_LIST(postn)->nd_head, state, (plen - ppos) + state->lhs_level));
6238 postn = RNODE_LIST(postn)->nd_next;
6243 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, splatn, state, 1 + state->lhs_level));
6247 if (!state->nested) {
6248 NO_CHECK(COMPILE(rhs,
"normal masgn rhs", rhsn));
6252 ADD_INSN(rhs, node, dup);
6254 ADD_INSN2(rhs, node, expandarray,
INT2FIX(llen),
INT2FIX(lhs_splat));
6261 if (!popped || RNODE_MASGN(node)->nd_args || !compile_massign_opt(iseq, ret, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head)) {
6263 state.lhs_level = popped ? 0 : 1;
6266 state.first_memo = NULL;
6267 state.last_memo = NULL;
6277 int ok = compile_massign0(iseq, pre, rhs, lhs, post, node, &state, popped);
6281 VALUE topn_arg =
INT2FIX((state.num_args - memo->argn) + memo->lhs_pos);
6282 for (
int i = 0; i < memo->num_args; i++) {
6283 INSERT_BEFORE_INSN1(memo->before_insn, nd_line(memo->line_node), nd_node_id(memo->line_node), topn, topn_arg);
6285 tmp_memo = memo->next;
6294 if (!popped && state.num_args >= 1) {
6296 ADD_INSN1(ret, node, setn,
INT2FIX(state.num_args));
6308 switch (nd_type(node)) {
6310 rb_ary_unshift(arr,
ID2SYM(RNODE_CONST(node)->nd_vid));
6314 rb_ary_unshift(arr,
ID2SYM(RNODE_COLON3(node)->nd_mid));
6315 rb_ary_unshift(arr,
ID2SYM(idNULL));
6319 rb_ary_unshift(arr,
ID2SYM(RNODE_COLON2(node)->nd_mid));
6320 node = RNODE_COLON2(node)->nd_head;
6329compile_const_prefix(
rb_iseq_t *iseq,
const NODE *
const node,
6332 switch (nd_type(node)) {
6334 debugi(
"compile_const_prefix - colon", RNODE_CONST(node)->nd_vid);
6335 ADD_INSN1(body, node, putobject,
Qtrue);
6336 ADD_INSN1(body, node, getconstant,
ID2SYM(RNODE_CONST(node)->nd_vid));
6339 debugi(
"compile_const_prefix - colon3", RNODE_COLON3(node)->nd_mid);
6340 ADD_INSN(body, node, pop);
6341 ADD_INSN1(body, node, putobject,
rb_cObject);
6342 ADD_INSN1(body, node, putobject,
Qtrue);
6343 ADD_INSN1(body, node, getconstant,
ID2SYM(RNODE_COLON3(node)->nd_mid));
6346 CHECK(compile_const_prefix(iseq, RNODE_COLON2(node)->nd_head, pref, body));
6347 debugi(
"compile_const_prefix - colon2", RNODE_COLON2(node)->nd_mid);
6348 ADD_INSN1(body, node, putobject,
Qfalse);
6349 ADD_INSN1(body, node, getconstant,
ID2SYM(RNODE_COLON2(node)->nd_mid));
6352 CHECK(COMPILE(pref,
"const colon2 prefix", node));
6359cpath_const_p(
const NODE *node)
6361 switch (nd_type(node)) {
6366 if (RNODE_COLON2(node)->nd_head) {
6367 return cpath_const_p(RNODE_COLON2(node)->nd_head);
6378 if (nd_type_p(cpath, NODE_COLON3)) {
6380 ADD_INSN1(ret, cpath, putobject,
rb_cObject);
6381 return VM_DEFINECLASS_FLAG_SCOPED;
6383 else if (nd_type_p(cpath, NODE_COLON2) && RNODE_COLON2(cpath)->nd_head) {
6385 NO_CHECK(COMPILE(ret,
"nd_else->nd_head", RNODE_COLON2(cpath)->nd_head));
6386 int flags = VM_DEFINECLASS_FLAG_SCOPED;
6387 if (!cpath_const_p(RNODE_COLON2(cpath)->nd_head)) {
6388 flags |= VM_DEFINECLASS_FLAG_DYNAMIC_CREF;
6394 ADD_INSN1(ret, cpath, putspecialobject,
6395 INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
6401private_recv_p(
const NODE *node)
6403 NODE *recv = get_nd_recv(node);
6404 if (recv && nd_type_p(recv, NODE_SELF)) {
6405 return RNODE_SELF(recv)->nd_state != 0;
6412 const NODE *
const node,
LABEL **lfinish,
VALUE needstr,
bool ignore);
6415compile_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);
6422 enum defined_type expr_type = DEFINED_NOT_DEFINED;
6423 enum node_type
type;
6424 const int line = nd_line(node);
6425 const NODE *line_node = node;
6427 switch (
type = nd_type(node)) {
6431 expr_type = DEFINED_NIL;
6434 expr_type = DEFINED_SELF;
6437 expr_type = DEFINED_TRUE;
6440 expr_type = DEFINED_FALSE;
6445 const NODE *vals = (nd_type(node) == NODE_HASH) ? RNODE_HASH(node)->nd_head : node;
6449 if (RNODE_LIST(vals)->nd_head) {
6450 defined_expr0(iseq, ret, RNODE_LIST(vals)->nd_head, lfinish,
Qfalse,
false);
6453 lfinish[1] = NEW_LABEL(line);
6455 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
6457 }
while ((vals = RNODE_LIST(vals)->nd_next) != NULL);
6470 case NODE_IMAGINARY:
6475 expr_type = DEFINED_EXPR;
6479 defined_expr0(iseq, ret, RNODE_LIST(node)->nd_head, lfinish,
Qfalse,
false);
6481 lfinish[1] = NEW_LABEL(line);
6483 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
6484 expr_type = DEFINED_EXPR;
6490 expr_type = DEFINED_LVAR;
6493#define PUSH_VAL(type) (needstr == Qfalse ? Qtrue : rb_iseq_defined_string(type))
6495 ADD_INSN3(ret, line_node, definedivar,
6496 ID2SYM(RNODE_IVAR(node)->nd_vid), get_ivar_ic_value(iseq,RNODE_IVAR(node)->nd_vid), PUSH_VAL(DEFINED_IVAR));
6500 ADD_INSN(ret, line_node, putnil);
6501 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_GVAR),
6502 ID2SYM(RNODE_GVAR(node)->nd_vid), PUSH_VAL(DEFINED_GVAR));
6506 ADD_INSN(ret, line_node, putnil);
6507 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CVAR),
6508 ID2SYM(RNODE_CVAR(node)->nd_vid), PUSH_VAL(DEFINED_CVAR));
6512 ADD_INSN(ret, line_node, putnil);
6513 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CONST),
6514 ID2SYM(RNODE_CONST(node)->nd_vid), PUSH_VAL(DEFINED_CONST));
6518 lfinish[1] = NEW_LABEL(line);
6520 defined_expr0(iseq, ret, RNODE_COLON2(node)->nd_head, lfinish,
Qfalse,
false);
6521 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
6522 NO_CHECK(COMPILE(ret,
"defined/colon2#nd_head", RNODE_COLON2(node)->nd_head));
6525 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CONST_FROM),
6526 ID2SYM(RNODE_COLON2(node)->nd_mid), PUSH_VAL(DEFINED_CONST));
6529 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_METHOD),
6530 ID2SYM(RNODE_COLON2(node)->nd_mid), PUSH_VAL(DEFINED_METHOD));
6534 ADD_INSN1(ret, line_node, putobject,
rb_cObject);
6535 ADD_INSN3(ret, line_node, defined,
6536 INT2FIX(DEFINED_CONST_FROM),
ID2SYM(RNODE_COLON3(node)->nd_mid), PUSH_VAL(DEFINED_CONST));
6544 case NODE_ATTRASGN:{
6545 const int explicit_receiver =
6546 (
type == NODE_CALL ||
type == NODE_OPCALL ||
6547 (
type == NODE_ATTRASGN && !private_recv_p(node)));
6549 if (get_nd_args(node) || explicit_receiver) {
6551 lfinish[1] = NEW_LABEL(line);
6554 lfinish[2] = NEW_LABEL(line);
6557 if (get_nd_args(node)) {
6558 defined_expr0(iseq, ret, get_nd_args(node), lfinish,
Qfalse,
false);
6559 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
6561 if (explicit_receiver) {
6562 defined_expr0(iseq, ret, get_nd_recv(node), lfinish,
Qfalse,
true);
6563 switch (nd_type(get_nd_recv(node))) {
6569 ADD_INSNL(ret, line_node, branchunless, lfinish[2]);
6570 compile_call(iseq, ret, get_nd_recv(node), nd_type(get_nd_recv(node)), line_node, 0,
true);
6573 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
6574 NO_CHECK(COMPILE(ret,
"defined/recv", get_nd_recv(node)));
6578 ADD_INSN(ret, line_node, dup);
6580 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_METHOD),
6581 ID2SYM(get_node_call_nd_mid(node)), PUSH_VAL(DEFINED_METHOD));
6584 ADD_INSN(ret, line_node, putself);
6586 ADD_INSN(ret, line_node, dup);
6588 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_FUNC),
6589 ID2SYM(get_node_call_nd_mid(node)), PUSH_VAL(DEFINED_METHOD));
6595 ADD_INSN(ret, line_node, putnil);
6596 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_YIELD), 0,
6597 PUSH_VAL(DEFINED_YIELD));
6598 iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
6603 ADD_INSN(ret, line_node, putnil);
6604 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_REF),
6605 INT2FIX((RNODE_BACK_REF(node)->nd_nth << 1) | (
type == NODE_BACK_REF)),
6606 PUSH_VAL(DEFINED_GVAR));
6611 ADD_INSN(ret, line_node, putnil);
6612 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_ZSUPER), 0,
6613 PUSH_VAL(DEFINED_ZSUPER));
6619 case NODE_OP_ASGN_OR:
6620 case NODE_OP_ASGN_AND:
6629 expr_type = DEFINED_ASGN;
6636 VALUE str = rb_iseq_defined_string(expr_type);
6637 ADD_INSN1(ret, line_node, putobject, str);
6640 ADD_INSN1(ret, line_node, putobject,
Qtrue);
6647 ADD_SYNTHETIC_INSN(ret, 0, -1, putnil);
6648 iseq_set_exception_local_table(iseq);
6653 const NODE *
const node,
LABEL **lfinish,
VALUE needstr,
bool ignore)
6656 defined_expr0(iseq, ret, node, lfinish, needstr,
false);
6658 int line = nd_line(node);
6659 LABEL *lstart = NEW_LABEL(line);
6660 LABEL *lend = NEW_LABEL(line);
6663 rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq, NULL);
6664 rescue = NEW_CHILD_ISEQ_WITH_CALLBACK(ifunc,
6666 ISEQ_BODY(iseq)->location.label),
6667 ISEQ_TYPE_RESCUE, 0);
6668 lstart->rescued = LABEL_RESCUE_BEG;
6669 lend->rescued = LABEL_RESCUE_END;
6670 APPEND_LABEL(ret, lcur, lstart);
6671 ADD_LABEL(ret, lend);
6673 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
6681 const int line = nd_line(node);
6682 const NODE *line_node = node;
6683 if (!RNODE_DEFINED(node)->nd_head) {
6684 VALUE str = rb_iseq_defined_string(DEFINED_NIL);
6685 ADD_INSN1(ret, line_node, putobject, str);
6690 lfinish[0] = NEW_LABEL(line);
6693 defined_expr(iseq, ret, RNODE_DEFINED(node)->nd_head, lfinish, needstr, ignore);
6695 ELEM_INSERT_NEXT(last, &new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(putnil), 0)->link);
6696 ADD_INSN(ret, line_node, swap);
6698 ADD_LABEL(ret, lfinish[2]);
6700 ADD_INSN(ret, line_node, pop);
6701 ADD_LABEL(ret, lfinish[1]);
6703 ADD_LABEL(ret, lfinish[0]);
6709make_name_for_block(
const rb_iseq_t *orig_iseq)
6714 if (ISEQ_BODY(orig_iseq)->parent_iseq != 0) {
6715 while (ISEQ_BODY(orig_iseq)->local_iseq != iseq) {
6716 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_BLOCK) {
6719 iseq = ISEQ_BODY(iseq)->parent_iseq;
6724 return rb_sprintf(
"block in %"PRIsVALUE, ISEQ_BODY(iseq)->location.label);
6727 return rb_sprintf(
"block (%d levels) in %"PRIsVALUE, level, ISEQ_BODY(iseq)->location.label);
6736 enl->ensure_node = node;
6737 enl->prev = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
6739 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl;
6749 while (erange->next != 0) {
6750 erange = erange->next;
6754 ne->end = erange->end;
6755 erange->end = lstart;
6761can_add_ensure_iseq(
const rb_iseq_t *iseq)
6764 if (ISEQ_COMPILE_DATA(iseq)->in_rescue && (e = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack) != NULL) {
6766 if (e->ensure_node)
return false;
6779 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
6781 DECL_ANCHOR(ensure);
6783 INIT_ANCHOR(ensure);
6785 if (enlp->erange != NULL) {
6786 DECL_ANCHOR(ensure_part);
6787 LABEL *lstart = NEW_LABEL(0);
6788 LABEL *lend = NEW_LABEL(0);
6789 INIT_ANCHOR(ensure_part);
6791 add_ensure_range(iseq, enlp->erange, lstart, lend);
6793 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enlp->prev;
6794 ADD_LABEL(ensure_part, lstart);
6795 NO_CHECK(COMPILE_POPPED(ensure_part,
"ensure part", enlp->ensure_node));
6796 ADD_LABEL(ensure_part, lend);
6797 ADD_SEQ(ensure, ensure_part);
6806 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = prev_enlp;
6807 ADD_SEQ(ret, ensure);
6812check_keyword(
const NODE *node)
6816 if (nd_type_p(node, NODE_LIST)) {
6817 while (RNODE_LIST(node)->nd_next) {
6818 node = RNODE_LIST(node)->nd_next;
6820 node = RNODE_LIST(node)->nd_head;
6823 return keyword_node_p(node);
6828keyword_node_single_splat_p(
NODE *kwnode)
6832 NODE *node = RNODE_HASH(kwnode)->nd_head;
6833 return RNODE_LIST(node)->nd_head == NULL &&
6834 RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next == NULL;
6839 NODE *kwnode,
unsigned int *flag_ptr)
6841 *flag_ptr |= VM_CALL_KW_SPLAT_MUT;
6842 ADD_INSN1(args, argn, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6843 ADD_INSN1(args, argn, newhash,
INT2FIX(0));
6844 compile_hash(iseq, args, kwnode, TRUE, FALSE);
6845 ADD_SEND(args, argn, id_core_hash_merge_kwd,
INT2FIX(2));
6848#define SPLATARRAY_FALSE 0
6849#define SPLATARRAY_TRUE 1
6850#define DUP_SINGLE_KW_SPLAT 2
6854 unsigned int *dup_rest,
unsigned int *flag_ptr,
struct rb_callinfo_kwarg **kwarg_ptr)
6856 if (!argn)
return 0;
6858 NODE *kwnode = NULL;
6860 switch (nd_type(argn)) {
6863 int len = compile_args(iseq, args, argn, &kwnode);
6864 RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_ARGS_SPLAT) == 0);
6867 if (compile_keyword_arg(iseq, args, kwnode, kwarg_ptr, flag_ptr)) {
6871 if (keyword_node_single_splat_p(kwnode) && (*dup_rest & DUP_SINGLE_KW_SPLAT)) {
6872 compile_single_keyword_splat_mutable(iseq, args, argn, kwnode, flag_ptr);
6875 compile_hash(iseq, args, kwnode, TRUE, FALSE);
6884 NO_CHECK(COMPILE(args,
"args (splat)", RNODE_SPLAT(argn)->nd_head));
6885 ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest & SPLATARRAY_TRUE));
6886 if (*dup_rest & SPLATARRAY_TRUE) *dup_rest &= ~SPLATARRAY_TRUE;
6887 if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
6888 RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0);
6891 case NODE_ARGSCAT: {
6892 if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
6893 int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, dup_rest, NULL, NULL);
6894 bool args_pushed =
false;
6896 if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) {
6897 int rest_len = compile_args(iseq, args, RNODE_ARGSCAT(argn)->nd_body, &kwnode);
6898 if (kwnode) rest_len--;
6899 ADD_INSN1(args, argn, pushtoarray,
INT2FIX(rest_len));
6903 RUBY_ASSERT(!check_keyword(RNODE_ARGSCAT(argn)->nd_body));
6904 NO_CHECK(COMPILE(args,
"args (cat: splat)", RNODE_ARGSCAT(argn)->nd_body));
6907 if (nd_type_p(RNODE_ARGSCAT(argn)->nd_head, NODE_LIST)) {
6908 ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest & SPLATARRAY_TRUE));
6909 if (*dup_rest & SPLATARRAY_TRUE) *dup_rest &= ~SPLATARRAY_TRUE;
6912 else if (!args_pushed) {
6913 ADD_INSN(args, argn, concattoarray);
6919 *flag_ptr |= VM_CALL_KW_SPLAT;
6920 compile_hash(iseq, args, kwnode, TRUE, FALSE);
6926 case NODE_ARGSPUSH: {
6927 if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
6928 int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, dup_rest, NULL, NULL);
6930 if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) {
6931 int rest_len = compile_args(iseq, args, RNODE_ARGSPUSH(argn)->nd_body, &kwnode);
6932 if (kwnode) rest_len--;
6933 ADD_INSN1(args, argn, newarray,
INT2FIX(rest_len));
6934 ADD_INSN1(args, argn, pushtoarray,
INT2FIX(1));
6937 if (keyword_node_p(RNODE_ARGSPUSH(argn)->nd_body)) {
6938 kwnode = RNODE_ARGSPUSH(argn)->nd_body;
6941 NO_CHECK(COMPILE(args,
"args (cat: splat)", RNODE_ARGSPUSH(argn)->nd_body));
6942 ADD_INSN1(args, argn, pushtoarray,
INT2FIX(1));
6948 *flag_ptr |= VM_CALL_KW_SPLAT;
6949 if (!keyword_node_single_splat_p(kwnode)) {
6950 *flag_ptr |= VM_CALL_KW_SPLAT_MUT;
6951 compile_hash(iseq, args, kwnode, TRUE, FALSE);
6953 else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
6954 compile_single_keyword_splat_mutable(iseq, args, argn, kwnode, flag_ptr);
6957 compile_hash(iseq, args, kwnode, TRUE, FALSE);
6965 UNKNOWN_NODE(
"setup_arg", argn,
Qnil);
6971setup_args_splat_mut(
unsigned int *flag,
int dup_rest,
int initial_dup_rest)
6973 if ((*flag & VM_CALL_ARGS_SPLAT) && dup_rest != initial_dup_rest) {
6974 *flag |= VM_CALL_ARGS_SPLAT_MUT;
6979setup_args_dup_rest_p(
const NODE *argn)
6981 switch(nd_type(argn)) {
6992 case NODE_IMAGINARY:
7005 return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
7008 if (setup_args_dup_rest_p(RNODE_LIST(argn)->nd_head)) {
7011 argn = RNODE_LIST(argn)->nd_next;
7024 unsigned int dup_rest = SPLATARRAY_TRUE, initial_dup_rest;
7027 const NODE *check_arg = nd_type_p(argn, NODE_BLOCK_PASS) ?
7028 RNODE_BLOCK_PASS(argn)->nd_head : argn;
7031 switch(nd_type(check_arg)) {
7034 dup_rest = SPLATARRAY_FALSE;
7038 dup_rest = !nd_type_p(RNODE_ARGSCAT(check_arg)->nd_head, NODE_LIST);
7040 case(NODE_ARGSPUSH):
7042 dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) ||
7043 (nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) &&
7044 nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) &&
7045 nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) &&
7046 !RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace);
7048 if (dup_rest == SPLATARRAY_FALSE) {
7050 NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
7052 NODE *key_node = RNODE_LIST(node)->nd_head;
7053 if (key_node && setup_args_dup_rest_p(key_node)) {
7054 dup_rest = SPLATARRAY_TRUE;
7058 node = RNODE_LIST(node)->nd_next;
7059 NODE *value_node = RNODE_LIST(node)->nd_head;
7060 if (setup_args_dup_rest_p(value_node)) {
7061 dup_rest = SPLATARRAY_TRUE;
7065 node = RNODE_LIST(node)->nd_next;
7074 if (check_arg != argn && setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
7076 dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT;
7079 initial_dup_rest = dup_rest;
7081 if (argn && nd_type_p(argn, NODE_BLOCK_PASS)) {
7082 DECL_ANCHOR(arg_block);
7083 INIT_ANCHOR(arg_block);
7085 if (RNODE_BLOCK_PASS(argn)->forwarding && ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) {
7086 int idx = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->local_table_size;
7088 RUBY_ASSERT(nd_type_p(RNODE_BLOCK_PASS(argn)->nd_head, NODE_ARGSPUSH));
7089 const NODE * arg_node =
7090 RNODE_ARGSPUSH(RNODE_BLOCK_PASS(argn)->nd_head)->nd_head;
7097 if (nd_type_p(arg_node, NODE_ARGSCAT)) {
7098 argc += setup_args_core(iseq, args, RNODE_ARGSCAT(arg_node)->nd_head, &dup_rest, flag, keywords);
7101 *flag |= VM_CALL_FORWARDING;
7103 ADD_GETLOCAL(args, argn, idx, get_lvar_level(iseq));
7104 setup_args_splat_mut(flag, dup_rest, initial_dup_rest);
7108 *flag |= VM_CALL_ARGS_BLOCKARG;
7110 NO_CHECK(COMPILE(arg_block,
"block", RNODE_BLOCK_PASS(argn)->nd_body));
7113 if (LIST_INSN_SIZE_ONE(arg_block)) {
7115 if (IS_INSN(elem)) {
7117 if (iobj->insn_id == BIN(getblockparam)) {
7118 iobj->insn_id = BIN(getblockparamproxy);
7122 ret =
INT2FIX(setup_args_core(iseq, args, RNODE_BLOCK_PASS(argn)->nd_head, &dup_rest, flag, keywords));
7123 ADD_SEQ(args, arg_block);
7126 ret =
INT2FIX(setup_args_core(iseq, args, argn, &dup_rest, flag, keywords));
7128 setup_args_splat_mut(flag, dup_rest, initial_dup_rest);
7135 const NODE *body = ptr;
7136 int line = nd_line(body);
7138 const rb_iseq_t *block = NEW_CHILD_ISEQ(body, make_name_for_block(ISEQ_BODY(iseq)->parent_iseq), ISEQ_TYPE_BLOCK, line);
7140 ADD_INSN1(ret, body, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7141 ADD_CALL_WITH_BLOCK(ret, body, id_core_set_postexe, argc, block);
7143 iseq_set_local_table(iseq, 0, 0);
7151 int line = nd_line(node);
7152 const NODE *line_node = node;
7153 LABEL *fail_label = NEW_LABEL(line), *end_label = NEW_LABEL(line);
7155#if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0)
7156 ADD_INSN1(ret, line_node, getglobal,
ID2SYM(idBACKREF));
7160 ADD_INSN(ret, line_node, dup);
7161 ADD_INSNL(ret, line_node, branchunless, fail_label);
7163 for (vars = node; vars; vars = RNODE_BLOCK(vars)->nd_next) {
7165 if (RNODE_BLOCK(vars)->nd_next) {
7166 ADD_INSN(ret, line_node, dup);
7169 NO_CHECK(COMPILE_POPPED(ret,
"capture", RNODE_BLOCK(vars)->nd_head));
7171 cap = new_insn_send(iseq, nd_line(line_node), nd_node_id(line_node), idAREF,
INT2FIX(1),
7174#if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
7175 if (!RNODE_BLOCK(vars)->nd_next && vars == node) {
7180 ADD_INSNL(nom, line_node, jump, end_label);
7181 ADD_LABEL(nom, fail_label);
7183 ADD_INSN(nom, line_node, pop);
7184 ADD_INSN(nom, line_node, putnil);
7186 ADD_LABEL(nom, end_label);
7187 (nom->last->next = cap->link.next)->prev = nom->last;
7188 (cap->link.next = nom->anchor.next)->prev = &cap->link;
7193 ADD_INSNL(ret, line_node, jump, end_label);
7194 ADD_LABEL(ret, fail_label);
7195 ADD_INSN(ret, line_node, pop);
7196 for (vars = node; vars; vars = RNODE_BLOCK(vars)->nd_next) {
7198 NO_CHECK(COMPILE_POPPED(ret,
"capture", RNODE_BLOCK(vars)->nd_head));
7200 ((
INSN*)last)->insn_id = BIN(putnil);
7201 ((
INSN*)last)->operand_size = 0;
7203 ADD_LABEL(ret, end_label);
7207optimizable_range_item_p(
const NODE *n)
7209 if (!n)
return FALSE;
7210 switch (nd_type(n)) {
7223optimized_range_item(
const NODE *n)
7225 switch (nd_type(n)) {
7227 return rb_node_line_lineno_val(n);
7229 return rb_node_integer_literal_val(n);
7231 return rb_node_float_literal_val(n);
7233 return rb_node_rational_literal_val(n);
7234 case NODE_IMAGINARY:
7235 return rb_node_imaginary_literal_val(n);
7239 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(n)));
7246 const NODE *
const node_body =
type == NODE_IF ? RNODE_IF(node)->nd_body : RNODE_UNLESS(node)->nd_else;
7247 const NODE *
const node_else =
type == NODE_IF ? RNODE_IF(node)->nd_else : RNODE_UNLESS(node)->nd_body;
7249 const int line = nd_line(node);
7250 const NODE *line_node = node;
7251 DECL_ANCHOR(cond_seq);
7252 LABEL *then_label, *else_label, *end_label;
7255 INIT_ANCHOR(cond_seq);
7256 then_label = NEW_LABEL(line);
7257 else_label = NEW_LABEL(line);
7260 NODE *cond = RNODE_IF(node)->nd_cond;
7261 if (nd_type(cond) == NODE_BLOCK) {
7262 cond = RNODE_BLOCK(cond)->nd_head;
7265 CHECK(compile_branch_condition(iseq, cond_seq, cond, then_label, else_label));
7266 ADD_SEQ(ret, cond_seq);
7268 if (then_label->refcnt && else_label->refcnt) {
7269 branches = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node),
type == NODE_IF ?
"if" :
"unless");
7272 if (then_label->refcnt) {
7273 ADD_LABEL(ret, then_label);
7275 DECL_ANCHOR(then_seq);
7276 INIT_ANCHOR(then_seq);
7277 CHECK(COMPILE_(then_seq,
"then", node_body, popped));
7279 if (else_label->refcnt) {
7280 const NODE *
const coverage_node = node_body ? node_body : node;
7281 add_trace_branch_coverage(
7284 nd_code_loc(coverage_node),
7285 nd_node_id(coverage_node),
7287 type == NODE_IF ?
"then" :
"else",
7289 end_label = NEW_LABEL(line);
7290 ADD_INSNL(then_seq, line_node, jump, end_label);
7292 ADD_INSN(then_seq, line_node, pop);
7295 ADD_SEQ(ret, then_seq);
7298 if (else_label->refcnt) {
7299 ADD_LABEL(ret, else_label);
7301 DECL_ANCHOR(else_seq);
7302 INIT_ANCHOR(else_seq);
7303 CHECK(COMPILE_(else_seq,
"else", node_else, popped));
7305 if (then_label->refcnt) {
7306 const NODE *
const coverage_node = node_else ? node_else : node;
7307 add_trace_branch_coverage(
7310 nd_code_loc(coverage_node),
7311 nd_node_id(coverage_node),
7313 type == NODE_IF ?
"else" :
"then",
7316 ADD_SEQ(ret, else_seq);
7320 ADD_LABEL(ret, end_label);
7330 const NODE *node = orig_node;
7331 LABEL *endlabel, *elselabel;
7333 DECL_ANCHOR(body_seq);
7334 DECL_ANCHOR(cond_seq);
7335 int only_special_literals = 1;
7336 VALUE literals = cdhash_new(0);
7338 enum node_type
type;
7339 const NODE *line_node;
7344 INIT_ANCHOR(body_seq);
7345 INIT_ANCHOR(cond_seq);
7347 CHECK(COMPILE(head,
"case base", RNODE_CASE(node)->nd_head));
7349 branches = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node),
"case");
7351 node = RNODE_CASE(node)->nd_body;
7352 EXPECT_NODE(
"NODE_CASE", node, NODE_WHEN, COMPILE_NG);
7353 type = nd_type(node);
7354 line = nd_line(node);
7357 endlabel = NEW_LABEL(line);
7358 elselabel = NEW_LABEL(line);
7362 while (
type == NODE_WHEN) {
7365 l1 = NEW_LABEL(line);
7366 ADD_LABEL(body_seq, l1);
7367 ADD_INSN(body_seq, line_node, pop);
7369 const NODE *
const coverage_node = RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node;
7370 add_trace_branch_coverage(
7373 nd_code_loc(coverage_node),
7374 nd_node_id(coverage_node),
7379 CHECK(COMPILE_(body_seq,
"when body", RNODE_WHEN(node)->nd_body, popped));
7380 ADD_INSNL(body_seq, line_node, jump, endlabel);
7382 vals = RNODE_WHEN(node)->nd_head;
7384 switch (nd_type(vals)) {
7386 only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
7387 if (only_special_literals < 0)
return COMPILE_NG;
7392 only_special_literals = 0;
7393 CHECK(when_splat_vals(iseq, cond_seq, vals, l1, only_special_literals, literals));
7396 UNKNOWN_NODE(
"NODE_CASE", vals, COMPILE_NG);
7400 EXPECT_NODE_NONULL(
"NODE_CASE", node, NODE_LIST, COMPILE_NG);
7403 node = RNODE_WHEN(node)->nd_next;
7407 type = nd_type(node);
7408 line = nd_line(node);
7413 ADD_LABEL(cond_seq, elselabel);
7414 ADD_INSN(cond_seq, line_node, pop);
7415 add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(node), nd_node_id(node), branch_id,
"else", branches);
7416 CHECK(COMPILE_(cond_seq,
"else", node, popped));
7417 ADD_INSNL(cond_seq, line_node, jump, endlabel);
7420 debugs(
"== else (implicit)\n");
7421 ADD_LABEL(cond_seq, elselabel);
7422 ADD_INSN(cond_seq, orig_node, pop);
7423 add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(orig_node), nd_node_id(orig_node), branch_id,
"else", branches);
7425 ADD_INSN(cond_seq, orig_node, putnil);
7427 ADD_INSNL(cond_seq, orig_node, jump, endlabel);
7430 if (only_special_literals && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
7431 ADD_INSN(ret, orig_node, dup);
7432 ADD_INSN2(ret, orig_node, opt_case_dispatch, literals, elselabel);
7434 LABEL_REF(elselabel);
7437 ADD_SEQ(ret, cond_seq);
7438 ADD_SEQ(ret, body_seq);
7439 ADD_LABEL(ret, endlabel);
7448 const NODE *node = RNODE_CASE2(orig_node)->nd_body;
7450 DECL_ANCHOR(body_seq);
7454 branches = decl_branch_base(iseq, nd_node_id(orig_node), nd_code_loc(orig_node),
"case");
7456 INIT_ANCHOR(body_seq);
7457 endlabel = NEW_LABEL(nd_line(node));
7459 while (node && nd_type_p(node, NODE_WHEN)) {
7460 const int line = nd_line(node);
7461 LABEL *l1 = NEW_LABEL(line);
7462 ADD_LABEL(body_seq, l1);
7464 const NODE *
const coverage_node = RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node;
7465 add_trace_branch_coverage(
7468 nd_code_loc(coverage_node),
7469 nd_node_id(coverage_node),
7474 CHECK(COMPILE_(body_seq,
"when", RNODE_WHEN(node)->nd_body, popped));
7475 ADD_INSNL(body_seq, node, jump, endlabel);
7477 vals = RNODE_WHEN(node)->nd_head;
7479 EXPECT_NODE_NONULL(
"NODE_WHEN", node, NODE_LIST, COMPILE_NG);
7481 switch (nd_type(vals)) {
7485 val = RNODE_LIST(vals)->nd_head;
7486 lnext = NEW_LABEL(nd_line(val));
7487 debug_compile(
"== when2\n", (
void)0);
7488 CHECK(compile_branch_condition(iseq, ret, val, l1, lnext));
7489 ADD_LABEL(ret, lnext);
7490 vals = RNODE_LIST(vals)->nd_next;
7496 ADD_INSN(ret, vals, putnil);
7497 CHECK(COMPILE(ret,
"when2/cond splat", vals));
7498 ADD_INSN1(ret, vals, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY));
7499 ADD_INSNL(ret, vals, branchif, l1);
7502 UNKNOWN_NODE(
"NODE_WHEN", vals, COMPILE_NG);
7504 node = RNODE_WHEN(node)->nd_next;
7507 const NODE *
const coverage_node = node ? node : orig_node;
7508 add_trace_branch_coverage(
7511 nd_code_loc(coverage_node),
7512 nd_node_id(coverage_node),
7516 CHECK(COMPILE_(ret,
"else", node, popped));
7517 ADD_INSNL(ret, orig_node, jump, endlabel);
7519 ADD_SEQ(ret, body_seq);
7520 ADD_LABEL(ret, endlabel);
7524static 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);
7526static 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);
7527static 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);
7528static int iseq_compile_pattern_set_general_errmsg(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
VALUE errmsg,
int base_index);
7529static 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);
7530static int iseq_compile_pattern_set_eqq_errmsg(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
int base_index);
7532#define CASE3_BI_OFFSET_DECONSTRUCTED_CACHE 0
7533#define CASE3_BI_OFFSET_ERROR_STRING 1
7534#define CASE3_BI_OFFSET_KEY_ERROR_P 2
7535#define CASE3_BI_OFFSET_KEY_ERROR_MATCHEE 3
7536#define CASE3_BI_OFFSET_KEY_ERROR_KEY 4
7539iseq_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)
7541 const int line = nd_line(node);
7542 const NODE *line_node = node;
7544 switch (nd_type(node)) {
7598 const NODE *args = RNODE_ARYPTN(node)->pre_args;
7599 const int pre_args_num = RNODE_ARYPTN(node)->pre_args ?
rb_long2int(RNODE_LIST(RNODE_ARYPTN(node)->pre_args)->as.nd_alen) : 0;
7600 const int post_args_num = RNODE_ARYPTN(node)->post_args ?
rb_long2int(RNODE_LIST(RNODE_ARYPTN(node)->post_args)->as.nd_alen) : 0;
7602 const int min_argc = pre_args_num + post_args_num;
7603 const int use_rest_num = RNODE_ARYPTN(node)->rest_arg && (NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg) ||
7604 (!NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg) && post_args_num > 0));
7606 LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
7608 match_failed = NEW_LABEL(line);
7609 type_error = NEW_LABEL(line);
7610 deconstruct = NEW_LABEL(line);
7611 deconstructed = NEW_LABEL(line);
7614 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
7615 ADD_INSN(ret, line_node, swap);
7621 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
7623 CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
7625 ADD_INSN(ret, line_node, dup);
7626 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
7627 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
7628 ADD_SEND(ret, line_node, RNODE_ARYPTN(node)->rest_arg ? idGE : idEq,
INT2FIX(1));
7629 if (in_single_pattern) {
7630 CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node,
7631 RNODE_ARYPTN(node)->rest_arg ? rb_fstring_lit(
"%p length mismatch (given %p, expected %p+)") :
7632 rb_fstring_lit(
"%p length mismatch (given %p, expected %p)"),
7633 INT2FIX(min_argc), base_index + 1 ));
7635 ADD_INSNL(ret, line_node, branchunless, match_failed);
7637 for (i = 0; i < pre_args_num; i++) {
7638 ADD_INSN(ret, line_node, dup);
7639 ADD_INSN1(ret, line_node, putobject,
INT2FIX(i));
7640 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
7641 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
7642 args = RNODE_LIST(args)->nd_next;
7645 if (RNODE_ARYPTN(node)->rest_arg) {
7646 if (NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg)) {
7647 ADD_INSN(ret, line_node, dup);
7648 ADD_INSN1(ret, line_node, putobject,
INT2FIX(pre_args_num));
7649 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
7650 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
7651 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
7652 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
7653 ADD_INSN1(ret, line_node, setn,
INT2FIX(4));
7654 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
7656 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_ARYPTN(node)->rest_arg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
7659 if (post_args_num > 0) {
7660 ADD_INSN(ret, line_node, dup);
7661 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
7662 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
7663 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
7664 ADD_INSN1(ret, line_node, setn,
INT2FIX(2));
7665 ADD_INSN(ret, line_node, pop);
7670 args = RNODE_ARYPTN(node)->post_args;
7671 for (i = 0; i < post_args_num; i++) {
7672 ADD_INSN(ret, line_node, dup);
7674 ADD_INSN1(ret, line_node, putobject,
INT2FIX(pre_args_num + i));
7675 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7676 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
7678 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
7679 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
7680 args = RNODE_LIST(args)->nd_next;
7683 ADD_INSN(ret, line_node, pop);
7685 ADD_INSN(ret, line_node, pop);
7687 ADD_INSNL(ret, line_node, jump, matched);
7688 ADD_INSN(ret, line_node, putnil);
7690 ADD_INSN(ret, line_node, putnil);
7693 ADD_LABEL(ret, type_error);
7694 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7696 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct must return Array"));
7697 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
7698 ADD_INSN(ret, line_node, pop);
7700 ADD_LABEL(ret, match_failed);
7701 ADD_INSN(ret, line_node, pop);
7703 ADD_INSN(ret, line_node, pop);
7705 ADD_INSNL(ret, line_node, jump, unmatched);
7758 const NODE *args = RNODE_FNDPTN(node)->args;
7759 const int args_num = RNODE_FNDPTN(node)->args ?
rb_long2int(RNODE_LIST(RNODE_FNDPTN(node)->args)->as.nd_alen) : 0;
7761 LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
7762 match_failed = NEW_LABEL(line);
7763 type_error = NEW_LABEL(line);
7764 deconstruct = NEW_LABEL(line);
7765 deconstructed = NEW_LABEL(line);
7767 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
7769 CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
7771 ADD_INSN(ret, line_node, dup);
7772 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
7773 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
7774 ADD_SEND(ret, line_node, idGE,
INT2FIX(1));
7775 if (in_single_pattern) {
7776 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 ));
7778 ADD_INSNL(ret, line_node, branchunless, match_failed);
7781 LABEL *while_begin = NEW_LABEL(nd_line(node));
7782 LABEL *next_loop = NEW_LABEL(nd_line(node));
7783 LABEL *find_succeeded = NEW_LABEL(line);
7784 LABEL *find_failed = NEW_LABEL(nd_line(node));
7787 ADD_INSN(ret, line_node, dup);
7788 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
7790 ADD_INSN(ret, line_node, dup);
7791 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
7792 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
7794 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
7796 ADD_LABEL(ret, while_begin);
7798 ADD_INSN(ret, line_node, dup);
7799 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
7800 ADD_SEND(ret, line_node, idLE,
INT2FIX(1));
7801 ADD_INSNL(ret, line_node, branchunless, find_failed);
7803 for (j = 0; j < args_num; j++) {
7804 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7805 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
7807 ADD_INSN1(ret, line_node, putobject,
INT2FIX(j));
7808 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
7810 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
7812 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, next_loop, in_single_pattern, in_alt_pattern, base_index + 4 ,
false));
7813 args = RNODE_LIST(args)->nd_next;
7816 if (NODE_NAMED_REST_P(RNODE_FNDPTN(node)->pre_rest_arg)) {
7817 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7818 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
7819 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
7820 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
7821 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));
7823 if (NODE_NAMED_REST_P(RNODE_FNDPTN(node)->post_rest_arg)) {
7824 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7825 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
7826 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
7827 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
7828 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7829 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
7830 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));
7832 ADD_INSNL(ret, line_node, jump, find_succeeded);
7834 ADD_LABEL(ret, next_loop);
7835 ADD_INSN1(ret, line_node, putobject,
INT2FIX(1));
7836 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
7837 ADD_INSNL(ret, line_node, jump, while_begin);
7839 ADD_LABEL(ret, find_failed);
7840 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(3));
7841 if (in_single_pattern) {
7842 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7843 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"%p does not match to find pattern"));
7844 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
7845 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(2));
7846 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
7848 ADD_INSN1(ret, line_node, putobject,
Qfalse);
7849 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
7851 ADD_INSN(ret, line_node, pop);
7852 ADD_INSN(ret, line_node, pop);
7854 ADD_INSNL(ret, line_node, jump, match_failed);
7855 ADD_INSN1(ret, line_node, dupn,
INT2FIX(3));
7857 ADD_LABEL(ret, find_succeeded);
7858 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(3));
7861 ADD_INSN(ret, line_node, pop);
7862 ADD_INSNL(ret, line_node, jump, matched);
7863 ADD_INSN(ret, line_node, putnil);
7865 ADD_LABEL(ret, type_error);
7866 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7868 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct must return Array"));
7869 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
7870 ADD_INSN(ret, line_node, pop);
7872 ADD_LABEL(ret, match_failed);
7873 ADD_INSN(ret, line_node, pop);
7874 ADD_INSNL(ret, line_node, jump, unmatched);
7938 LABEL *match_failed, *type_error;
7941 match_failed = NEW_LABEL(line);
7942 type_error = NEW_LABEL(line);
7944 if (RNODE_HSHPTN(node)->nd_pkwargs && !RNODE_HSHPTN(node)->nd_pkwrestarg) {
7945 const NODE *kw_args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head;
7946 keys =
rb_ary_new_capa(kw_args ? RNODE_LIST(kw_args)->as.nd_alen/2 : 0);
7948 rb_ary_push(keys, get_symbol_value(iseq, RNODE_LIST(kw_args)->nd_head));
7949 kw_args = RNODE_LIST(RNODE_LIST(kw_args)->nd_next)->nd_next;
7953 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
7955 ADD_INSN(ret, line_node, dup);
7956 ADD_INSN1(ret, line_node, putobject,
ID2SYM(rb_intern(
"deconstruct_keys")));
7957 ADD_SEND(ret, line_node, idRespond_to,
INT2FIX(1));
7958 if (in_single_pattern) {
7959 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p does not respond to #deconstruct_keys"), base_index + 1 ));
7961 ADD_INSNL(ret, line_node, branchunless, match_failed);
7964 ADD_INSN(ret, line_node, putnil);
7968 ADD_INSN1(ret, line_node, duparray, keys);
7971 ADD_SEND(ret, line_node, rb_intern(
"deconstruct_keys"),
INT2FIX(1));
7973 ADD_INSN(ret, line_node, dup);
7975 ADD_INSNL(ret, line_node, branchunless, type_error);
7977 if (RNODE_HSHPTN(node)->nd_pkwrestarg) {
7978 ADD_SEND(ret, line_node, rb_intern(
"dup"),
INT2FIX(0));
7981 if (RNODE_HSHPTN(node)->nd_pkwargs) {
7985 args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head;
7987 DECL_ANCHOR(match_values);
7988 INIT_ANCHOR(match_values);
7989 keys_num =
rb_long2int(RNODE_LIST(args)->as.nd_alen) / 2;
7990 for (i = 0; i < keys_num; i++) {
7991 NODE *key_node = RNODE_LIST(args)->nd_head;
7992 NODE *value_node = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_head;
7993 VALUE key = get_symbol_value(iseq, key_node);
7995 ADD_INSN(ret, line_node, dup);
7996 ADD_INSN1(ret, line_node, putobject, key);
7997 ADD_SEND(ret, line_node, rb_intern(
"key?"),
INT2FIX(1));
7998 if (in_single_pattern) {
7999 LABEL *match_succeeded;
8000 match_succeeded = NEW_LABEL(line);
8002 ADD_INSN(ret, line_node, dup);
8003 ADD_INSNL(ret, line_node, branchif, match_succeeded);
8007 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 2 ));
8008 ADD_INSN1(ret, line_node, putobject,
Qtrue);
8009 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 3 ));
8010 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
8011 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4 ));
8012 ADD_INSN1(ret, line_node, putobject, key);
8013 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_KEY + 5 ));
8015 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(4));
8017 ADD_LABEL(ret, match_succeeded);
8019 ADD_INSNL(ret, line_node, branchunless, match_failed);
8021 ADD_INSN(match_values, line_node, dup);
8022 ADD_INSN1(match_values, line_node, putobject, key);
8023 ADD_SEND(match_values, line_node, RNODE_HSHPTN(node)->nd_pkwrestarg ? rb_intern(
"delete") : idAREF,
INT2FIX(1));
8024 CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
8025 args = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_next;
8027 ADD_SEQ(ret, match_values);
8031 ADD_INSN(ret, line_node, dup);
8032 ADD_SEND(ret, line_node, idEmptyP,
INT2FIX(0));
8033 if (in_single_pattern) {
8034 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p is not empty"), base_index + 1 ));
8036 ADD_INSNL(ret, line_node, branchunless, match_failed);
8039 if (RNODE_HSHPTN(node)->nd_pkwrestarg) {
8040 if (RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
8041 ADD_INSN(ret, line_node, dup);
8042 ADD_SEND(ret, line_node, idEmptyP,
INT2FIX(0));
8043 if (in_single_pattern) {
8044 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"rest of %p is not empty"), base_index + 1 ));
8046 ADD_INSNL(ret, line_node, branchunless, match_failed);
8049 ADD_INSN(ret, line_node, dup);
8050 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_HSHPTN(node)->nd_pkwrestarg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
8054 ADD_INSN(ret, line_node, pop);
8055 ADD_INSNL(ret, line_node, jump, matched);
8056 ADD_INSN(ret, line_node, putnil);
8058 ADD_LABEL(ret, type_error);
8059 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
8061 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct_keys must return Hash"));
8062 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
8063 ADD_INSN(ret, line_node, pop);
8065 ADD_LABEL(ret, match_failed);
8066 ADD_INSN(ret, line_node, pop);
8067 ADD_INSNL(ret, line_node, jump, unmatched);
8076 case NODE_IMAGINARY:
8104 CHECK(COMPILE(ret,
"case in literal", node));
8105 if (in_single_pattern) {
8106 ADD_INSN1(ret, line_node, dupn,
INT2FIX(2));
8108 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
8109 if (in_single_pattern) {
8110 CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 2 ));
8112 ADD_INSNL(ret, line_node, branchif, matched);
8113 ADD_INSNL(ret, line_node, jump, unmatched);
8117 ID id = RNODE_LASGN(node)->nd_vid;
8118 int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
8120 if (in_alt_pattern) {
8121 const char *name = rb_id2name(
id);
8122 if (name && strlen(name) > 0 && name[0] !=
'_') {
8123 COMPILE_ERROR(ERROR_ARGS
"illegal variable in alternative pattern (%"PRIsVALUE
")",
8129 ADD_SETLOCAL(ret, line_node, idx, get_lvar_level(iseq));
8130 ADD_INSNL(ret, line_node, jump, matched);
8135 ID id = RNODE_DASGN(node)->nd_vid;
8137 idx = get_dyna_var_idx(iseq,
id, &lv, &ls);
8139 if (in_alt_pattern) {
8140 const char *name = rb_id2name(
id);
8141 if (name && strlen(name) > 0 && name[0] !=
'_') {
8142 COMPILE_ERROR(ERROR_ARGS
"illegal variable in alternative pattern (%"PRIsVALUE
")",
8149 COMPILE_ERROR(ERROR_ARGS
"NODE_DASGN: unknown id (%"PRIsVALUE
")",
8153 ADD_SETLOCAL(ret, line_node, ls - idx, lv);
8154 ADD_INSNL(ret, line_node, jump, matched);
8159 LABEL *match_failed;
8160 match_failed = unmatched;
8161 CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_IF(node)->nd_body, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
8162 CHECK(COMPILE(ret,
"case in if", RNODE_IF(node)->nd_cond));
8163 if (in_single_pattern) {
8164 LABEL *match_succeeded;
8165 match_succeeded = NEW_LABEL(line);
8167 ADD_INSN(ret, line_node, dup);
8168 if (nd_type_p(node, NODE_IF)) {
8169 ADD_INSNL(ret, line_node, branchif, match_succeeded);
8172 ADD_INSNL(ret, line_node, branchunless, match_succeeded);
8175 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"guard clause does not return true"));
8176 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
8177 ADD_INSN1(ret, line_node, putobject,
Qfalse);
8178 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
8180 ADD_INSN(ret, line_node, pop);
8181 ADD_INSN(ret, line_node, pop);
8183 ADD_LABEL(ret, match_succeeded);
8185 if (nd_type_p(node, NODE_IF)) {
8186 ADD_INSNL(ret, line_node, branchunless, match_failed);
8189 ADD_INSNL(ret, line_node, branchif, match_failed);
8191 ADD_INSNL(ret, line_node, jump, matched);
8196 LABEL *match_failed;
8197 match_failed = NEW_LABEL(line);
8199 n = RNODE_HASH(node)->nd_head;
8200 if (! (nd_type_p(n, NODE_LIST) && RNODE_LIST(n)->as.nd_alen == 2)) {
8201 COMPILE_ERROR(ERROR_ARGS
"unexpected node");
8205 ADD_INSN(ret, line_node, dup);
8206 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));
8207 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));
8208 ADD_INSN(ret, line_node, putnil);
8210 ADD_LABEL(ret, match_failed);
8211 ADD_INSN(ret, line_node, pop);
8212 ADD_INSNL(ret, line_node, jump, unmatched);
8216 LABEL *match_succeeded, *fin;
8217 match_succeeded = NEW_LABEL(line);
8218 fin = NEW_LABEL(line);
8220 ADD_INSN(ret, line_node, dup);
8221 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));
8222 ADD_LABEL(ret, match_succeeded);
8223 ADD_INSN(ret, line_node, pop);
8224 ADD_INSNL(ret, line_node, jump, matched);
8225 ADD_INSN(ret, line_node, putnil);
8226 ADD_LABEL(ret, fin);
8227 CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_OR(node)->nd_2nd, matched, unmatched, in_single_pattern,
true, base_index, use_deconstructed_cache));
8231 UNKNOWN_NODE(
"NODE_IN", node, COMPILE_NG);
8237iseq_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)
8239 LABEL *fin = NEW_LABEL(nd_line(node));
8240 CHECK(iseq_compile_pattern_each(iseq, ret, node, fin, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
8241 ADD_LABEL(ret, fin);
8246iseq_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)
8248 const NODE *line_node = node;
8250 if (RNODE_ARYPTN(node)->nd_pconst) {
8251 ADD_INSN(ret, line_node, dup);
8252 CHECK(COMPILE(ret,
"constant", RNODE_ARYPTN(node)->nd_pconst));
8253 if (in_single_pattern) {
8254 ADD_INSN1(ret, line_node, dupn,
INT2FIX(2));
8256 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
8257 if (in_single_pattern) {
8258 CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 3 ));
8260 ADD_INSNL(ret, line_node, branchunless, match_failed);
8267iseq_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)
8269 const NODE *line_node = node;
8273 if (use_deconstructed_cache) {
8275 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
8276 ADD_INSNL(ret, line_node, branchnil, deconstruct);
8279 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
8280 ADD_INSNL(ret, line_node, branchunless, match_failed);
8283 ADD_INSN(ret, line_node, pop);
8284 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE - 1 ));
8285 ADD_INSNL(ret, line_node, jump, deconstructed);
8288 ADD_INSNL(ret, line_node, jump, deconstruct);
8291 ADD_LABEL(ret, deconstruct);
8292 ADD_INSN(ret, line_node, dup);
8293 ADD_INSN1(ret, line_node, putobject,
ID2SYM(rb_intern(
"deconstruct")));
8294 ADD_SEND(ret, line_node, idRespond_to,
INT2FIX(1));
8297 if (use_deconstructed_cache) {
8298 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE + 1 ));
8301 if (in_single_pattern) {
8302 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p does not respond to #deconstruct"), base_index + 1 ));
8305 ADD_INSNL(ret, line_node, branchunless, match_failed);
8307 ADD_SEND(ret, line_node, rb_intern(
"deconstruct"),
INT2FIX(0));
8310 if (use_deconstructed_cache) {
8311 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
8314 ADD_INSN(ret, line_node, dup);
8316 ADD_INSNL(ret, line_node, branchunless, type_error);
8318 ADD_LABEL(ret, deconstructed);
8334 const int line = nd_line(node);
8335 const NODE *line_node = node;
8336 LABEL *match_succeeded = NEW_LABEL(line);
8338 ADD_INSN(ret, line_node, dup);
8339 ADD_INSNL(ret, line_node, branchif, match_succeeded);
8341 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
8342 ADD_INSN1(ret, line_node, putobject, errmsg);
8343 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
8344 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(2));
8345 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
8347 ADD_INSN1(ret, line_node, putobject,
Qfalse);
8348 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
8350 ADD_INSN(ret, line_node, pop);
8351 ADD_INSN(ret, line_node, pop);
8352 ADD_LABEL(ret, match_succeeded);
8368 const int line = nd_line(node);
8369 const NODE *line_node = node;
8370 LABEL *match_succeeded = NEW_LABEL(line);
8372 ADD_INSN(ret, line_node, dup);
8373 ADD_INSNL(ret, line_node, branchif, match_succeeded);
8375 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
8376 ADD_INSN1(ret, line_node, putobject, errmsg);
8377 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
8378 ADD_INSN(ret, line_node, dup);
8379 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
8380 ADD_INSN1(ret, line_node, putobject, pattern_length);
8381 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(4));
8382 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
8384 ADD_INSN1(ret, line_node, putobject,
Qfalse);
8385 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2));
8387 ADD_INSN(ret, line_node, pop);
8388 ADD_INSN(ret, line_node, pop);
8389 ADD_LABEL(ret, match_succeeded);
8395iseq_compile_pattern_set_eqq_errmsg(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
int base_index)
8405 const int line = nd_line(node);
8406 const NODE *line_node = node;
8407 LABEL *match_succeeded = NEW_LABEL(line);
8409 ADD_INSN(ret, line_node, dup);
8410 ADD_INSNL(ret, line_node, branchif, match_succeeded);
8412 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
8413 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"%p === %p does not return true"));
8414 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
8415 ADD_INSN1(ret, line_node, topn,
INT2FIX(5));
8416 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(3));
8417 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
8419 ADD_INSN1(ret, line_node, putobject,
Qfalse);
8420 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
8422 ADD_INSN(ret, line_node, pop);
8423 ADD_INSN(ret, line_node, pop);
8425 ADD_LABEL(ret, match_succeeded);
8426 ADD_INSN1(ret, line_node, setn,
INT2FIX(2));
8427 ADD_INSN(ret, line_node, pop);
8428 ADD_INSN(ret, line_node, pop);
8436 const NODE *pattern;
8437 const NODE *node = orig_node;
8438 LABEL *endlabel, *elselabel;
8440 DECL_ANCHOR(body_seq);
8441 DECL_ANCHOR(cond_seq);
8443 enum node_type
type;
8444 const NODE *line_node;
8447 bool single_pattern;
8450 INIT_ANCHOR(body_seq);
8451 INIT_ANCHOR(cond_seq);
8453 branches = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node),
"case");
8455 node = RNODE_CASE3(node)->nd_body;
8456 EXPECT_NODE(
"NODE_CASE3", node, NODE_IN, COMPILE_NG);
8457 type = nd_type(node);
8458 line = nd_line(node);
8460 single_pattern = !RNODE_IN(node)->nd_next;
8462 endlabel = NEW_LABEL(line);
8463 elselabel = NEW_LABEL(line);
8465 if (single_pattern) {
8467 ADD_INSN(head, line_node, putnil);
8468 ADD_INSN(head, line_node, putnil);
8469 ADD_INSN1(head, line_node, putobject,
Qfalse);
8470 ADD_INSN(head, line_node, putnil);
8472 ADD_INSN(head, line_node, putnil);
8474 CHECK(COMPILE(head,
"case base", RNODE_CASE3(orig_node)->nd_head));
8478 while (
type == NODE_IN) {
8482 ADD_INSN(body_seq, line_node, putnil);
8484 l1 = NEW_LABEL(line);
8485 ADD_LABEL(body_seq, l1);
8486 ADD_INSN1(body_seq, line_node, adjuststack,
INT2FIX(single_pattern ? 6 : 2));
8488 const NODE *
const coverage_node = RNODE_IN(node)->nd_body ? RNODE_IN(node)->nd_body : node;
8489 add_trace_branch_coverage(
8492 nd_code_loc(coverage_node),
8493 nd_node_id(coverage_node),
8498 CHECK(COMPILE_(body_seq,
"in body", RNODE_IN(node)->nd_body, popped));
8499 ADD_INSNL(body_seq, line_node, jump, endlabel);
8501 pattern = RNODE_IN(node)->nd_head;
8503 int pat_line = nd_line(pattern);
8504 LABEL *next_pat = NEW_LABEL(pat_line);
8505 ADD_INSN (cond_seq, pattern, dup);
8507 CHECK(iseq_compile_pattern_each(iseq, cond_seq, pattern, l1, next_pat, single_pattern,
false, 2,
true));
8508 ADD_LABEL(cond_seq, next_pat);
8509 LABEL_UNREMOVABLE(next_pat);
8512 COMPILE_ERROR(ERROR_ARGS
"unexpected node");
8516 node = RNODE_IN(node)->nd_next;
8520 type = nd_type(node);
8521 line = nd_line(node);
8526 ADD_LABEL(cond_seq, elselabel);
8527 ADD_INSN(cond_seq, line_node, pop);
8528 ADD_INSN(cond_seq, line_node, pop);
8529 add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(node), nd_node_id(node), branch_id,
"else", branches);
8530 CHECK(COMPILE_(cond_seq,
"else", node, popped));
8531 ADD_INSNL(cond_seq, line_node, jump, endlabel);
8532 ADD_INSN(cond_seq, line_node, putnil);
8534 ADD_INSN(cond_seq, line_node, putnil);
8538 debugs(
"== else (implicit)\n");
8539 ADD_LABEL(cond_seq, elselabel);
8540 add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(orig_node), nd_node_id(orig_node), branch_id,
"else", branches);
8541 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
8543 if (single_pattern) {
8551 LABEL *key_error, *fin;
8554 key_error = NEW_LABEL(line);
8555 fin = NEW_LABEL(line);
8558 kw_arg->references = 0;
8559 kw_arg->keyword_len = 2;
8560 kw_arg->keywords[0] =
ID2SYM(rb_intern(
"matchee"));
8561 kw_arg->keywords[1] =
ID2SYM(rb_intern(
"key"));
8563 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_P + 2));
8564 ADD_INSNL(cond_seq, orig_node, branchif, key_error);
8566 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
8567 ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit(
"%p: %s"));
8568 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(4));
8569 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6));
8570 ADD_SEND(cond_seq, orig_node, id_core_sprintf,
INT2FIX(3));
8571 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(2));
8572 ADD_INSNL(cond_seq, orig_node, jump, fin);
8574 ADD_LABEL(cond_seq, key_error);
8576 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
8577 ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit(
"%p: %s"));
8578 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(4));
8579 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6));
8580 ADD_SEND(cond_seq, orig_node, id_core_sprintf,
INT2FIX(3));
8581 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4));
8582 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_KEY + 5));
8583 ADD_SEND_R(cond_seq, orig_node, rb_intern(
"new"),
INT2FIX(1), NULL,
INT2FIX(VM_CALL_KWARG), kw_arg);
8584 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(1));
8586 ADD_LABEL(cond_seq, fin);
8590 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(2));
8591 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(2));
8593 ADD_INSN1(cond_seq, orig_node, adjuststack,
INT2FIX(single_pattern ? 7 : 3));
8595 ADD_INSN(cond_seq, orig_node, putnil);
8597 ADD_INSNL(cond_seq, orig_node, jump, endlabel);
8598 ADD_INSN1(cond_seq, orig_node, dupn,
INT2FIX(single_pattern ? 5 : 1));
8600 ADD_INSN(cond_seq, line_node, putnil);
8604 ADD_SEQ(ret, cond_seq);
8605 ADD_SEQ(ret, body_seq);
8606 ADD_LABEL(ret, endlabel);
8610#undef CASE3_BI_OFFSET_DECONSTRUCTED_CACHE
8611#undef CASE3_BI_OFFSET_ERROR_STRING
8612#undef CASE3_BI_OFFSET_KEY_ERROR_P
8613#undef CASE3_BI_OFFSET_KEY_ERROR_MATCHEE
8614#undef CASE3_BI_OFFSET_KEY_ERROR_KEY
8619 const int line = (int)nd_line(node);
8620 const NODE *line_node = node;
8622 LABEL *prev_start_label = ISEQ_COMPILE_DATA(iseq)->start_label;
8623 LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label;
8624 LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label;
8625 int prev_loopval_popped = ISEQ_COMPILE_DATA(iseq)->loopval_popped;
8630 LABEL *next_label = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(line);
8631 LABEL *redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label = NEW_LABEL(line);
8632 LABEL *break_label = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(line);
8633 LABEL *end_label = NEW_LABEL(line);
8634 LABEL *adjust_label = NEW_LABEL(line);
8636 LABEL *next_catch_label = NEW_LABEL(line);
8637 LABEL *tmp_label = NULL;
8639 ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0;
8640 push_ensure_entry(iseq, &enl, NULL, NULL);
8642 if (RNODE_WHILE(node)->nd_state == 1) {
8643 ADD_INSNL(ret, line_node, jump, next_label);
8646 tmp_label = NEW_LABEL(line);
8647 ADD_INSNL(ret, line_node, jump, tmp_label);
8649 ADD_LABEL(ret, adjust_label);
8650 ADD_INSN(ret, line_node, putnil);
8651 ADD_LABEL(ret, next_catch_label);
8652 ADD_INSN(ret, line_node, pop);
8653 ADD_INSNL(ret, line_node, jump, next_label);
8654 if (tmp_label) ADD_LABEL(ret, tmp_label);
8656 ADD_LABEL(ret, redo_label);
8657 branches = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node),
type == NODE_WHILE ?
"while" :
"until");
8659 const NODE *
const coverage_node = RNODE_WHILE(node)->nd_body ? RNODE_WHILE(node)->nd_body : node;
8660 add_trace_branch_coverage(
8663 nd_code_loc(coverage_node),
8664 nd_node_id(coverage_node),
8669 CHECK(COMPILE_POPPED(ret,
"while body", RNODE_WHILE(node)->nd_body));
8670 ADD_LABEL(ret, next_label);
8672 if (
type == NODE_WHILE) {
8673 CHECK(compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
8674 redo_label, end_label));
8678 CHECK(compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
8679 end_label, redo_label));
8682 ADD_LABEL(ret, end_label);
8683 ADD_ADJUST_RESTORE(ret, adjust_label);
8685 if (UNDEF_P(RNODE_WHILE(node)->nd_state)) {
8687 COMPILE_ERROR(ERROR_ARGS
"unsupported: putundef");
8691 ADD_INSN(ret, line_node, putnil);
8694 ADD_LABEL(ret, break_label);
8697 ADD_INSN(ret, line_node, pop);
8700 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, NULL,
8702 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, NULL,
8704 ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, NULL,
8705 ISEQ_COMPILE_DATA(iseq)->redo_label);
8707 ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label;
8708 ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label;
8709 ISEQ_COMPILE_DATA(iseq)->redo_label = prev_redo_label;
8710 ISEQ_COMPILE_DATA(iseq)->loopval_popped = prev_loopval_popped;
8711 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->prev;
8718 const int line = nd_line(node);
8719 const NODE *line_node = node;
8720 const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(iseq)->current_block;
8721 LABEL *retry_label = NEW_LABEL(line);
8722 LABEL *retry_end_l = NEW_LABEL(line);
8725 ADD_LABEL(ret, retry_label);
8726 if (nd_type_p(node, NODE_FOR)) {
8727 CHECK(COMPILE(ret,
"iter caller (for)", RNODE_FOR(node)->nd_iter));
8729 ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
8730 NEW_CHILD_ISEQ(RNODE_FOR(node)->nd_body, make_name_for_block(iseq),
8731 ISEQ_TYPE_BLOCK, line);
8732 ADD_SEND_WITH_BLOCK(ret, line_node, idEach,
INT2FIX(0), child_iseq);
8735 ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
8736 NEW_CHILD_ISEQ(RNODE_ITER(node)->nd_body, make_name_for_block(iseq),
8737 ISEQ_TYPE_BLOCK, line);
8738 CHECK(COMPILE(ret,
"iter caller", RNODE_ITER(node)->nd_iter));
8752 iobj = IS_INSN(last_elem) ? (
INSN*) last_elem : (
INSN*) get_prev_insn((
INSN*) last_elem);
8753 while (!IS_INSN_ID(iobj, send) && !IS_INSN_ID(iobj, invokesuper) && !IS_INSN_ID(iobj, sendforward) && !IS_INSN_ID(iobj, invokesuperforward)) {
8754 iobj = (
INSN*) get_prev_insn(iobj);
8756 ELEM_INSERT_NEXT(&iobj->link, (
LINK_ELEMENT*) retry_end_l);
8760 if (&iobj->link == LAST_ELEMENT(ret)) {
8766 ADD_INSN(ret, line_node, pop);
8769 ISEQ_COMPILE_DATA(iseq)->current_block = prevblock;
8771 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l);
8781 const NODE *line_node = node;
8782 const NODE *var = RNODE_FOR_MASGN(node)->nd_var;
8783 LABEL *not_single = NEW_LABEL(nd_line(var));
8784 LABEL *not_ary = NEW_LABEL(nd_line(var));
8785 CHECK(COMPILE(ret,
"for var", var));
8786 ADD_INSN(ret, line_node, dup);
8787 ADD_CALL(ret, line_node, idLength,
INT2FIX(0));
8788 ADD_INSN1(ret, line_node, putobject,
INT2FIX(1));
8789 ADD_CALL(ret, line_node, idEq,
INT2FIX(1));
8790 ADD_INSNL(ret, line_node, branchunless, not_single);
8791 ADD_INSN(ret, line_node, dup);
8792 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
8793 ADD_CALL(ret, line_node, idAREF,
INT2FIX(1));
8794 ADD_INSN1(ret, line_node, putobject,
rb_cArray);
8795 ADD_INSN(ret, line_node, swap);
8796 ADD_CALL(ret, line_node, rb_intern(
"try_convert"),
INT2FIX(1));
8797 ADD_INSN(ret, line_node, dup);
8798 ADD_INSNL(ret, line_node, branchunless, not_ary);
8799 ADD_INSN(ret, line_node, swap);
8800 ADD_LABEL(ret, not_ary);
8801 ADD_INSN(ret, line_node, pop);
8802 ADD_LABEL(ret, not_single);
8809 const NODE *line_node = node;
8810 unsigned long throw_flag = 0;
8812 if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
8814 LABEL *splabel = NEW_LABEL(0);
8815 ADD_LABEL(ret, splabel);
8816 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
8817 CHECK(COMPILE_(ret,
"break val (while/until)", RNODE_BREAK(node)->nd_stts,
8818 ISEQ_COMPILE_DATA(iseq)->loopval_popped));
8819 add_ensure_iseq(ret, iseq, 0);
8820 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
8821 ADD_ADJUST_RESTORE(ret, splabel);
8824 ADD_INSN(ret, line_node, putnil);
8831 if (!ISEQ_COMPILE_DATA(ip)) {
8836 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
8837 throw_flag = VM_THROW_NO_ESCAPE_FLAG;
8839 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
8842 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
8843 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with break");
8847 ip = ISEQ_BODY(ip)->parent_iseq;
8852 CHECK(COMPILE(ret,
"break val (block)", RNODE_BREAK(node)->nd_stts));
8853 ADD_INSN1(ret, line_node,
throw,
INT2FIX(throw_flag | TAG_BREAK));
8855 ADD_INSN(ret, line_node, pop);
8859 COMPILE_ERROR(ERROR_ARGS
"Invalid break");
8868 const NODE *line_node = node;
8869 unsigned long throw_flag = 0;
8871 if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
8872 LABEL *splabel = NEW_LABEL(0);
8873 debugs(
"next in while loop\n");
8874 ADD_LABEL(ret, splabel);
8875 CHECK(COMPILE(ret,
"next val/valid syntax?", RNODE_NEXT(node)->nd_stts));
8876 add_ensure_iseq(ret, iseq, 0);
8877 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
8878 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
8879 ADD_ADJUST_RESTORE(ret, splabel);
8881 ADD_INSN(ret, line_node, putnil);
8884 else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) {
8885 LABEL *splabel = NEW_LABEL(0);
8886 debugs(
"next in block\n");
8887 ADD_LABEL(ret, splabel);
8888 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
8889 CHECK(COMPILE(ret,
"next val", RNODE_NEXT(node)->nd_stts));
8890 add_ensure_iseq(ret, iseq, 0);
8891 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
8892 ADD_ADJUST_RESTORE(ret, splabel);
8895 ADD_INSN(ret, line_node, putnil);
8902 if (!ISEQ_COMPILE_DATA(ip)) {
8907 throw_flag = VM_THROW_NO_ESCAPE_FLAG;
8908 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
8912 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
8915 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
8916 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with next");
8920 ip = ISEQ_BODY(ip)->parent_iseq;
8923 CHECK(COMPILE(ret,
"next val", RNODE_NEXT(node)->nd_stts));
8924 ADD_INSN1(ret, line_node,
throw,
INT2FIX(throw_flag | TAG_NEXT));
8927 ADD_INSN(ret, line_node, pop);
8931 COMPILE_ERROR(ERROR_ARGS
"Invalid next");
8941 const NODE *line_node = node;
8943 if (ISEQ_COMPILE_DATA(iseq)->redo_label && can_add_ensure_iseq(iseq)) {
8944 LABEL *splabel = NEW_LABEL(0);
8945 debugs(
"redo in while");
8946 ADD_LABEL(ret, splabel);
8947 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
8948 add_ensure_iseq(ret, iseq, 0);
8949 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
8950 ADD_ADJUST_RESTORE(ret, splabel);
8952 ADD_INSN(ret, line_node, putnil);
8955 else if (ISEQ_BODY(iseq)->
type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) {
8956 LABEL *splabel = NEW_LABEL(0);
8958 debugs(
"redo in block");
8959 ADD_LABEL(ret, splabel);
8960 add_ensure_iseq(ret, iseq, 0);
8961 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
8962 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
8963 ADD_ADJUST_RESTORE(ret, splabel);
8966 ADD_INSN(ret, line_node, putnil);
8973 if (!ISEQ_COMPILE_DATA(ip)) {
8978 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
8981 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
8984 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
8985 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with redo");
8989 ip = ISEQ_BODY(ip)->parent_iseq;
8992 ADD_INSN(ret, line_node, putnil);
8993 ADD_INSN1(ret, line_node,
throw,
INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO));
8996 ADD_INSN(ret, line_node, pop);
9000 COMPILE_ERROR(ERROR_ARGS
"Invalid redo");
9010 const NODE *line_node = node;
9012 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE) {
9013 ADD_INSN(ret, line_node, putnil);
9014 ADD_INSN1(ret, line_node,
throw,
INT2FIX(TAG_RETRY));
9017 ADD_INSN(ret, line_node, pop);
9021 COMPILE_ERROR(ERROR_ARGS
"Invalid retry");
9030 const int line = nd_line(node);
9031 const NODE *line_node = node;
9032 LABEL *lstart = NEW_LABEL(line);
9033 LABEL *lend = NEW_LABEL(line);
9034 LABEL *lcont = NEW_LABEL(line);
9035 const rb_iseq_t *rescue = NEW_CHILD_ISEQ(RNODE_RESCUE(node)->nd_resq,
9037 ISEQ_BODY(iseq)->location.label),
9038 ISEQ_TYPE_RESCUE, line);
9040 lstart->rescued = LABEL_RESCUE_BEG;
9041 lend->rescued = LABEL_RESCUE_END;
9042 ADD_LABEL(ret, lstart);
9044 bool prev_in_rescue = ISEQ_COMPILE_DATA(iseq)->in_rescue;
9045 ISEQ_COMPILE_DATA(iseq)->in_rescue =
true;
9047 CHECK(COMPILE(ret,
"rescue head", RNODE_RESCUE(node)->nd_head));
9049 ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue;
9051 ADD_LABEL(ret, lend);
9052 if (RNODE_RESCUE(node)->nd_else) {
9053 ADD_INSN(ret, line_node, pop);
9054 CHECK(COMPILE(ret,
"rescue else", RNODE_RESCUE(node)->nd_else));
9056 ADD_INSN(ret, line_node, nop);
9057 ADD_LABEL(ret, lcont);
9060 ADD_INSN(ret, line_node, pop);
9064 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont);
9065 ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, NULL, lstart);
9072 const int line = nd_line(node);
9073 const NODE *line_node = node;
9074 const NODE *resq = node;
9076 LABEL *label_miss, *label_hit;
9079 label_miss = NEW_LABEL(line);
9080 label_hit = NEW_LABEL(line);
9082 narg = RNODE_RESBODY(resq)->nd_args;
9084 switch (nd_type(narg)) {
9087 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
9088 CHECK(COMPILE(ret,
"rescue arg", RNODE_LIST(narg)->nd_head));
9089 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
9090 ADD_INSNL(ret, line_node, branchif, label_hit);
9091 narg = RNODE_LIST(narg)->nd_next;
9097 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
9098 CHECK(COMPILE(ret,
"rescue/cond splat", narg));
9099 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY));
9100 ADD_INSNL(ret, line_node, branchif, label_hit);
9103 UNKNOWN_NODE(
"NODE_RESBODY", narg, COMPILE_NG);
9107 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
9109 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
9110 ADD_INSNL(ret, line_node, branchif, label_hit);
9112 ADD_INSNL(ret, line_node, jump, label_miss);
9113 ADD_LABEL(ret, label_hit);
9116 if (RNODE_RESBODY(resq)->nd_exc_var) {
9117 CHECK(COMPILE_POPPED(ret,
"resbody exc_var", RNODE_RESBODY(resq)->nd_exc_var));
9120 if (nd_type(RNODE_RESBODY(resq)->nd_body) == NODE_BEGIN && RNODE_BEGIN(RNODE_RESBODY(resq)->nd_body)->nd_body == NULL && !RNODE_RESBODY(resq)->nd_exc_var) {
9122 ADD_SYNTHETIC_INSN(ret, nd_line(RNODE_RESBODY(resq)->nd_body), -1, putnil);
9125 CHECK(COMPILE(ret,
"resbody body", RNODE_RESBODY(resq)->nd_body));
9128 if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
9129 ADD_INSN(ret, line_node, nop);
9131 ADD_INSN(ret, line_node, leave);
9132 ADD_LABEL(ret, label_miss);
9133 resq = RNODE_RESBODY(resq)->nd_next;
9141 const int line = nd_line(RNODE_ENSURE(node)->nd_ensr);
9142 const NODE *line_node = node;
9144 const rb_iseq_t *ensure = NEW_CHILD_ISEQ(RNODE_ENSURE(node)->nd_ensr,
9146 ISEQ_TYPE_ENSURE, line);
9147 LABEL *lstart = NEW_LABEL(line);
9148 LABEL *lend = NEW_LABEL(line);
9149 LABEL *lcont = NEW_LABEL(line);
9157 CHECK(COMPILE_POPPED(ensr,
"ensure ensr", RNODE_ENSURE(node)->nd_ensr));
9159 last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave);
9164 push_ensure_entry(iseq, &enl, &er, RNODE_ENSURE(node)->nd_ensr);
9166 ADD_LABEL(ret, lstart);
9167 CHECK(COMPILE_(ret,
"ensure head", RNODE_ENSURE(node)->nd_head, (popped | last_leave)));
9168 ADD_LABEL(ret, lend);
9170 if (!popped && last_leave) ADD_INSN(ret, line_node, putnil);
9171 ADD_LABEL(ret, lcont);
9172 if (last_leave) ADD_INSN(ret, line_node, pop);
9174 erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange;
9175 if (lstart->link.next != &lend->link) {
9177 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end,
9179 erange = erange->next;
9183 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev;
9190 const NODE *line_node = node;
9193 enum rb_iseq_type
type = ISEQ_BODY(iseq)->type;
9195 enum rb_iseq_type t =
type;
9196 const NODE *retval = RNODE_RETURN(node)->nd_stts;
9199 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) {
9200 if (!(is = ISEQ_BODY(is)->parent_iseq))
break;
9201 t = ISEQ_BODY(is)->type;
9205 case ISEQ_TYPE_MAIN:
9207 rb_warn(
"argument of top-level return is ignored");
9211 type = ISEQ_TYPE_METHOD;
9218 if (
type == ISEQ_TYPE_METHOD) {
9219 splabel = NEW_LABEL(0);
9220 ADD_LABEL(ret, splabel);
9221 ADD_ADJUST(ret, line_node, 0);
9224 CHECK(COMPILE(ret,
"return nd_stts (return val)", retval));
9226 if (
type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
9227 add_ensure_iseq(ret, iseq, 1);
9229 ADD_INSN(ret, line_node, leave);
9230 ADD_ADJUST_RESTORE(ret, splabel);
9233 ADD_INSN(ret, line_node, putnil);
9237 ADD_INSN1(ret, line_node,
throw,
INT2FIX(TAG_RETURN));
9239 ADD_INSN(ret, line_node, pop);
9250 if (!i)
return false;
9251 if (IS_TRACE(i)) i = i->prev;
9252 if (!IS_INSN(i) || !IS_INSN_ID(i, putnil))
return false;
9254 if (IS_ADJUST(i)) i = i->prev;
9255 if (!IS_INSN(i))
return false;
9256 switch (INSN_OF(i)) {
9263 (ret->last = last->prev)->next = NULL;
9270 CHECK(COMPILE_(ret,
"nd_body", node, popped));
9272 if (!popped && !all_string_result_p(node)) {
9273 const NODE *line_node = node;
9274 const unsigned int flag = VM_CALL_FCALL;
9278 ADD_INSN(ret, line_node, dup);
9279 ADD_INSN1(ret, line_node, objtostring, new_callinfo(iseq, idTo_s, 0, flag, NULL, FALSE));
9280 ADD_INSN(ret, line_node, anytostring);
9288 int idx = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
9290 debugs(
"id: %s idx: %d\n", rb_id2name(
id), idx);
9291 ADD_GETLOCAL(ret, line_node, idx, get_lvar_level(iseq));
9297 LABEL *else_label = NEW_LABEL(nd_line(line_node));
9300 br = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node),
"&.");
9302 ADD_INSN(recv, line_node, dup);
9303 ADD_INSNL(recv, line_node, branchnil, else_label);
9304 add_trace_branch_coverage(iseq, recv, nd_code_loc(node), nd_node_id(node), 0,
"then", br);
9312 if (!else_label)
return;
9313 end_label = NEW_LABEL(nd_line(line_node));
9314 ADD_INSNL(ret, line_node, jump, end_label);
9315 ADD_LABEL(ret, else_label);
9316 add_trace_branch_coverage(iseq, ret, nd_code_loc(node), nd_node_id(node), 1,
"else", branches);
9317 ADD_LABEL(ret, end_label);
9326 if (get_nd_recv(node) &&
9327 (nd_type_p(get_nd_recv(node), NODE_STR) || nd_type_p(get_nd_recv(node), NODE_FILE)) &&
9328 (get_node_call_nd_mid(node) == idFreeze || get_node_call_nd_mid(node) == idUMinus) &&
9329 get_nd_args(node) == NULL &&
9330 ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
9331 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
9332 VALUE str = get_string_value(get_nd_recv(node));
9333 if (get_node_call_nd_mid(node) == idUMinus) {
9334 ADD_INSN2(ret, line_node, opt_str_uminus, str,
9335 new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE));
9338 ADD_INSN2(ret, line_node, opt_str_freeze, str,
9339 new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE));
9343 ADD_INSN(ret, line_node, pop);
9351iseq_has_builtin_function_table(
const rb_iseq_t *iseq)
9353 return ISEQ_COMPILE_DATA(iseq)->builtin_function_table != NULL;
9357iseq_builtin_function_lookup(
const rb_iseq_t *iseq,
const char *name)
9360 const struct rb_builtin_function *table = ISEQ_COMPILE_DATA(iseq)->builtin_function_table;
9361 for (i=0; table[i].index != -1; i++) {
9362 if (strcmp(table[i].name, name) == 0) {
9370iseq_builtin_function_name(
const enum node_type
type,
const NODE *recv,
ID mid)
9372 const char *name = rb_id2name(mid);
9373 static const char prefix[] =
"__builtin_";
9374 const size_t prefix_len =
sizeof(prefix) - 1;
9379 switch (nd_type(recv)) {
9381 if (RNODE_VCALL(recv)->nd_mid == rb_intern(
"__builtin")) {
9386 if (RNODE_CONST(recv)->nd_vid == rb_intern(
"Primitive")) {
9396 if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) {
9397 return &name[prefix_len];
9406delegate_call_p(
const rb_iseq_t *iseq,
unsigned int argc,
const LINK_ANCHOR *args,
unsigned int *pstart_index)
9413 else if (argc <= ISEQ_BODY(iseq)->local_table_size) {
9414 unsigned int start=0;
9419 argc + start <= ISEQ_BODY(iseq)->local_table_size;
9423 for (
unsigned int i=start; i-start<argc; i++) {
9424 if (IS_INSN(elem) &&
9425 INSN_OF(elem) == BIN(getlocal)) {
9426 int local_index =
FIX2INT(OPERAND_AT(elem, 0));
9427 int local_level =
FIX2INT(OPERAND_AT(elem, 1));
9429 if (local_level == 0) {
9430 unsigned int index = ISEQ_BODY(iseq)->local_table_size - (local_index - VM_ENV_DATA_SIZE + 1);
9432 fprintf(stderr,
"lvar:%s (%d), id:%s (%d) local_index:%d, local_size:%d\n",
9433 rb_id2name(ISEQ_BODY(iseq)->local_table[i]), i,
9434 rb_id2name(ISEQ_BODY(iseq)->local_table[index]), index,
9435 local_index, (
int)ISEQ_BODY(iseq)->local_table_size);
9459 *pstart_index = start;
9471 if (rb_streql_lit(
string,
"leaf")) {
9472 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_LEAF;
9474 else if (rb_streql_lit(
string,
"inline_block")) {
9475 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_INLINE_BLOCK;
9477 else if (rb_streql_lit(
string,
"use_block")) {
9478 iseq_set_use_block(iseq);
9480 else if (rb_streql_lit(
string,
"c_trace")) {
9482 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_C_TRACE;
9484 else if (rb_streql_lit(
string,
"without_interrupts")) {
9485 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_WITHOUT_INTERRUPTS;
9487 else if (rb_streql_lit(
string,
"caller_user_box")) {
9488 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_CALLER_USER_BOX;
9490 else if (rb_streql_lit(
string,
"always_inline")) {
9491 ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_ALWAYS_INLINE;
9504 if (!node)
goto no_arg;
9506 if (!nd_type_p(node, NODE_LIST))
goto bad_arg;
9507 const NODE *next = RNODE_LIST(node)->nd_next;
9509 node = RNODE_LIST(node)->nd_head;
9510 if (!node)
goto no_arg;
9511 switch (nd_type(node)) {
9513 symbol = rb_node_sym_string_val(node);
9519 if (!
SYMBOL_P(symbol))
goto non_symbol_arg;
9520 if (compile_builtin_attr_symbol(iseq, symbol) != COMPILE_OK)
goto unknown_arg;
9525 COMPILE_ERROR(ERROR_ARGS
"attr!: no argument");
9528 COMPILE_ERROR(ERROR_ARGS
"non symbol argument to attr!: %s", rb_builtin_class_name(symbol));
9531 COMPILE_ERROR(ERROR_ARGS
"unknown argument to attr!: %" PRIsVALUE, symbol);
9534 UNKNOWN_NODE(
"attr!", node, COMPILE_NG);
9542 if (!node)
goto no_arg;
9543 if (!nd_type_p(node, NODE_LIST))
goto bad_arg;
9544 if (RNODE_LIST(node)->nd_next)
goto too_many_arg;
9545 node = RNODE_LIST(node)->nd_head;
9546 if (!node)
goto no_arg;
9547 switch (nd_type(node)) {
9549 name = rb_node_sym_string_val(node);
9554 if (!
SYMBOL_P(name))
goto non_symbol_arg;
9556 compile_lvar(iseq, ret, line_node,
SYM2ID(name));
9560 COMPILE_ERROR(ERROR_ARGS
"arg!: no argument");
9563 COMPILE_ERROR(ERROR_ARGS
"arg!: too many argument");
9566 COMPILE_ERROR(ERROR_ARGS
"non symbol argument to arg!: %s",
9567 rb_builtin_class_name(name));
9570 UNKNOWN_NODE(
"arg!", node, COMPILE_NG);
9576 const NODE *node = ISEQ_COMPILE_DATA(iseq)->root_node;
9577 if (nd_type(node) == NODE_IF && RNODE_IF(node)->nd_cond == cond_node) {
9578 return RNODE_IF(node)->nd_body;
9581 rb_bug(
"mandatory_node: can't find mandatory node");
9586compile_builtin_mandatory_only_method(
rb_iseq_t *iseq,
const NODE *node,
const NODE *line_node)
9590 .pre_args_num = ISEQ_BODY(iseq)->param.lead_num,
9593 rb_node_init(RNODE(&args_node), NODE_ARGS);
9594 args_node.nd_ainfo = args;
9597 const int skip_local_size = ISEQ_BODY(iseq)->param.size - ISEQ_BODY(iseq)->param.lead_num;
9598 const int table_size = ISEQ_BODY(iseq)->local_table_size - skip_local_size;
9602 tbl->size = table_size;
9607 for (i=0; i<ISEQ_BODY(iseq)->param.lead_num; i++) {
9608 tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i];
9611 for (; i<table_size; i++) {
9612 tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i + skip_local_size];
9616 rb_node_init(RNODE(&scope_node), NODE_SCOPE);
9617 scope_node.nd_tbl = tbl;
9618 scope_node.nd_body = mandatory_node(iseq, node);
9619 scope_node.nd_parent = NULL;
9620 scope_node.nd_args = &args_node;
9622 VALUE ast_value = rb_ruby_ast_new(RNODE(&scope_node));
9625 rb_iseq_new_with_opt(ast_value, rb_iseq_base_label(iseq),
9626 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
9627 nd_line(line_node), NULL, 0,
9628 ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option,
9629 ISEQ_SCRIPT_LINES(iseq));
9630 RB_OBJ_WRITE(iseq, &ISEQ_BODY(iseq)->mandatory_only_iseq, (
VALUE)mandatory_only_iseq);
9640 NODE *args_node = get_nd_args(node);
9642 if (parent_block != NULL) {
9643 COMPILE_ERROR(ERROR_ARGS_AT(line_node)
"should not call builtins here.");
9647# define BUILTIN_INLINE_PREFIX "_bi"
9648 char inline_func[
sizeof(BUILTIN_INLINE_PREFIX) +
DECIMAL_SIZE_OF(
int)];
9649 bool cconst =
false;
9654 if (strcmp(
"cstmt!", builtin_func) == 0 ||
9655 strcmp(
"cexpr!", builtin_func) == 0) {
9658 else if (strcmp(
"cconst!", builtin_func) == 0) {
9661 else if (strcmp(
"cinit!", builtin_func) == 0) {
9665 else if (strcmp(
"attr!", builtin_func) == 0) {
9666 return compile_builtin_attr(iseq, args_node);
9668 else if (strcmp(
"arg!", builtin_func) == 0) {
9669 return compile_builtin_arg(iseq, ret, args_node, line_node, popped);
9671 else if (strcmp(
"mandatory_only?", builtin_func) == 0) {
9673 rb_bug(
"mandatory_only? should be in if condition");
9675 else if (!LIST_INSN_SIZE_ZERO(ret)) {
9676 rb_bug(
"mandatory_only? should be put on top");
9679 ADD_INSN1(ret, line_node, putobject,
Qfalse);
9680 return compile_builtin_mandatory_only_method(iseq, node, line_node);
9682 else if (strcmp(
"local_self!", builtin_func) == 0) {
9687 compile_lvar(iseq, ret, line_node, id_self);
9691 rb_bug(
"can't find builtin function:%s", builtin_func);
9694 COMPILE_ERROR(ERROR_ARGS
"can't find builtin function:%s", builtin_func);
9698 int inline_index = nd_line(node);
9699 snprintf(inline_func,
sizeof(inline_func), BUILTIN_INLINE_PREFIX
"%d", inline_index);
9700 builtin_func = inline_func;
9706 typedef VALUE(*builtin_func0)(
void *,
VALUE);
9707 VALUE const_val = (*(builtin_func0)(uintptr_t)bf->func_ptr)(NULL,
Qnil);
9708 ADD_INSN1(ret, line_node, putobject, const_val);
9714 unsigned int flag = 0;
9716 VALUE argc = setup_args(iseq, args, args_node, &flag, &keywords);
9718 if (
FIX2INT(argc) != bf->argc) {
9719 COMPILE_ERROR(ERROR_ARGS
"argc is not match for builtin function:%s (expect %d but %d)",
9720 builtin_func, bf->argc,
FIX2INT(argc));
9724 unsigned int start_index;
9725 if (delegate_call_p(iseq,
FIX2INT(argc), args, &start_index)) {
9726 ADD_INSN2(ret, line_node, opt_invokebuiltin_delegate, bf,
INT2FIX(start_index));
9730 ADD_INSN1(ret, line_node, invokebuiltin, bf);
9733 if (popped) ADD_INSN(ret, line_node, pop);
9739compile_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)
9747 ID mid = get_node_call_nd_mid(node);
9749 unsigned int flag = 0;
9751 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
9752 LABEL *else_label = NULL;
9755 ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
9761 if (nd_type_p(node, NODE_VCALL)) {
9766 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
9768 if (mid == id_bitblt) {
9769 ADD_INSN(ret, line_node, bitblt);
9772 else if (mid == id_answer) {
9773 ADD_INSN(ret, line_node, answer);
9785 if (nd_type_p(node, NODE_FCALL) &&
9786 (mid == goto_id || mid == label_id)) {
9789 st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
9792 if (!labels_table) {
9793 labels_table = st_init_numtable();
9794 ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
9797 COMPILE_ERROR(ERROR_ARGS
"invalid goto/label format");
9801 if (mid == goto_id) {
9802 ADD_INSNL(ret, line_node, jump, label);
9805 ADD_LABEL(ret, label);
9812 const char *builtin_func;
9813 if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
9814 (builtin_func = iseq_builtin_function_name(
type, get_nd_recv(node), mid)) != NULL) {
9815 return compile_builtin_function_call(iseq, ret, node, line_node, popped, parent_block, args, builtin_func);
9819 if (!assume_receiver) {
9820 if (
type == NODE_CALL ||
type == NODE_OPCALL ||
type == NODE_QCALL) {
9823 if ((mid == idCall || mid == idAREF || mid == idYield || mid == idEqq) &&
9824 nd_type_p(get_nd_recv(node), NODE_LVAR) &&
9825 iseq_block_param_id_p(iseq, RNODE_LVAR(get_nd_recv(node))->nd_vid, &idx, &level)) {
9826 ADD_INSN2(recv, get_nd_recv(node), getblockparamproxy,
INT2FIX(idx + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
9828 else if (private_recv_p(node)) {
9829 ADD_INSN(recv, node, putself);
9830 flag |= VM_CALL_FCALL;
9833 CHECK(COMPILE(recv,
"recv", get_nd_recv(node)));
9836 if (
type == NODE_QCALL) {
9837 else_label = qcall_branch_start(iseq, recv, &branches, node, line_node);
9840 else if (
type == NODE_FCALL ||
type == NODE_VCALL) {
9841 ADD_CALL_RECEIVER(recv, line_node);
9846 if (
type != NODE_VCALL) {
9847 argc = setup_args(iseq, args, get_nd_args(node), &flag, &keywords);
9848 CHECK(!
NIL_P(argc));
9856 bool inline_new = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction &&
9857 mid == rb_intern(
"new") &&
9858 parent_block == NULL &&
9859 !(flag & VM_CALL_ARGS_BLOCKARG);
9862 ADD_INSN(ret, node, putnil);
9863 ADD_INSN(ret, node, swap);
9868 debugp_param(
"call args argc", argc);
9869 debugp_param(
"call method",
ID2SYM(mid));
9871 switch ((
int)
type) {
9873 flag |= VM_CALL_VCALL;
9876 flag |= VM_CALL_FCALL;
9879 if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) {
9880 ADD_INSN(ret, line_node, splatkw);
9883 LABEL *not_basic_new = NEW_LABEL(nd_line(node));
9884 LABEL *not_basic_new_finish = NEW_LABEL(nd_line(node));
9889 if (flag & VM_CALL_FORWARDING) {
9890 ci = (
VALUE)new_callinfo(iseq, mid,
NUM2INT(argc) + 1, flag, keywords, 0);
9893 ci = (
VALUE)new_callinfo(iseq, mid,
NUM2INT(argc), flag, keywords, 0);
9895 ADD_INSN2(ret, node, opt_new, ci, not_basic_new);
9896 LABEL_REF(not_basic_new);
9899 ADD_SEND_R(ret, line_node, rb_intern(
"initialize"), argc, parent_block,
INT2FIX(flag | VM_CALL_FCALL), keywords);
9900 ADD_INSNL(ret, line_node, jump, not_basic_new_finish);
9902 ADD_LABEL(ret, not_basic_new);
9904 ADD_SEND_R(ret, line_node, mid, argc, parent_block,
INT2FIX(flag), keywords);
9905 ADD_INSN(ret, line_node, swap);
9907 ADD_LABEL(ret, not_basic_new_finish);
9908 ADD_INSN(ret, line_node, pop);
9911 ADD_SEND_R(ret, line_node, mid, argc, parent_block,
INT2FIX(flag), keywords);
9914 qcall_branch_end(iseq, ret, else_label, branches, node, line_node);
9916 ADD_INSN(ret, line_node, pop);
9924 const int line = nd_line(node);
9926 unsigned int flag = 0;
9928 ID id = RNODE_OP_ASGN1(node)->nd_mid;
9954 ADD_INSN(ret, node, putnil);
9956 asgnflag = COMPILE_RECV(ret,
"NODE_OP_ASGN1 recv", node, RNODE_OP_ASGN1(node)->nd_recv);
9957 CHECK(asgnflag != -1);
9958 switch (nd_type(RNODE_OP_ASGN1(node)->nd_index)) {
9963 argc = setup_args(iseq, ret, RNODE_OP_ASGN1(node)->nd_index, &flag, NULL);
9964 CHECK(!
NIL_P(argc));
9966 int dup_argn =
FIX2INT(argc) + 1;
9967 ADD_INSN1(ret, node, dupn,
INT2FIX(dup_argn));
9969 ADD_SEND_R(ret, node, idAREF, argc, NULL,
INT2FIX(flag & ~VM_CALL_ARGS_SPLAT_MUT), NULL);
9971 if (
id == idOROP ||
id == idANDOP) {
9980 LABEL *label = NEW_LABEL(line);
9981 LABEL *lfin = NEW_LABEL(line);
9983 ADD_INSN(ret, node, dup);
9985 ADD_INSNL(ret, node, branchif, label);
9988 ADD_INSNL(ret, node, branchunless, label);
9990 ADD_INSN(ret, node, pop);
9992 CHECK(COMPILE(ret,
"NODE_OP_ASGN1 nd_rvalue: ", RNODE_OP_ASGN1(node)->nd_rvalue));
9994 ADD_INSN1(ret, node, setn,
INT2FIX(dup_argn+1));
9996 if (flag & VM_CALL_ARGS_SPLAT) {
9997 if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) {
9998 ADD_INSN(ret, node, swap);
9999 ADD_INSN1(ret, node, splatarray,
Qtrue);
10000 ADD_INSN(ret, node, swap);
10001 flag |= VM_CALL_ARGS_SPLAT_MUT;
10003 ADD_INSN1(ret, node, pushtoarray,
INT2FIX(1));
10004 ADD_SEND_R(ret, node, idASET, argc, NULL,
INT2FIX(flag), NULL);
10007 ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL,
INT2FIX(flag), NULL);
10009 ADD_INSN(ret, node, pop);
10010 ADD_INSNL(ret, node, jump, lfin);
10011 ADD_LABEL(ret, label);
10013 ADD_INSN1(ret, node, setn,
INT2FIX(dup_argn+1));
10015 ADD_INSN1(ret, node, adjuststack,
INT2FIX(dup_argn+1));
10016 ADD_LABEL(ret, lfin);
10019 CHECK(COMPILE(ret,
"NODE_OP_ASGN1 nd_rvalue: ", RNODE_OP_ASGN1(node)->nd_rvalue));
10020 ADD_SEND(ret, node,
id,
INT2FIX(1));
10022 ADD_INSN1(ret, node, setn,
INT2FIX(dup_argn+1));
10024 if (flag & VM_CALL_ARGS_SPLAT) {
10025 if (flag & VM_CALL_KW_SPLAT) {
10026 ADD_INSN1(ret, node, topn,
INT2FIX(2));
10027 if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) {
10028 ADD_INSN1(ret, node, splatarray,
Qtrue);
10029 flag |= VM_CALL_ARGS_SPLAT_MUT;
10031 ADD_INSN(ret, node, swap);
10032 ADD_INSN1(ret, node, pushtoarray,
INT2FIX(1));
10033 ADD_INSN1(ret, node, setn,
INT2FIX(2));
10034 ADD_INSN(ret, node, pop);
10037 if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) {
10038 ADD_INSN(ret, node, swap);
10039 ADD_INSN1(ret, node, splatarray,
Qtrue);
10040 ADD_INSN(ret, node, swap);
10041 flag |= VM_CALL_ARGS_SPLAT_MUT;
10043 ADD_INSN1(ret, node, pushtoarray,
INT2FIX(1));
10045 ADD_SEND_R(ret, node, idASET, argc, NULL,
INT2FIX(flag), NULL);
10048 ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL,
INT2FIX(flag), NULL);
10050 ADD_INSN(ret, node, pop);
10058 const int line = nd_line(node);
10059 ID atype = RNODE_OP_ASGN2(node)->nd_mid;
10060 ID vid = RNODE_OP_ASGN2(node)->nd_vid, aid = rb_id_attrset(vid);
10062 LABEL *lfin = NEW_LABEL(line);
10063 LABEL *lcfin = NEW_LABEL(line);
10118 asgnflag = COMPILE_RECV(ret,
"NODE_OP_ASGN2#recv", node, RNODE_OP_ASGN2(node)->nd_recv);
10119 CHECK(asgnflag != -1);
10120 if (RNODE_OP_ASGN2(node)->nd_aid) {
10121 lskip = NEW_LABEL(line);
10122 ADD_INSN(ret, node, dup);
10123 ADD_INSNL(ret, node, branchnil, lskip);
10125 ADD_INSN(ret, node, dup);
10126 ADD_SEND_WITH_FLAG(ret, node, vid,
INT2FIX(0),
INT2FIX(asgnflag));
10128 if (atype == idOROP || atype == idANDOP) {
10130 ADD_INSN(ret, node, dup);
10132 if (atype == idOROP) {
10133 ADD_INSNL(ret, node, branchif, lcfin);
10136 ADD_INSNL(ret, node, branchunless, lcfin);
10139 ADD_INSN(ret, node, pop);
10141 CHECK(COMPILE(ret,
"NODE_OP_ASGN2 val", RNODE_OP_ASGN2(node)->nd_value));
10143 ADD_INSN(ret, node, swap);
10144 ADD_INSN1(ret, node, topn,
INT2FIX(1));
10146 ADD_SEND_WITH_FLAG(ret, node, aid,
INT2FIX(1),
INT2FIX(asgnflag));
10147 ADD_INSNL(ret, node, jump, lfin);
10149 ADD_LABEL(ret, lcfin);
10151 ADD_INSN(ret, node, swap);
10154 ADD_LABEL(ret, lfin);
10157 CHECK(COMPILE(ret,
"NODE_OP_ASGN2 val", RNODE_OP_ASGN2(node)->nd_value));
10158 ADD_SEND(ret, node, atype,
INT2FIX(1));
10160 ADD_INSN(ret, node, swap);
10161 ADD_INSN1(ret, node, topn,
INT2FIX(1));
10163 ADD_SEND_WITH_FLAG(ret, node, aid,
INT2FIX(1),
INT2FIX(asgnflag));
10165 if (lskip && popped) {
10166 ADD_LABEL(ret, lskip);
10168 ADD_INSN(ret, node, pop);
10169 if (lskip && !popped) {
10170 ADD_LABEL(ret, lskip);
10175static int compile_shareable_constant_value(
rb_iseq_t *iseq,
LINK_ANCHOR *ret,
enum rb_parser_shareability shareable,
const NODE *lhs,
const NODE *value);
10180 const int line = nd_line(node);
10182 LABEL *lassign = 0;
10185 switch (nd_type(RNODE_OP_CDECL(node)->nd_head)) {
10187 ADD_INSN1(ret, node, putobject,
rb_cObject);
10190 CHECK(COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", RNODE_COLON2(RNODE_OP_CDECL(node)->nd_head)->nd_head));
10193 COMPILE_ERROR(ERROR_ARGS
"%s: invalid node in NODE_OP_CDECL",
10194 ruby_node_name(nd_type(RNODE_OP_CDECL(node)->nd_head)));
10197 mid = get_node_colon_nd_mid(RNODE_OP_CDECL(node)->nd_head);
10199 if (RNODE_OP_CDECL(node)->nd_aid == idOROP) {
10200 lassign = NEW_LABEL(line);
10201 ADD_INSN(ret, node, dup);
10202 ADD_INSN3(ret, node, defined,
INT2FIX(DEFINED_CONST_FROM),
10204 ADD_INSNL(ret, node, branchunless, lassign);
10206 ADD_INSN(ret, node, dup);
10207 ADD_INSN1(ret, node, putobject,
Qtrue);
10208 ADD_INSN1(ret, node, getconstant,
ID2SYM(mid));
10210 if (RNODE_OP_CDECL(node)->nd_aid == idOROP || RNODE_OP_CDECL(node)->nd_aid == idANDOP) {
10211 lfin = NEW_LABEL(line);
10212 if (!popped) ADD_INSN(ret, node, dup);
10213 if (RNODE_OP_CDECL(node)->nd_aid == idOROP)
10214 ADD_INSNL(ret, node, branchif, lfin);
10216 ADD_INSNL(ret, node, branchunless, lfin);
10218 if (!popped) ADD_INSN(ret, node, pop);
10219 if (lassign) ADD_LABEL(ret, lassign);
10220 CHECK(compile_shareable_constant_value(iseq, ret, RNODE_OP_CDECL(node)->shareability, RNODE_OP_CDECL(node)->nd_head, RNODE_OP_CDECL(node)->nd_value));
10223 ADD_INSN1(ret, node, topn,
INT2FIX(1));
10225 ADD_INSN1(ret, node, dupn,
INT2FIX(2));
10226 ADD_INSN(ret, node, swap);
10228 ADD_INSN1(ret, node, setconstant,
ID2SYM(mid));
10229 ADD_LABEL(ret, lfin);
10230 if (!popped) ADD_INSN(ret, node, swap);
10231 ADD_INSN(ret, node, pop);
10234 CHECK(compile_shareable_constant_value(iseq, ret, RNODE_OP_CDECL(node)->shareability, RNODE_OP_CDECL(node)->nd_head, RNODE_OP_CDECL(node)->nd_value));
10236 ADD_CALL(ret, node, RNODE_OP_CDECL(node)->nd_aid,
INT2FIX(1));
10238 ADD_INSN(ret, node, swap);
10240 ADD_INSN1(ret, node, topn,
INT2FIX(1));
10241 ADD_INSN(ret, node, swap);
10243 ADD_INSN1(ret, node, setconstant,
ID2SYM(mid));
10251 const int line = nd_line(node);
10252 LABEL *lfin = NEW_LABEL(line);
10255 if (
type == NODE_OP_ASGN_OR && !nd_type_p(RNODE_OP_ASGN_OR(node)->nd_head, NODE_IVAR)) {
10259 defined_expr(iseq, ret, RNODE_OP_ASGN_OR(node)->nd_head, lfinish,
Qfalse,
false);
10260 lassign = lfinish[1];
10262 lassign = NEW_LABEL(line);
10264 ADD_INSNL(ret, node, branchunless, lassign);
10267 lassign = NEW_LABEL(line);
10270 CHECK(COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", RNODE_OP_ASGN_OR(node)->nd_head));
10273 ADD_INSN(ret, node, dup);
10276 if (
type == NODE_OP_ASGN_AND) {
10277 ADD_INSNL(ret, node, branchunless, lfin);
10280 ADD_INSNL(ret, node, branchif, lfin);
10284 ADD_INSN(ret, node, pop);
10287 ADD_LABEL(ret, lassign);
10288 CHECK(COMPILE_(ret,
"NODE_OP_ASGN_AND/OR#nd_value", RNODE_OP_ASGN_OR(node)->nd_value, popped));
10289 ADD_LABEL(ret, lfin);
10299 unsigned int flag = 0;
10301 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
10305 ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
10307 if (
type == NODE_SUPER) {
10308 VALUE vargc = setup_args(iseq, args, RNODE_SUPER(node)->nd_args, &flag, &keywords);
10309 CHECK(!
NIL_P(vargc));
10311 if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) {
10312 ADD_INSN(args, node, splatkw);
10315 if (flag & VM_CALL_ARGS_BLOCKARG) {
10322 const rb_iseq_t *liseq = body->local_iseq;
10324 const struct rb_iseq_param_keyword *
const local_kwd = local_body->param.keyword;
10325 int lvar_level = get_lvar_level(iseq);
10327 argc = local_body->param.lead_num;
10330 for (i = 0; i < local_body->param.lead_num; i++) {
10331 int idx = local_body->local_table_size - i;
10332 ADD_GETLOCAL(args, node, idx, lvar_level);
10336 if (local_body->param.flags.forwardable) {
10337 flag |= VM_CALL_FORWARDING;
10338 int idx = local_body->local_table_size - get_local_var_idx(liseq, idDot3);
10339 ADD_GETLOCAL(args, node, idx, lvar_level);
10342 if (local_body->param.flags.has_opt) {
10345 for (j = 0; j < local_body->param.opt_num; j++) {
10346 int idx = local_body->local_table_size - (i + j);
10347 ADD_GETLOCAL(args, node, idx, lvar_level);
10352 if (local_body->param.flags.has_rest) {
10354 int idx = local_body->local_table_size - local_body->param.rest_start;
10355 ADD_GETLOCAL(args, node, idx, lvar_level);
10356 ADD_INSN1(args, node, splatarray, RBOOL(local_body->param.flags.has_post));
10358 argc = local_body->param.rest_start + 1;
10359 flag |= VM_CALL_ARGS_SPLAT;
10361 if (local_body->param.flags.has_post) {
10363 int post_len = local_body->param.post_num;
10364 int post_start = local_body->param.post_start;
10366 if (local_body->param.flags.has_rest) {
10368 for (j=0; j<post_len; j++) {
10369 int idx = local_body->local_table_size - (post_start + j);
10370 ADD_GETLOCAL(args, node, idx, lvar_level);
10372 ADD_INSN1(args, node, pushtoarray,
INT2FIX(j));
10373 flag |= VM_CALL_ARGS_SPLAT_MUT;
10378 for (j=0; j<post_len; j++) {
10379 int idx = local_body->local_table_size - (post_start + j);
10380 ADD_GETLOCAL(args, node, idx, lvar_level);
10382 argc = post_len + post_start;
10386 if (local_body->param.flags.has_kw) {
10387 int local_size = local_body->local_table_size;
10390 ADD_INSN1(args, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10392 if (local_body->param.flags.has_kwrest) {
10393 int idx = local_body->local_table_size - local_kwd->rest_start;
10394 ADD_GETLOCAL(args, node, idx, lvar_level);
10396 ADD_SEND (args, node, rb_intern(
"dup"),
INT2FIX(0));
10399 ADD_INSN1(args, node, newhash,
INT2FIX(0));
10401 for (i = 0; i < local_kwd->num; ++i) {
10402 ID id = local_kwd->table[i];
10403 int idx = local_size - get_local_var_idx(liseq,
id);
10404 ADD_INSN1(args, node, putobject,
ID2SYM(
id));
10405 ADD_GETLOCAL(args, node, idx, lvar_level);
10407 ADD_SEND(args, node, id_core_hash_merge_bang_ptr,
INT2FIX(i * 2 + 1));
10408 flag |= VM_CALL_KW_SPLAT| VM_CALL_KW_SPLAT_MUT;
10410 else if (local_body->param.flags.has_kwrest) {
10411 int idx = local_body->local_table_size - local_kwd->rest_start;
10412 ADD_GETLOCAL(args, node, idx, lvar_level);
10414 flag |= VM_CALL_KW_SPLAT;
10418 if (use_block && parent_block == NULL) {
10419 iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
10422 flag |= VM_CALL_SUPER | VM_CALL_FCALL;
10423 if (
type == NODE_ZSUPER) flag |= VM_CALL_ZSUPER;
10424 ADD_INSN(ret, node, putself);
10425 ADD_SEQ(ret, args);
10427 const struct rb_callinfo * ci = new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL);
10429 if (vm_ci_flag(ci) & VM_CALL_FORWARDING) {
10430 ADD_INSN2(ret, node, invokesuperforward, ci, parent_block);
10433 ADD_INSN2(ret, node, invokesuper, ci, parent_block);
10437 ADD_INSN(ret, node, pop);
10447 unsigned int flag = 0;
10452 switch (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->
type) {
10453 case ISEQ_TYPE_TOP:
10454 case ISEQ_TYPE_MAIN:
10455 case ISEQ_TYPE_CLASS:
10456 COMPILE_ERROR(ERROR_ARGS
"Invalid yield");
10461 if (RNODE_YIELD(node)->nd_head) {
10462 argc = setup_args(iseq, args, RNODE_YIELD(node)->nd_head, &flag, &keywords);
10463 CHECK(!
NIL_P(argc));
10469 ADD_SEQ(ret, args);
10470 ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0,
FIX2INT(argc), flag, keywords, FALSE));
10471 iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
10474 ADD_INSN(ret, node, pop);
10479 for (; tmp_iseq != ISEQ_BODY(iseq)->local_iseq; level++ ) {
10480 tmp_iseq = ISEQ_BODY(tmp_iseq)->parent_iseq;
10482 if (level > 0) access_outer_variables(iseq, level, rb_intern(
"yield"),
true);
10495 switch ((
int)
type) {
10498 VALUE re = rb_node_regx_string_val(node);
10500 ADD_INSN1(recv, node, putobject, re);
10501 ADD_INSN2(val, node, getspecial,
INT2FIX(0),
10506 CHECK(COMPILE(recv,
"receiver", RNODE_MATCH2(node)->nd_recv));
10507 CHECK(COMPILE(val,
"value", RNODE_MATCH2(node)->nd_value));
10510 CHECK(COMPILE(recv,
"receiver", RNODE_MATCH3(node)->nd_value));
10511 CHECK(COMPILE(val,
"value", RNODE_MATCH3(node)->nd_recv));
10515 ADD_SEQ(ret, recv);
10517 ADD_SEND(ret, node, idEqTilde,
INT2FIX(1));
10519 if (nd_type_p(node, NODE_MATCH2) && RNODE_MATCH2(node)->nd_args) {
10520 compile_named_capture_assign(iseq, ret, RNODE_MATCH2(node)->nd_args);
10524 ADD_INSN(ret, node, pop);
10535 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache &&
10536 (segments = collect_const_segments(iseq, node))) {
10537 ISEQ_BODY(iseq)->ic_size++;
10538 ADD_INSN1(ret, node, opt_getconstant_path, segments);
10548 CHECK(compile_const_prefix(iseq, node, pref, body));
10549 if (LIST_INSN_SIZE_ZERO(pref)) {
10550 ADD_INSN(ret, node, putnil);
10551 ADD_SEQ(ret, body);
10554 ADD_SEQ(ret, pref);
10555 ADD_SEQ(ret, body);
10561 ADD_CALL_RECEIVER(ret, node);
10562 CHECK(COMPILE(ret,
"colon2#nd_head", RNODE_COLON2(node)->nd_head));
10563 ADD_CALL(ret, node, RNODE_COLON2(node)->nd_mid,
INT2FIX(1));
10566 ADD_INSN(ret, node, pop);
10574 debugi(
"colon3#nd_mid", RNODE_COLON3(node)->nd_mid);
10577 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
10578 ISEQ_BODY(iseq)->ic_size++;
10579 VALUE segments = rb_ary_new_from_args(2,
ID2SYM(idNULL),
ID2SYM(RNODE_COLON3(node)->nd_mid));
10581 ADD_INSN1(ret, node, opt_getconstant_path, segments);
10585 ADD_INSN1(ret, node, putobject,
rb_cObject);
10586 ADD_INSN1(ret, node, putobject,
Qtrue);
10587 ADD_INSN1(ret, node, getconstant,
ID2SYM(RNODE_COLON3(node)->nd_mid));
10591 ADD_INSN(ret, node, pop);
10600 const NODE *b = RNODE_DOT2(node)->nd_beg;
10601 const NODE *e = RNODE_DOT2(node)->nd_end;
10603 if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
10605 VALUE bv = optimized_range_item(b);
10606 VALUE ev = optimized_range_item(e);
10609 ADD_INSN1(ret, node, putobject, val);
10614 CHECK(COMPILE_(ret,
"min", b, popped));
10615 CHECK(COMPILE_(ret,
"max", e, popped));
10617 ADD_INSN1(ret, node, newrange, flag);
10627 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE) {
10628 ADD_GETLOCAL(ret, node, LVAR_ERRINFO, 0);
10634 if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_RESCUE) {
10637 ip = ISEQ_BODY(ip)->parent_iseq;
10641 ADD_GETLOCAL(ret, node, LVAR_ERRINFO, level);
10644 ADD_INSN(ret, node, putnil);
10655 LABEL *end_label = NEW_LABEL(nd_line(node));
10656 const NODE *default_value = get_nd_value(RNODE_KW_ARG(node)->nd_body);
10658 if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) {
10660 COMPILE_ERROR(ERROR_ARGS
"unreachable");
10663 else if (nd_type_p(default_value, NODE_SYM) ||
10664 nd_type_p(default_value, NODE_REGX) ||
10665 nd_type_p(default_value, NODE_LINE) ||
10666 nd_type_p(default_value, NODE_INTEGER) ||
10667 nd_type_p(default_value, NODE_FLOAT) ||
10668 nd_type_p(default_value, NODE_RATIONAL) ||
10669 nd_type_p(default_value, NODE_IMAGINARY) ||
10670 nd_type_p(default_value, NODE_NIL) ||
10671 nd_type_p(default_value, NODE_TRUE) ||
10672 nd_type_p(default_value, NODE_FALSE)) {
10673 COMPILE_ERROR(ERROR_ARGS
"unreachable");
10681 int kw_bits_idx = body->local_table_size - body->param.keyword->bits_start;
10682 int keyword_idx = body->param.keyword->num;
10684 ADD_INSN2(ret, node, checkkeyword,
INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1),
INT2FIX(keyword_idx));
10685 ADD_INSNL(ret, node, branchif, end_label);
10686 CHECK(COMPILE_POPPED(ret,
"keyword default argument", RNODE_KW_ARG(node)->nd_body));
10687 ADD_LABEL(ret, end_label);
10697 unsigned int flag = 0;
10698 ID mid = RNODE_ATTRASGN(node)->nd_mid;
10700 LABEL *else_label = NULL;
10705 argc = setup_args(iseq, args, RNODE_ATTRASGN(node)->nd_args, &flag, NULL);
10706 CHECK(!
NIL_P(argc));
10708 int asgnflag = COMPILE_RECV(recv,
"recv", node, RNODE_ATTRASGN(node)->nd_recv);
10709 CHECK(asgnflag != -1);
10710 flag |= (
unsigned int)asgnflag;
10712 debugp_param(
"argc", argc);
10713 debugp_param(
"nd_mid",
ID2SYM(mid));
10717 mid = rb_id_attrset(mid);
10718 else_label = qcall_branch_start(iseq, recv, &branches, node, node);
10721 ADD_INSN(ret, node, putnil);
10722 ADD_SEQ(ret, recv);
10723 ADD_SEQ(ret, args);
10725 if (flag & VM_CALL_ARGS_SPLAT) {
10726 ADD_INSN(ret, node, dup);
10727 ADD_INSN1(ret, node, putobject,
INT2FIX(-1));
10728 ADD_SEND_WITH_FLAG(ret, node, idAREF,
INT2FIX(1),
INT2FIX(asgnflag));
10729 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2));
10730 ADD_INSN (ret, node, pop);
10733 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 1));
10737 ADD_SEQ(ret, recv);
10738 ADD_SEQ(ret, args);
10740 ADD_SEND_WITH_FLAG(ret, node, mid, argc,
INT2FIX(flag));
10741 qcall_branch_end(iseq, ret, else_label, branches, node, node);
10742 ADD_INSN(ret, node, pop);
10749 ADD_INSN1(ret, value, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10757 ADD_SEND_WITH_FLAG(ret, value, rb_intern(
"make_shareable_copy"),
INT2FIX(1),
INT2FIX(VM_CALL_ARGS_SIMPLE));
10764 ADD_SEND_WITH_FLAG(ret, value, rb_intern(
"make_shareable"),
INT2FIX(1),
INT2FIX(VM_CALL_ARGS_SIMPLE));
10771node_const_decl_val(
const NODE *node)
10774 switch (nd_type(node)) {
10776 if (RNODE_CDECL(node)->nd_vid) {
10777 path = rb_id2str(RNODE_CDECL(node)->nd_vid);
10781 node = RNODE_CDECL(node)->nd_else;
10789 rb_str_append(path, rb_id2str(RNODE_COLON3(node)->nd_mid));
10792 rb_bug(
"unexpected node: %s", ruby_node_name(nd_type(node)));
10798 for (; node && nd_type_p(node, NODE_COLON2); node = RNODE_COLON2(node)->nd_head) {
10799 rb_ary_push(path, rb_id2str(RNODE_COLON2(node)->nd_mid));
10801 if (node && nd_type_p(node, NODE_CONST)) {
10803 rb_ary_push(path, rb_id2str(RNODE_CONST(node)->nd_vid));
10805 else if (node && nd_type_p(node, NODE_COLON3)) {
10807 rb_ary_push(path, rb_id2str(RNODE_COLON3(node)->nd_mid));
10817 path = rb_fstring(path);
10822const_decl_path(
NODE *dest)
10825 if (!nd_type_p(dest, NODE_CALL)) {
10826 path = node_const_decl_val(dest);
10837 VALUE path = const_decl_path(dest);
10838 ADD_INSN1(ret, value, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10839 CHECK(COMPILE(ret,
"compile_ensure_shareable_node", value));
10840 ADD_INSN1(ret, value, putobject, path);
10842 ADD_SEND_WITH_FLAG(ret, value, rb_intern(
"ensure_shareable"),
INT2FIX(2),
INT2FIX(VM_CALL_ARGS_SIMPLE));
10847#ifndef SHAREABLE_BARE_EXPRESSION
10848#define SHAREABLE_BARE_EXPRESSION 1
10852compile_shareable_literal_constant(
rb_iseq_t *iseq,
LINK_ANCHOR *ret,
enum rb_parser_shareability shareable,
NODE *dest,
const NODE *node,
size_t level,
VALUE *value_p,
int *shareable_literal_p)
10854# define compile_shareable_literal_constant_next(node, anchor, value_p, shareable_literal_p) \
10855 compile_shareable_literal_constant(iseq, anchor, shareable, dest, node, level+1, value_p, shareable_literal_p)
10857 DECL_ANCHOR(anchor);
10859 enum node_type
type = node ? nd_type(node) : NODE_NIL;
10871 *value_p = rb_node_sym_string_val(node);
10874 *value_p = rb_node_regx_string_val(node);
10877 *value_p = rb_node_line_lineno_val(node);
10880 *value_p = rb_node_integer_literal_val(node);
10883 *value_p = rb_node_float_literal_val(node);
10885 case NODE_RATIONAL:
10886 *value_p = rb_node_rational_literal_val(node);
10888 case NODE_IMAGINARY:
10889 *value_p = rb_node_imaginary_literal_val(node);
10891 case NODE_ENCODING:
10892 *value_p = rb_node_encoding_val(node);
10895 CHECK(COMPILE(ret,
"shareable_literal_constant", node));
10896 *shareable_literal_p = 1;
10900 CHECK(COMPILE(ret,
"shareable_literal_constant", node));
10901 if (shareable == rb_parser_shareable_literal) {
10907 ADD_SEND_WITH_FLAG(ret, node, idUMinus,
INT2FIX(0),
INT2FIX(VM_CALL_ARGS_SIMPLE));
10910 *shareable_literal_p = 1;
10914 VALUE lit = rb_node_str_string_val(node);
10915 ADD_INSN1(ret, node, putobject, lit);
10918 *shareable_literal_p = 1;
10924 VALUE lit = rb_node_file_path_val(node);
10925 ADD_INSN1(ret, node, putobject, lit);
10928 *shareable_literal_p = 1;
10936 ADD_INSN1(ret, node, putobject, lit);
10939 *shareable_literal_p = 1;
10945 INIT_ANCHOR(anchor);
10947 for (
NODE *n = (
NODE *)node; n; n = RNODE_LIST(n)->nd_next) {
10949 int shareable_literal_p2;
10950 NODE *elt = RNODE_LIST(n)->nd_head;
10952 CHECK(compile_shareable_literal_constant_next(elt, anchor, &val, &shareable_literal_p2));
10953 if (shareable_literal_p2) {
10956 else if (
RTEST(lit)) {
10962 if (!UNDEF_P(val)) {
10974 if (!RNODE_HASH(node)->nd_brace) {
10976 *shareable_literal_p = 0;
10979 for (
NODE *n = RNODE_HASH(node)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) {
10980 if (!RNODE_LIST(n)->nd_head) {
10982 goto compile_shareable;
10986 INIT_ANCHOR(anchor);
10987 lit = rb_hash_new();
10988 for (
NODE *n = RNODE_HASH(node)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) {
10990 VALUE value_val = 0;
10991 int shareable_literal_p2;
10992 NODE *key = RNODE_LIST(n)->nd_head;
10993 NODE *val = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head;
10994 CHECK(compile_shareable_literal_constant_next(key, anchor, &key_val, &shareable_literal_p2));
10995 if (shareable_literal_p2) {
10998 else if (
RTEST(lit)) {
10999 rb_hash_clear(lit);
11002 CHECK(compile_shareable_literal_constant_next(val, anchor, &value_val, &shareable_literal_p2));
11003 if (shareable_literal_p2) {
11006 else if (
RTEST(lit)) {
11007 rb_hash_clear(lit);
11011 if (!UNDEF_P(key_val) && !UNDEF_P(value_val)) {
11012 rb_hash_aset(lit, key_val, value_val);
11015 rb_hash_clear(lit);
11026 if (shareable == rb_parser_shareable_literal &&
11027 (SHAREABLE_BARE_EXPRESSION || level > 0)) {
11028 CHECK(compile_ensure_shareable_node(iseq, ret, dest, node));
11030 *shareable_literal_p = 1;
11033 CHECK(COMPILE(ret,
"shareable_literal_constant", node));
11035 *shareable_literal_p = 0;
11041 if (nd_type(node) == NODE_LIST) {
11042 ADD_INSN1(anchor, node, newarray,
INT2FIX(RNODE_LIST(node)->as.nd_alen));
11044 else if (nd_type(node) == NODE_HASH) {
11045 long len = RNODE_LIST(RNODE_HASH(node)->nd_head)->as.nd_alen;
11051 *shareable_literal_p = 0;
11052 ADD_SEQ(ret, anchor);
11058 if (nd_type(node) == NODE_LIST) {
11059 ADD_INSN1(anchor, node, newarray,
INT2FIX(RNODE_LIST(node)->as.nd_alen));
11061 else if (nd_type(node) == NODE_HASH) {
11062 long len = RNODE_LIST(RNODE_HASH(node)->nd_head)->as.nd_alen;
11067 CHECK(compile_make_shareable_node(iseq, ret, anchor, node,
false));
11069 *shareable_literal_p = 1;
11073 ADD_INSN1(ret, node, putobject, val);
11076 *shareable_literal_p = 1;
11083compile_shareable_constant_value(
rb_iseq_t *iseq,
LINK_ANCHOR *ret,
enum rb_parser_shareability shareable,
const NODE *lhs,
const NODE *value)
11087 DECL_ANCHOR(anchor);
11088 INIT_ANCHOR(anchor);
11090 switch (shareable) {
11091 case rb_parser_shareable_none:
11092 CHECK(COMPILE(ret,
"compile_shareable_constant_value", value));
11095 case rb_parser_shareable_literal:
11096 CHECK(compile_shareable_literal_constant(iseq, anchor, shareable, (
NODE *)lhs, value, 0, &val, &literal_p));
11097 ADD_SEQ(ret, anchor);
11100 case rb_parser_shareable_copy:
11101 case rb_parser_shareable_everything:
11102 CHECK(compile_shareable_literal_constant(iseq, anchor, shareable, (
NODE *)lhs, value, 0, &val, &literal_p));
11104 CHECK(compile_make_shareable_node(iseq, ret, anchor, value, shareable == rb_parser_shareable_copy));
11107 ADD_SEQ(ret, anchor);
11111 rb_bug(
"unexpected rb_parser_shareability: %d", shareable);
11128 int lineno = ISEQ_COMPILE_DATA(iseq)->last_line;
11129 if (lineno == 0) lineno =
FIX2INT(rb_iseq_first_lineno(iseq));
11130 debugs(
"node: NODE_NIL(implicit)\n");
11131 ADD_SYNTHETIC_INSN(ret, lineno, -1, putnil);
11135 return iseq_compile_each0(iseq, ret, node, popped);
11141 const int line = (int)nd_line(node);
11142 const enum node_type
type = nd_type(node);
11145 if (ISEQ_COMPILE_DATA(iseq)->last_line == line) {
11149 if (nd_fl_newline(node)) {
11151 ISEQ_COMPILE_DATA(iseq)->last_line = line;
11152 if (line > 0 && ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
11153 event |= RUBY_EVENT_COVERAGE_LINE;
11155 ADD_TRACE(ret, event);
11159 debug_node_start(node);
11160#undef BEFORE_RETURN
11161#define BEFORE_RETURN debug_node_end()
11165 CHECK(compile_block(iseq, ret, node, popped));
11169 CHECK(compile_if(iseq, ret, node, popped,
type));
11172 CHECK(compile_case(iseq, ret, node, popped));
11175 CHECK(compile_case2(iseq, ret, node, popped));
11178 CHECK(compile_case3(iseq, ret, node, popped));
11182 CHECK(compile_loop(iseq, ret, node, popped,
type));
11186 CHECK(compile_iter(iseq, ret, node, popped));
11188 case NODE_FOR_MASGN:
11189 CHECK(compile_for_masgn(iseq, ret, node, popped));
11192 CHECK(compile_break(iseq, ret, node, popped));
11195 CHECK(compile_next(iseq, ret, node, popped));
11198 CHECK(compile_redo(iseq, ret, node, popped));
11201 CHECK(compile_retry(iseq, ret, node, popped));
11204 CHECK(COMPILE_(ret,
"NODE_BEGIN", RNODE_BEGIN(node)->nd_body, popped));
11208 CHECK(compile_rescue(iseq, ret, node, popped));
11211 CHECK(compile_resbody(iseq, ret, node, popped));
11214 CHECK(compile_ensure(iseq, ret, node, popped));
11219 LABEL *end_label = NEW_LABEL(line);
11220 const NODE *cond = node;
11227 CHECK(COMPILE(ret,
"nd_1st", RNODE_OR(cond)->nd_1st));
11229 ADD_INSN(ret, cond, dup);
11231 if (
type == NODE_AND) {
11232 ADD_INSNL(ret, cond, branchunless, end_label);
11235 ADD_INSNL(ret, cond, branchif, end_label);
11238 ADD_INSN(ret, cond, pop);
11240 const NODE *rest = RNODE_OR(cond)->nd_2nd;
11241 if (nd_type_p(rest,
type)) {
11245 CHECK(COMPILE_(ret,
"nd_2nd", rest, popped));
11248 ADD_LABEL(ret, end_label);
11253 compile_massign(iseq, ret, node, popped);
11258 ID id = RNODE_LASGN(node)->nd_vid;
11259 int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
11261 debugs(
"lvar: %s idx: %d\n", rb_id2name(
id), idx);
11262 CHECK(COMPILE(ret,
"rvalue", RNODE_LASGN(node)->nd_value));
11265 ADD_INSN(ret, node, dup);
11267 ADD_SETLOCAL(ret, node, idx, get_lvar_level(iseq));
11272 ID id = RNODE_DASGN(node)->nd_vid;
11273 CHECK(COMPILE(ret,
"dvalue", RNODE_DASGN(node)->nd_value));
11274 debugi(
"dassn id", rb_id2str(
id) ?
id :
'*');
11277 ADD_INSN(ret, node, dup);
11280 idx = get_dyna_var_idx(iseq,
id, &lv, &ls);
11283 COMPILE_ERROR(ERROR_ARGS
"NODE_DASGN: unknown id (%"PRIsVALUE
")",
11287 ADD_SETLOCAL(ret, node, ls - idx, lv);
11291 CHECK(COMPILE(ret,
"lvalue", RNODE_GASGN(node)->nd_value));
11294 ADD_INSN(ret, node, dup);
11296 ADD_INSN1(ret, node, setglobal,
ID2SYM(RNODE_GASGN(node)->nd_vid));
11300 CHECK(COMPILE(ret,
"lvalue", RNODE_IASGN(node)->nd_value));
11302 ADD_INSN(ret, node, dup);
11304 ADD_INSN2(ret, node, setinstancevariable,
11305 ID2SYM(RNODE_IASGN(node)->nd_vid),
11306 get_ivar_ic_value(iseq,RNODE_IASGN(node)->nd_vid));
11310 if (RNODE_CDECL(node)->nd_vid) {
11311 CHECK(compile_shareable_constant_value(iseq, ret, RNODE_CDECL(node)->shareability, node, RNODE_CDECL(node)->nd_value));
11314 ADD_INSN(ret, node, dup);
11317 ADD_INSN1(ret, node, putspecialobject,
11318 INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
11319 ADD_INSN1(ret, node, setconstant,
ID2SYM(RNODE_CDECL(node)->nd_vid));
11322 compile_cpath(ret, iseq, RNODE_CDECL(node)->nd_else);
11323 CHECK(compile_shareable_constant_value(iseq, ret, RNODE_CDECL(node)->shareability, node, RNODE_CDECL(node)->nd_value));
11324 ADD_INSN(ret, node, swap);
11327 ADD_INSN1(ret, node, topn,
INT2FIX(1));
11328 ADD_INSN(ret, node, swap);
11331 ADD_INSN1(ret, node, setconstant,
ID2SYM(get_node_colon_nd_mid(RNODE_CDECL(node)->nd_else)));
11336 CHECK(COMPILE(ret,
"cvasgn val", RNODE_CVASGN(node)->nd_value));
11338 ADD_INSN(ret, node, dup);
11340 ADD_INSN2(ret, node, setclassvariable,
11341 ID2SYM(RNODE_CVASGN(node)->nd_vid),
11342 get_cvar_ic_value(iseq, RNODE_CVASGN(node)->nd_vid));
11345 case NODE_OP_ASGN1:
11346 CHECK(compile_op_asgn1(iseq, ret, node, popped));
11348 case NODE_OP_ASGN2:
11349 CHECK(compile_op_asgn2(iseq, ret, node, popped));
11351 case NODE_OP_CDECL:
11352 CHECK(compile_op_cdecl(iseq, ret, node, popped));
11354 case NODE_OP_ASGN_AND:
11355 case NODE_OP_ASGN_OR:
11356 CHECK(compile_op_log(iseq, ret, node, popped,
type));
11360 if (compile_call_precheck_freeze(iseq, ret, node, node, popped) == TRUE) {
11366 if (compile_call(iseq, ret, node,
type, node, popped,
false) == COMPILE_NG) {
11372 CHECK(compile_super(iseq, ret, node, popped,
type));
11375 CHECK(compile_array(iseq, ret, node, popped, TRUE) >= 0);
11380 ADD_INSN1(ret, node, newarray,
INT2FIX(0));
11385 CHECK(compile_hash(iseq, ret, node, FALSE, popped) >= 0);
11388 CHECK(compile_return(iseq, ret, node, popped));
11391 CHECK(compile_yield(iseq, ret, node, popped));
11395 compile_lvar(iseq, ret, node, RNODE_LVAR(node)->nd_vid);
11401 debugi(
"nd_vid", RNODE_DVAR(node)->nd_vid);
11403 idx = get_dyna_var_idx(iseq, RNODE_DVAR(node)->nd_vid, &lv, &ls);
11405 COMPILE_ERROR(ERROR_ARGS
"unknown dvar (%"PRIsVALUE
")",
11406 rb_id2str(RNODE_DVAR(node)->nd_vid));
11409 ADD_GETLOCAL(ret, node, ls - idx, lv);
11414 ADD_INSN1(ret, node, getglobal,
ID2SYM(RNODE_GVAR(node)->nd_vid));
11416 ADD_INSN(ret, node, pop);
11421 debugi(
"nd_vid", RNODE_IVAR(node)->nd_vid);
11423 ADD_INSN2(ret, node, getinstancevariable,
11424 ID2SYM(RNODE_IVAR(node)->nd_vid),
11425 get_ivar_ic_value(iseq, RNODE_IVAR(node)->nd_vid));
11430 debugi(
"nd_vid", RNODE_CONST(node)->nd_vid);
11432 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
11434 VALUE segments = rb_ary_new_from_args(1,
ID2SYM(RNODE_CONST(node)->nd_vid));
11436 ADD_INSN1(ret, node, opt_getconstant_path, segments);
11440 ADD_INSN(ret, node, putnil);
11441 ADD_INSN1(ret, node, putobject,
Qtrue);
11442 ADD_INSN1(ret, node, getconstant,
ID2SYM(RNODE_CONST(node)->nd_vid));
11446 ADD_INSN(ret, node, pop);
11452 ADD_INSN2(ret, node, getclassvariable,
11453 ID2SYM(RNODE_CVAR(node)->nd_vid),
11454 get_cvar_ic_value(iseq, RNODE_CVAR(node)->nd_vid));
11458 case NODE_NTH_REF:{
11460 if (!RNODE_NTH_REF(node)->nd_nth) {
11461 ADD_INSN(ret, node, putnil);
11464 ADD_INSN2(ret, node, getspecial,
INT2FIX(1) ,
11465 INT2FIX(RNODE_NTH_REF(node)->nd_nth << 1));
11469 case NODE_BACK_REF:{
11471 ADD_INSN2(ret, node, getspecial,
INT2FIX(1) ,
11472 INT2FIX(0x01 | (RNODE_BACK_REF(node)->nd_nth << 1)));
11479 CHECK(compile_match(iseq, ret, node, popped,
type));
11483 ADD_INSN1(ret, node, putobject, rb_node_sym_string_val(node));
11489 ADD_INSN1(ret, node, putobject, rb_node_line_lineno_val(node));
11493 case NODE_ENCODING:{
11495 ADD_INSN1(ret, node, putobject, rb_node_encoding_val(node));
11499 case NODE_INTEGER:{
11500 VALUE lit = rb_node_integer_literal_val(node);
11502 debugp_param(
"integer", lit);
11504 ADD_INSN1(ret, node, putobject, lit);
11510 VALUE lit = rb_node_float_literal_val(node);
11512 debugp_param(
"float", lit);
11514 ADD_INSN1(ret, node, putobject, lit);
11519 case NODE_RATIONAL:{
11520 VALUE lit = rb_node_rational_literal_val(node);
11522 debugp_param(
"rational", lit);
11524 ADD_INSN1(ret, node, putobject, lit);
11529 case NODE_IMAGINARY:{
11530 VALUE lit = rb_node_imaginary_literal_val(node);
11532 debugp_param(
"imaginary", lit);
11534 ADD_INSN1(ret, node, putobject, lit);
11541 debugp_param(
"nd_lit", get_string_value(node));
11543 VALUE lit = get_string_value(node);
11546 option->frozen_string_literal != ISEQ_FROZEN_STRING_LITERAL_DISABLED) {
11547 lit = rb_str_with_debug_created_info(lit, rb_iseq_path(iseq), line);
11550 switch (option->frozen_string_literal) {
11551 case ISEQ_FROZEN_STRING_LITERAL_UNSET:
11552 ADD_INSN1(ret, node, dupchilledstring, lit);
11554 case ISEQ_FROZEN_STRING_LITERAL_DISABLED:
11555 ADD_INSN1(ret, node, dupstring, lit);
11557 case ISEQ_FROZEN_STRING_LITERAL_ENABLED:
11558 ADD_INSN1(ret, node, putobject, lit);
11561 rb_bug(
"invalid frozen_string_literal");
11568 compile_dstr(iseq, ret, node);
11571 ADD_INSN(ret, node, pop);
11576 ADD_CALL_RECEIVER(ret, node);
11577 VALUE str = rb_node_str_string_val(node);
11578 ADD_INSN1(ret, node, putobject, str);
11580 ADD_CALL(ret, node, idBackquote,
INT2FIX(1));
11583 ADD_INSN(ret, node, pop);
11588 ADD_CALL_RECEIVER(ret, node);
11589 compile_dstr(iseq, ret, node);
11590 ADD_CALL(ret, node, idBackquote,
INT2FIX(1));
11593 ADD_INSN(ret, node, pop);
11598 CHECK(compile_evstr(iseq, ret, RNODE_EVSTR(node)->nd_body, popped));
11602 VALUE lit = rb_node_regx_string_val(node);
11604 ADD_INSN1(ret, node, putobject, lit);
11610 compile_dregx(iseq, ret, node, popped);
11613 int ic_index = body->ise_size++;
11615 block_iseq = NEW_CHILD_ISEQ(RNODE_ONCE(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line);
11617 ADD_INSN2(ret, node, once, block_iseq,
INT2FIX(ic_index));
11621 ADD_INSN(ret, node, pop);
11625 case NODE_ARGSCAT:{
11627 CHECK(COMPILE(ret,
"argscat head", RNODE_ARGSCAT(node)->nd_head));
11628 ADD_INSN1(ret, node, splatarray,
Qfalse);
11629 ADD_INSN(ret, node, pop);
11630 CHECK(COMPILE(ret,
"argscat body", RNODE_ARGSCAT(node)->nd_body));
11631 ADD_INSN1(ret, node, splatarray,
Qfalse);
11632 ADD_INSN(ret, node, pop);
11635 CHECK(COMPILE(ret,
"argscat head", RNODE_ARGSCAT(node)->nd_head));
11636 const NODE *body_node = RNODE_ARGSCAT(node)->nd_body;
11637 if (nd_type_p(body_node, NODE_LIST)) {
11638 CHECK(compile_array(iseq, ret, body_node, popped, FALSE) >= 0);
11641 CHECK(COMPILE(ret,
"argscat body", body_node));
11642 ADD_INSN(ret, node, concattoarray);
11647 case NODE_ARGSPUSH:{
11649 CHECK(COMPILE(ret,
"argspush head", RNODE_ARGSPUSH(node)->nd_head));
11650 ADD_INSN1(ret, node, splatarray,
Qfalse);
11651 ADD_INSN(ret, node, pop);
11652 CHECK(COMPILE_(ret,
"argspush body", RNODE_ARGSPUSH(node)->nd_body, popped));
11655 CHECK(COMPILE(ret,
"argspush head", RNODE_ARGSPUSH(node)->nd_head));
11656 const NODE *body_node = RNODE_ARGSPUSH(node)->nd_body;
11657 if (keyword_node_p(body_node)) {
11658 CHECK(COMPILE_(ret,
"array element", body_node, FALSE));
11659 ADD_INSN(ret, node, pushtoarraykwsplat);
11661 else if (static_literal_node_p(body_node, iseq,
false)) {
11662 ADD_INSN1(ret, body_node, putobject, static_literal_value(body_node, iseq));
11663 ADD_INSN1(ret, node, pushtoarray,
INT2FIX(1));
11666 CHECK(COMPILE_(ret,
"array element", body_node, FALSE));
11667 ADD_INSN1(ret, node, pushtoarray,
INT2FIX(1));
11673 CHECK(COMPILE(ret,
"splat", RNODE_SPLAT(node)->nd_head));
11674 ADD_INSN1(ret, node, splatarray,
Qtrue);
11677 ADD_INSN(ret, node, pop);
11682 ID mid = RNODE_DEFN(node)->nd_mid;
11683 const rb_iseq_t *method_iseq = NEW_ISEQ(RNODE_DEFN(node)->nd_defn,
11685 ISEQ_TYPE_METHOD, line);
11687 debugp_param(
"defn/iseq", rb_iseqw_new(method_iseq));
11688 ADD_INSN2(ret, node, definemethod,
ID2SYM(mid), method_iseq);
11692 ADD_INSN1(ret, node, putobject,
ID2SYM(mid));
11698 ID mid = RNODE_DEFS(node)->nd_mid;
11699 const rb_iseq_t * singleton_method_iseq = NEW_ISEQ(RNODE_DEFS(node)->nd_defn,
11701 ISEQ_TYPE_METHOD, line);
11703 debugp_param(
"defs/iseq", rb_iseqw_new(singleton_method_iseq));
11704 CHECK(COMPILE(ret,
"defs: recv", RNODE_DEFS(node)->nd_recv));
11705 ADD_INSN2(ret, node, definesmethod,
ID2SYM(mid), singleton_method_iseq);
11709 ADD_INSN1(ret, node, putobject,
ID2SYM(mid));
11714 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
11715 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_CBASE));
11716 CHECK(COMPILE(ret,
"alias arg1", RNODE_ALIAS(node)->nd_1st));
11717 CHECK(COMPILE(ret,
"alias arg2", RNODE_ALIAS(node)->nd_2nd));
11718 ADD_SEND(ret, node, id_core_set_method_alias,
INT2FIX(3));
11721 ADD_INSN(ret, node, pop);
11726 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
11727 ADD_INSN1(ret, node, putobject,
ID2SYM(RNODE_VALIAS(node)->nd_alias));
11728 ADD_INSN1(ret, node, putobject,
ID2SYM(RNODE_VALIAS(node)->nd_orig));
11729 ADD_SEND(ret, node, id_core_set_variable_alias,
INT2FIX(2));
11732 ADD_INSN(ret, node, pop);
11739 for (
long i = 0; i < ary->len; i++) {
11740 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
11741 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_CBASE));
11742 CHECK(COMPILE(ret,
"undef arg", ary->data[i]));
11743 ADD_SEND(ret, node, id_core_undef_method,
INT2FIX(2));
11745 if (i < ary->
len - 1) {
11746 ADD_INSN(ret, node, pop);
11751 ADD_INSN(ret, node, pop);
11756 const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(RNODE_CLASS(node)->nd_body,
11757 rb_str_freeze(rb_sprintf(
"<class:%"PRIsVALUE
">", rb_id2str(get_node_colon_nd_mid(RNODE_CLASS(node)->nd_cpath)))),
11758 ISEQ_TYPE_CLASS, line);
11759 const int flags = VM_DEFINECLASS_TYPE_CLASS |
11760 (RNODE_CLASS(node)->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) |
11761 compile_cpath(ret, iseq, RNODE_CLASS(node)->nd_cpath);
11763 CHECK(COMPILE(ret,
"super", RNODE_CLASS(node)->nd_super));
11764 ADD_INSN3(ret, node, defineclass,
ID2SYM(get_node_colon_nd_mid(RNODE_CLASS(node)->nd_cpath)), class_iseq,
INT2FIX(flags));
11768 ADD_INSN(ret, node, pop);
11773 const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(RNODE_MODULE(node)->nd_body,
11774 rb_str_freeze(rb_sprintf(
"<module:%"PRIsVALUE
">", rb_id2str(get_node_colon_nd_mid(RNODE_MODULE(node)->nd_cpath)))),
11775 ISEQ_TYPE_CLASS, line);
11776 const int flags = VM_DEFINECLASS_TYPE_MODULE |
11777 compile_cpath(ret, iseq, RNODE_MODULE(node)->nd_cpath);
11779 ADD_INSN (ret, node, putnil);
11780 ADD_INSN3(ret, node, defineclass,
ID2SYM(get_node_colon_nd_mid(RNODE_MODULE(node)->nd_cpath)), module_iseq,
INT2FIX(flags));
11784 ADD_INSN(ret, node, pop);
11790 const rb_iseq_t *singleton_class = NEW_ISEQ(RNODE_SCLASS(node)->nd_body, rb_fstring_lit(
"singleton class"),
11791 ISEQ_TYPE_CLASS, line);
11793 CHECK(COMPILE(ret,
"sclass#recv", RNODE_SCLASS(node)->nd_recv));
11794 ADD_INSN (ret, node, putnil);
11795 CONST_ID(singletonclass,
"singletonclass");
11799 int sclass_flags = VM_DEFINECLASS_TYPE_SINGLETON_CLASS;
11800 const NODE *recv = RNODE_SCLASS(node)->nd_recv;
11801 if (!(nd_type_p(recv, NODE_SELF) &&
11802 ISEQ_BODY(iseq)->
type == ISEQ_TYPE_CLASS) &&
11803 !cpath_const_p(recv)) {
11804 sclass_flags |= VM_DEFINECLASS_FLAG_DYNAMIC_CREF;
11807 ADD_INSN3(ret, node, defineclass,
11808 ID2SYM(singletonclass), singleton_class,
11813 ADD_INSN(ret, node, pop);
11818 CHECK(compile_colon2(iseq, ret, node, popped));
11821 CHECK(compile_colon3(iseq, ret, node, popped));
11824 CHECK(compile_dots(iseq, ret, node, popped, FALSE));
11827 CHECK(compile_dots(iseq, ret, node, popped, TRUE));
11831 LABEL *lend = NEW_LABEL(line);
11832 LABEL *ltrue = NEW_LABEL(line);
11833 LABEL *lfalse = NEW_LABEL(line);
11834 CHECK(compile_flip_flop(iseq, ret, node,
type == NODE_FLIP2,
11836 ADD_LABEL(ret, ltrue);
11837 ADD_INSN1(ret, node, putobject,
Qtrue);
11838 ADD_INSNL(ret, node, jump, lend);
11839 ADD_LABEL(ret, lfalse);
11840 ADD_INSN1(ret, node, putobject,
Qfalse);
11841 ADD_LABEL(ret, lend);
11846 ADD_INSN(ret, node, putself);
11852 ADD_INSN(ret, node, putnil);
11858 ADD_INSN1(ret, node, putobject,
Qtrue);
11864 ADD_INSN1(ret, node, putobject,
Qfalse);
11869 CHECK(compile_errinfo(iseq, ret, node, popped));
11873 CHECK(compile_defined_expr(iseq, ret, node,
Qtrue,
false));
11876 case NODE_POSTEXE:{
11880 int is_index = body->ise_size++;
11882 rb_iseq_new_with_callback_new_callback(build_postexe_iseq, RNODE_POSTEXE(node)->nd_body);
11884 NEW_CHILD_ISEQ_WITH_CALLBACK(ifunc, rb_fstring(make_name_for_block(iseq)), ISEQ_TYPE_BLOCK, line);
11886 ADD_INSN2(ret, node, once, once_iseq,
INT2FIX(is_index));
11890 ADD_INSN(ret, node, pop);
11895 CHECK(compile_kw_arg(iseq, ret, node, popped));
11898 compile_dstr(iseq, ret, node);
11900 ADD_INSN(ret, node, intern);
11903 ADD_INSN(ret, node, pop);
11907 case NODE_ATTRASGN:
11908 CHECK(compile_attrasgn(iseq, ret, node, popped));
11912 const rb_iseq_t *block = NEW_CHILD_ISEQ(RNODE_LAMBDA(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
11915 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
11916 ADD_CALL_WITH_BLOCK(ret, node, idLambda, argc, block);
11920 ADD_INSN(ret, node, pop);
11925 UNKNOWN_NODE(
"iseq_compile_each", node, COMPILE_NG);
11940insn_data_length(
INSN *iobj)
11942 return insn_len(iobj->insn_id);
11946calc_sp_depth(
int depth,
INSN *insn)
11948 return comptime_insn_stack_increase(depth, insn->insn_id, insn->operands);
11952opobj_inspect(
VALUE obj)
11972insn_data_to_s_detail(
INSN *iobj)
11974 VALUE str = rb_sprintf(
"%-20s ", insn_name(iobj->insn_id));
11976 if (iobj->operands) {
11977 const char *types = insn_op_types(iobj->insn_id);
11980 for (j = 0; types[j]; j++) {
11981 char type = types[j];
11987 rb_str_catf(str, LABEL_FORMAT, lobj->label_no);
12005 VALUE v = OPERAND_AT(iobj, j);
12020 rb_str_catf(str,
"<ivc:%d>",
FIX2INT(OPERAND_AT(iobj, j)));
12023 rb_str_catf(str,
"<icvarc:%d>",
FIX2INT(OPERAND_AT(iobj, j)));
12026 rb_str_catf(str,
"<ise:%d>",
FIX2INT(OPERAND_AT(iobj, j)));
12032 if (vm_ci_mid(ci))
rb_str_append(str, rb_id2str(vm_ci_mid(ci)));
12033 rb_str_catf(str,
", %d>", vm_ci_argc(ci));
12041 void *func = (
void *)OPERAND_AT(iobj, j);
12044 if (dladdr(func, &info) && info.dli_sname) {
12049 rb_str_catf(str,
"<%p>", func);
12059 if (types[j + 1]) {
12070 dump_disasm_list_with_cursor(link, NULL, NULL);
12081 printf(
"-- raw disasm--------\n");
12084 if (curr) printf(curr == link ?
"*" :
" ");
12085 switch (link->type) {
12086 case ISEQ_ELEMENT_INSN:
12088 iobj = (
INSN *)link;
12089 str = insn_data_to_s_detail(iobj);
12090 printf(
" %04d %-65s(%4u)\n", pos,
StringValueCStr(str), iobj->insn_info.line_no);
12091 pos += insn_data_length(iobj);
12094 case ISEQ_ELEMENT_LABEL:
12096 lobj = (
LABEL *)link;
12097 printf(LABEL_FORMAT
" [sp: %d, unremovable: %d, refcnt: %d]%s\n", lobj->label_no, lobj->sp, lobj->unremovable, lobj->refcnt,
12098 dest == lobj ?
" <---" :
"");
12101 case ISEQ_ELEMENT_TRACE:
12104 printf(
" trace: %0x\n", trace->event);
12107 case ISEQ_ELEMENT_ADJUST:
12110 printf(
" adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1);
12115 rb_raise(
rb_eSyntaxError,
"dump_disasm_list error: %d\n", (
int)link->type);
12119 printf(
"---------------------\n");
12124rb_insn_len(
VALUE insn)
12126 return insn_len(insn);
12130rb_insns_name(
int i)
12132 return insn_name(i);
12136rb_insns_name_array(
void)
12140 for (i = 0; i < VM_INSTRUCTION_SIZE; i++) {
12151 obj = rb_to_symbol_type(obj);
12153 if (st_lookup(labels_table, obj, &tmp) == 0) {
12154 label = NEW_LABEL(0);
12155 st_insert(labels_table, obj, (st_data_t)label);
12158 label = (
LABEL *)tmp;
12165get_exception_sym2type(
VALUE sym)
12167 static VALUE symRescue, symEnsure, symRetry;
12168 static VALUE symBreak, symRedo, symNext;
12170 if (symRescue == 0) {
12179 if (sym == symRescue)
return CATCH_TYPE_RESCUE;
12180 if (sym == symEnsure)
return CATCH_TYPE_ENSURE;
12181 if (sym == symRetry)
return CATCH_TYPE_RETRY;
12182 if (sym == symBreak)
return CATCH_TYPE_BREAK;
12183 if (sym == symRedo)
return CATCH_TYPE_REDO;
12184 if (sym == symNext)
return CATCH_TYPE_NEXT;
12185 rb_raise(
rb_eSyntaxError,
"invalid exception symbol: %+"PRIsVALUE, sym);
12198 LABEL *lstart, *lend, *lcont;
12213 lstart = register_label(iseq, labels_table,
RARRAY_AREF(v, 2));
12214 lend = register_label(iseq, labels_table,
RARRAY_AREF(v, 3));
12215 lcont = register_label(iseq, labels_table,
RARRAY_AREF(v, 4));
12219 if (
type == CATCH_TYPE_RESCUE ||
12220 type == CATCH_TYPE_BREAK ||
12221 type == CATCH_TYPE_NEXT) {
12227 ADD_CATCH_ENTRY(
type, lstart, lend, eiseq, lcont);
12235insn_make_insn_table(
void)
12239 table = st_init_numtable_with_size(VM_INSTRUCTION_SIZE);
12241 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
12255 iseqw = rb_iseq_load(op, (
VALUE)iseq,
Qnil);
12257 else if (
CLASS_OF(op) == rb_cISeq) {
12264 loaded_iseq = rb_iseqw_to_iseq(iseqw);
12265 return loaded_iseq;
12273 unsigned int flag = 0;
12284 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
12286 if (!
NIL_P(vkw_arg)) {
12289 size_t n = rb_callinfo_kwarg_bytes(
len);
12292 kw_arg->references = 0;
12293 kw_arg->keyword_len =
len;
12294 for (i = 0; i <
len; i++) {
12297 kw_arg->keywords[i] = kw;
12302 const struct rb_callinfo *ci = new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0);
12308event_name_to_flag(
VALUE sym)
12310#define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern_const(#ev))) return ev;
12331 int line_no = 0, node_id = -1, insn_idx = 0;
12332 int ret = COMPILE_OK;
12337 static struct st_table *insn_table;
12339 if (insn_table == 0) {
12340 insn_table = insn_make_insn_table();
12343 for (i=0; i<
len; i++) {
12349 ADD_TRACE(anchor, event);
12352 LABEL *label = register_label(iseq, labels_table, obj);
12353 ADD_LABEL(anchor, label);
12370 if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
12372 COMPILE_ERROR(iseq, line_no,
12373 "unknown instruction: %+"PRIsVALUE, insn);
12378 if (argc != insn_len((
VALUE)insn_id)-1) {
12379 COMPILE_ERROR(iseq, line_no,
12380 "operand size mismatch");
12386 argv = compile_data_calloc2_type(iseq,
VALUE, argc);
12391 (
enum ruby_vminsn_type)insn_id, argc, argv));
12393 for (j=0; j<argc; j++) {
12395 switch (insn_op_type((
VALUE)insn_id, j)) {
12397 LABEL *label = register_label(iseq, labels_table, op);
12398 argv[j] = (
VALUE)label;
12413 VALUE v = (
VALUE)iseq_build_load_iseq(iseq, op);
12424 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->ise_size) {
12425 ISEQ_BODY(iseq)->ise_size =
NUM2INT(op) + 1;
12431 op = rb_to_array_type(op);
12435 sym = rb_to_symbol_type(sym);
12440 argv[j] = segments;
12442 ISEQ_BODY(iseq)->ic_size++;
12447 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->ivc_size) {
12448 ISEQ_BODY(iseq)->ivc_size =
NUM2INT(op) + 1;
12453 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->icvarc_size) {
12454 ISEQ_BODY(iseq)->icvarc_size =
NUM2INT(op) + 1;
12458 argv[j] = iseq_build_callinfo_from_hash(iseq, op);
12461 argv[j] = rb_to_symbol_type(op);
12468 op = rb_to_array_type(op);
12473 register_label(iseq, labels_table, sym);
12474 cdhash_aset(map, key, (
VALUE)label);
12484#if SIZEOF_VALUE <= SIZEOF_LONG
12489 argv[j] = (
VALUE)funcptr;
12500 (
enum ruby_vminsn_type)insn_id, argc, NULL));
12504 rb_raise(
rb_eTypeError,
"unexpected object for instruction");
12509 validate_labels(iseq, labels_table);
12510 if (!ret)
return ret;
12511 return iseq_setup(iseq, anchor);
12514#define CHECK_ARRAY(v) rb_to_array_type(v)
12515#define CHECK_SYMBOL(v) rb_to_symbol_type(v)
12520 VALUE val = rb_hash_aref(param, sym);
12525 else if (!
NIL_P(val)) {
12526 rb_raise(
rb_eTypeError,
"invalid %+"PRIsVALUE
" Fixnum: %+"PRIsVALUE,
12532static const struct rb_iseq_param_keyword *
12538 VALUE key, sym, default_val;
12541 struct rb_iseq_param_keyword *keyword =
ZALLOC(
struct rb_iseq_param_keyword);
12543 ISEQ_BODY(iseq)->param.flags.has_kw = TRUE;
12545 keyword->num =
len;
12546#define SYM(s) ID2SYM(rb_intern_const(#s))
12547 (void)int_param(&keyword->bits_start, params, SYM(kwbits));
12548 i = keyword->bits_start - keyword->num;
12549 ids = (
ID *)&ISEQ_BODY(iseq)->local_table[i];
12553 for (i = 0; i <
len; i++) {
12557 goto default_values;
12560 keyword->required_num++;
12564 default_len =
len - i;
12565 if (default_len == 0) {
12566 keyword->table = ids;
12569 else if (default_len < 0) {
12575 for (j = 0; i <
len; i++, j++) {
12589 rb_raise(
rb_eTypeError,
"keyword default has unsupported len %+"PRIsVALUE, key);
12595 keyword->table = ids;
12596 keyword->default_values = dvs;
12602iseq_insn_each_object_mark_and_move(
VALUE * obj,
VALUE _)
12604 rb_gc_mark_and_move(obj);
12611 size_t size =
sizeof(
INSN);
12612 size_t align = ALIGNMENT_SIZE_OF(
INSN);
12613 unsigned int pos = 0;
12616 size_t padding = calc_padding((
void *)&storage->buff[pos], align);
12617 size_t offset = pos + size + padding;
12618 if (offset > storage->size || offset > storage->pos) {
12620 storage = storage->next;
12623 pos += (int)padding;
12625 iobj = (
INSN *)&storage->buff[pos];
12627 if (iobj->operands) {
12628 iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark_and_move, (
VALUE)0);
12641 .flags = RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED,
12648#define SYM(s) ID2SYM(rb_intern_const(#s))
12650 unsigned int arg_size, local_size, stack_max;
12652 struct st_table *labels_table = st_init_numtable();
12654 VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt));
12655 VALUE keywords = rb_hash_aref(params, SYM(keyword));
12657 DECL_ANCHOR(anchor);
12658 INIT_ANCHOR(anchor);
12661 ISEQ_BODY(iseq)->local_table_size =
len;
12662 ISEQ_BODY(iseq)->local_table = tbl =
len > 0 ? (
ID *)
ALLOC_N(
ID, ISEQ_BODY(iseq)->local_table_size) : NULL;
12664 for (i = 0; i <
len; i++) {
12667 if (sym_arg_rest == lv) {
12675#define INT_PARAM(F) int_param(&ISEQ_BODY(iseq)->param.F, params, SYM(F))
12676 if (INT_PARAM(lead_num)) {
12677 ISEQ_BODY(iseq)->param.flags.has_lead = TRUE;
12679 if (INT_PARAM(post_num)) ISEQ_BODY(iseq)->param.flags.has_post = TRUE;
12680 if (INT_PARAM(post_start)) ISEQ_BODY(iseq)->param.flags.has_post = TRUE;
12681 if (INT_PARAM(rest_start)) ISEQ_BODY(iseq)->param.flags.has_rest = TRUE;
12682 if (INT_PARAM(block_start)) ISEQ_BODY(iseq)->param.flags.has_block = TRUE;
12685#define INT_PARAM(F) F = (int_param(&x, misc, SYM(F)) ? (unsigned int)x : 0)
12687 INT_PARAM(arg_size);
12688 INT_PARAM(local_size);
12689 INT_PARAM(stack_max);
12693 VALUE source_hash = rb_hash_aref(misc,
ID2SYM(rb_intern(
"source_hash")));
12694 if (!
NIL_P(source_hash)) {
12695 ISEQ_BODY(iseq)->source_hash =
NUM2ULL(source_hash);
12699#ifdef USE_ISEQ_NODE_ID
12700 node_ids = rb_hash_aref(misc,
ID2SYM(rb_intern(
"node_ids")));
12708 ISEQ_BODY(iseq)->param.flags.has_opt = !!(
len - 1 >= 0);
12710 if (ISEQ_BODY(iseq)->param.flags.has_opt) {
12713 for (i = 0; i <
len; i++) {
12715 LABEL *label = register_label(iseq, labels_table, ent);
12716 opt_table[i] = (
VALUE)label;
12719 ISEQ_BODY(iseq)->param.opt_num =
len - 1;
12720 ISEQ_BODY(iseq)->param.opt_table = opt_table;
12723 else if (!
NIL_P(arg_opt_labels)) {
12724 rb_raise(
rb_eTypeError,
":opt param is not an array: %+"PRIsVALUE,
12729 ISEQ_BODY(iseq)->param.keyword = iseq_build_kw(iseq, params, keywords);
12731 else if (!
NIL_P(keywords)) {
12732 rb_raise(
rb_eTypeError,
":keywords param is not an array: %+"PRIsVALUE,
12736 if (
Qtrue == rb_hash_aref(params, SYM(ambiguous_param0))) {
12737 ISEQ_BODY(iseq)->param.flags.ambiguous_param0 = TRUE;
12740 if (
Qtrue == rb_hash_aref(params, SYM(use_block))) {
12741 ISEQ_BODY(iseq)->param.flags.use_block = TRUE;
12744 if (int_param(&i, params, SYM(kwrest))) {
12745 struct rb_iseq_param_keyword *keyword = (
struct rb_iseq_param_keyword *)ISEQ_BODY(iseq)->param.keyword;
12746 if (keyword == NULL) {
12747 ISEQ_BODY(iseq)->param.keyword = keyword =
ZALLOC(
struct rb_iseq_param_keyword);
12749 keyword->rest_start = i;
12750 ISEQ_BODY(iseq)->param.flags.has_kwrest = TRUE;
12753 iseq_calc_param_size(iseq);
12756 iseq_build_from_ary_exception(iseq, labels_table, exception);
12759 iseq_build_from_ary_body(iseq, anchor, body, node_ids, labels_wrapper);
12761 ISEQ_BODY(iseq)->param.size = arg_size;
12762 ISEQ_BODY(iseq)->local_table_size = local_size;
12763 ISEQ_BODY(iseq)->stack_max = stack_max;
12773 while (body->type == ISEQ_TYPE_BLOCK ||
12774 body->type == ISEQ_TYPE_RESCUE ||
12775 body->type == ISEQ_TYPE_ENSURE ||
12776 body->type == ISEQ_TYPE_EVAL ||
12777 body->type == ISEQ_TYPE_MAIN
12781 for (i = 0; i < body->local_table_size; i++) {
12782 if (body->local_table[i] ==
id) {
12786 iseq = body->parent_iseq;
12787 body = ISEQ_BODY(iseq);
12800 for (i=0; i<body->local_table_size; i++) {
12801 if (body->local_table[i] ==
id) {
12811#ifndef IBF_ISEQ_DEBUG
12812#define IBF_ISEQ_DEBUG 0
12815#ifndef IBF_ISEQ_ENABLE_LOCAL_BUFFER
12816#define IBF_ISEQ_ENABLE_LOCAL_BUFFER 0
12819typedef uint32_t ibf_offset_t;
12820#define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
12822#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
12824#define IBF_DEVEL_VERSION 12
12825#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
12827#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
12830static const char IBF_ENDIAN_MARK =
12831#ifdef WORDS_BIGENDIAN
12840 uint32_t major_version;
12841 uint32_t minor_version;
12843 uint32_t extra_size;
12845 uint32_t iseq_list_size;
12846 uint32_t global_object_list_size;
12847 ibf_offset_t iseq_list_offset;
12848 ibf_offset_t global_object_list_offset;
12869 unsigned int obj_list_size;
12870 ibf_offset_t obj_list_offset;
12889pinned_list_mark(
void *ptr)
12893 for (i = 0; i < list->size; i++) {
12894 if (list->buffer[i]) {
12895 rb_gc_mark(list->buffer[i]);
12907 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_EMBEDDABLE
12911pinned_list_fetch(
VALUE list,
long offset)
12917 if (offset < 0 || offset >= ptr->size) {
12918 rb_raise(
rb_eIndexError,
"object index out of range: %ld", offset);
12921 return ptr->buffer[offset];
12925pinned_list_store(
VALUE list,
long offset,
VALUE object)
12931 if (offset < 0 || offset >= ptr->size) {
12932 rb_raise(
rb_eIndexError,
"object index out of range: %ld", offset);
12939pinned_list_new(
long size)
12941 size_t memsize = offsetof(
struct pinned_list, buffer) + size *
sizeof(
VALUE);
12942 VALUE obj_list = rb_data_typed_object_zalloc(0, memsize, &pinned_list_type);
12943 struct pinned_list * ptr = RTYPEDDATA_GET_DATA(obj_list);
12949ibf_dump_pos(
struct ibf_dump *dump)
12951 rb_len_t pos = RSTRING_LEN(dump->current_buffer->str);
12952#if SIZEOF_RB_LEN_T > SIZEOF_INT
12953 if (pos >= UINT_MAX) {
12957 return (
unsigned int)pos;
12961ibf_dump_align(
struct ibf_dump *dump,
size_t align)
12963 ibf_offset_t pos = ibf_dump_pos(dump);
12965 static const char padding[
sizeof(
VALUE)];
12966 size_t size = align - ((size_t)pos % align);
12967#if SIZEOF_RB_LEN_T > SIZEOF_INT
12968 if (pos + size >= UINT_MAX) {
12972 for (; size >
sizeof(padding); size -=
sizeof(padding)) {
12973 rb_str_cat(dump->current_buffer->str, padding,
sizeof(padding));
12975 rb_str_cat(dump->current_buffer->str, padding, size);
12980ibf_dump_write(
struct ibf_dump *dump,
const void *buff,
size_t size)
12982 ibf_offset_t pos = ibf_dump_pos(dump);
12983#if SIZEOF_RB_LEN_T > SIZEOF_INT
12985 if (size >= UINT_MAX || pos + size >= UINT_MAX) {
12989 rb_str_cat(dump->current_buffer->str, (
const char *)buff, size);
12994ibf_dump_write_byte(
struct ibf_dump *dump,
unsigned char byte)
12996 return ibf_dump_write(dump, &
byte,
sizeof(
unsigned char));
13000ibf_dump_overwrite(
struct ibf_dump *dump,
void *buff,
unsigned int size,
rb_len_t offset)
13002 VALUE str = dump->current_buffer->str;
13003 char *ptr = RSTRING_PTR(str);
13005 rb_bug(
"ibf_dump_overwrite: overflow");
13006 memcpy(ptr + offset, buff, size);
13010ibf_load_ptr(
const struct ibf_load *load, ibf_offset_t *offset,
int size)
13012 ibf_offset_t beg = *offset;
13014 return load->current_buffer->buff + beg;
13018ibf_load_alloc(
const struct ibf_load *load, ibf_offset_t offset,
size_t x,
size_t y)
13020 void *buff = ruby_xmalloc2(x, y);
13021 size_t size = x * y;
13022 memcpy(buff, load->current_buffer->buff + offset, size);
13026#define IBF_W_ALIGN(type) (RUBY_ALIGNOF(type) > 1 ? ibf_dump_align(dump, RUBY_ALIGNOF(type)) : (void)0)
13028#define IBF_W(b, type, n) (IBF_W_ALIGN(type), (type *)(VALUE)IBF_WP(b, type, n))
13029#define IBF_WV(variable) ibf_dump_write(dump, &(variable), sizeof(variable))
13030#define IBF_WP(b, type, n) ibf_dump_write(dump, (b), sizeof(type) * (n))
13031#define IBF_R(val, type, n) (type *)ibf_load_alloc(load, IBF_OFFSET(val), sizeof(type), (n))
13032#define IBF_ZERO(variable) memset(&(variable), 0, sizeof(variable))
13035ibf_table_lookup(
struct st_table *table, st_data_t key)
13039 if (st_lookup(table, key, &val)) {
13048ibf_table_find_or_insert(
struct st_table *table, st_data_t key)
13050 int index = ibf_table_lookup(table, key);
13053 index = (int)table->num_entries;
13054 st_insert(table, key, (st_data_t)index);
13062static void ibf_dump_object_list(
struct ibf_dump *dump, ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size);
13068ibf_dump_object_table_new(
void)
13070 st_table *obj_table = st_init_numtable();
13071 st_insert(obj_table, (st_data_t)
Qnil, (st_data_t)0);
13079 return ibf_table_find_or_insert(dump->current_buffer->obj_table, (st_data_t)obj);
13085 if (
id == 0 || rb_id2name(
id) == NULL) {
13088 return ibf_dump_object(dump,
rb_id2sym(
id));
13092ibf_load_id(
const struct ibf_load *load,
const ID id_index)
13094 if (id_index == 0) {
13097 VALUE sym = ibf_load_object(load, id_index);
13107static ibf_offset_t ibf_dump_iseq_each(
struct ibf_dump *dump,
const rb_iseq_t *iseq);
13112 if (iseq == NULL) {
13116 return ibf_table_find_or_insert(dump->iseq_table, (st_data_t)iseq);
13120static unsigned char
13121ibf_load_byte(
const struct ibf_load *load, ibf_offset_t *offset)
13123 if (*offset >= load->current_buffer->size) { rb_raise(
rb_eRuntimeError,
"invalid bytecode"); }
13124 return (
unsigned char)load->current_buffer->buff[(*offset)++];
13140 if (
sizeof(
VALUE) > 8 || CHAR_BIT != 8) {
13141 ibf_dump_write(dump, &x,
sizeof(
VALUE));
13145 enum { max_byte_length =
sizeof(
VALUE) + 1 };
13147 unsigned char bytes[max_byte_length];
13150 for (n = 0; n <
sizeof(
VALUE) && (x >> (7 - n)); n++, x >>= 8) {
13151 bytes[max_byte_length - 1 - n] = (
unsigned char)x;
13157 bytes[max_byte_length - 1 - n] = (
unsigned char)x;
13160 ibf_dump_write(dump, bytes + max_byte_length - n, n);
13164ibf_load_small_value(
const struct ibf_load *load, ibf_offset_t *offset)
13166 if (
sizeof(
VALUE) > 8 || CHAR_BIT != 8) {
13167 union {
char s[
sizeof(
VALUE)];
VALUE v; } x;
13169 memcpy(x.s, load->current_buffer->buff + *offset,
sizeof(
VALUE));
13170 *offset +=
sizeof(
VALUE);
13175 enum { max_byte_length =
sizeof(
VALUE) + 1 };
13177 const unsigned char *buffer = (
const unsigned char *)load->current_buffer->buff;
13178 const unsigned char c = buffer[*offset];
13182 c == 0 ? 9 : ntz_int32(c) + 1;
13185 if (*offset + n > load->current_buffer->size) {
13190 for (i = 1; i < n; i++) {
13192 x |= (
VALUE)buffer[*offset + i];
13206 ibf_dump_write_small_value(dump, (
VALUE)bf->index);
13208 size_t len = strlen(bf->name);
13209 ibf_dump_write_small_value(dump, (
VALUE)
len);
13210 ibf_dump_write(dump, bf->name,
len);
13214ibf_load_builtin(
const struct ibf_load *load, ibf_offset_t *offset)
13216 int i = (int)ibf_load_small_value(load, offset);
13217 int len = (int)ibf_load_small_value(load, offset);
13218 const char *name = (
char *)ibf_load_ptr(load, offset,
len);
13221 fprintf(stderr,
"%.*s!!\n",
len, name);
13225 if (table == NULL) rb_raise(rb_eArgError,
"builtin function table is not provided");
13226 if (strncmp(table[i].name, name,
len) != 0) {
13227 rb_raise(rb_eArgError,
"builtin function index (%d) mismatch (expect %.*s but %s)",
13228 i,
len, name, table[i].name);
13239 const int iseq_size = body->iseq_size;
13241 const VALUE *orig_code = rb_iseq_original_iseq(iseq);
13243 ibf_offset_t offset = ibf_dump_pos(dump);
13245 for (code_index=0; code_index<iseq_size;) {
13246 const VALUE insn = orig_code[code_index++];
13247 const char *types = insn_op_types(insn);
13252 ibf_dump_write_small_value(dump, insn);
13255 for (op_index=0; types[op_index]; op_index++, code_index++) {
13256 VALUE op = orig_code[code_index];
13259 switch (types[op_index]) {
13262 wv = ibf_dump_object(dump, op);
13271 wv = ibf_dump_object(dump, arr);
13279 wv = is - ISEQ_IS_ENTRY_START(body, types[op_index]);
13287 wv = ibf_dump_id(dump, (
ID)op);
13299 ibf_dump_write_small_value(dump, wv);
13309ibf_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)
13312 unsigned int code_index;
13313 ibf_offset_t reading_pos = bytecode_offset;
13317 struct rb_call_data *cd_entries = load_body->call_data;
13320 load_body->iseq_encoded = code;
13321 load_body->iseq_size = iseq_size;
13323 iseq_bits_t * mark_offset_bits;
13324 if (ISEQ_MBITS_BUFLEN(iseq_size) == 1) {
13325 load_body->mark_bits.single = 0;
13326 mark_offset_bits = &load_body->mark_bits.single;
13329 load_body->mark_bits.list =
ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(iseq_size));
13330 mark_offset_bits = load_body->mark_bits.list;
13332 bool needs_bitmap =
false;
13334 for (code_index=0; code_index<iseq_size;) {
13336 const VALUE insn = code[code_index] = ibf_load_small_value(load, &reading_pos);
13337 const char *types = insn_op_types(insn);
13343 for (op_index=0; types[op_index]; op_index++, code_index++) {
13344 const char operand_type = types[op_index];
13345 switch (operand_type) {
13348 VALUE op = ibf_load_small_value(load, &reading_pos);
13349 VALUE v = ibf_load_object(load, op);
13350 code[code_index] = v;
13353 ISEQ_MBITS_SET(mark_offset_bits, code_index);
13354 needs_bitmap =
true;
13360 VALUE op = ibf_load_small_value(load, &reading_pos);
13361 VALUE v = ibf_load_object(load, op);
13366 pinned_list_store(load->current_buffer->obj_list, (
long)op, v);
13368 code[code_index] = v;
13369 ISEQ_MBITS_SET(mark_offset_bits, code_index);
13371 needs_bitmap =
true;
13376 VALUE op = (
VALUE)ibf_load_small_value(load, &reading_pos);
13378 code[code_index] = v;
13381 ISEQ_MBITS_SET(mark_offset_bits, code_index);
13382 needs_bitmap =
true;
13388 VALUE op = ibf_load_small_value(load, &reading_pos);
13389 VALUE arr = ibf_load_object(load, op);
13391 IC ic = &ISEQ_IS_IC_ENTRY(load_body, ic_index++);
13392 ic->
segments = array_to_idlist(arr);
13394 code[code_index] = (
VALUE)ic;
13401 unsigned int op = (
unsigned int)ibf_load_small_value(load, &reading_pos);
13403 ISE ic = ISEQ_IS_ENTRY_START(load_body, operand_type) + op;
13404 code[code_index] = (
VALUE)ic;
13406 if (operand_type == TS_IVC) {
13409 if (insn == BIN(setinstancevariable)) {
13410 ID iv_name = (
ID)code[code_index - 1];
13411 cache->iv_set_name = iv_name;
13412 cache->value = IVAR_CACHE_INIT;
13415 cache->iv_set_name = 0;
13416 cache->value = rb_getivar_cache_pack(ROOT_SHAPE_ID, ATTR_INDEX_NOT_SET);
13424 code[code_index] = (
VALUE)cd_entries++;
13429 VALUE op = ibf_load_small_value(load, &reading_pos);
13430 code[code_index] = ibf_load_id(load, (
ID)(
VALUE)op);
13437 code[code_index] = (
VALUE)ibf_load_builtin(load, &reading_pos);
13440 code[code_index] = ibf_load_small_value(load, &reading_pos);
13444 if (insn_len(insn) != op_index+1) {
13449 if (!needs_bitmap) {
13450 SIZED_FREE_N(load_body->mark_bits.list, ISEQ_MBITS_BUFLEN(iseq_size));
13451 load_body->mark_bits.list = NULL;
13455 RUBY_ASSERT(reading_pos == bytecode_offset + bytecode_size);
13462 int opt_num = ISEQ_BODY(iseq)->param.opt_num;
13465 IBF_W_ALIGN(
VALUE);
13466 return ibf_dump_write(dump, ISEQ_BODY(iseq)->param.opt_table,
sizeof(
VALUE) * (opt_num + 1));
13469 return ibf_dump_pos(dump);
13474ibf_load_param_opt_table(
const struct ibf_load *load, ibf_offset_t opt_table_offset,
int opt_num)
13478 MEMCPY(table, load->current_buffer->buff + opt_table_offset,
VALUE, opt_num+1);
13489 const struct rb_iseq_param_keyword *kw = ISEQ_BODY(iseq)->param.keyword;
13492 struct rb_iseq_param_keyword dump_kw = *kw;
13493 int dv_num = kw->num - kw->required_num;
13498 for (i=0; i<kw->num; i++) ids[i] = (
ID)ibf_dump_id(dump, kw->table[i]);
13499 for (i=0; i<dv_num; i++) dvs[i] = (
VALUE)ibf_dump_object(dump, kw->default_values[i]);
13501 dump_kw.table = IBF_W(ids,
ID, kw->num);
13502 dump_kw.default_values = IBF_W(dvs,
VALUE, dv_num);
13503 IBF_W_ALIGN(
struct rb_iseq_param_keyword);
13504 return ibf_dump_write(dump, &dump_kw,
sizeof(
struct rb_iseq_param_keyword) * 1);
13511static const struct rb_iseq_param_keyword *
13512ibf_load_param_keyword(
const struct ibf_load *load, ibf_offset_t param_keyword_offset)
13514 if (param_keyword_offset) {
13515 struct rb_iseq_param_keyword *kw = IBF_R(param_keyword_offset,
struct rb_iseq_param_keyword, 1);
13516 int dv_num = kw->num - kw->required_num;
13517 VALUE *dvs = dv_num ? IBF_R(kw->default_values,
VALUE, dv_num) : NULL;
13520 for (i=0; i<dv_num; i++) {
13521 dvs[i] = ibf_load_object(load, dvs[i]);
13527 kw->default_values = dvs;
13538 ibf_offset_t offset = ibf_dump_pos(dump);
13542#ifdef USE_ISEQ_NODE_ID
13543 ibf_dump_write_small_value(dump, body->insns_info.node_ids_size);
13546 for (i = 0; i < body->insns_info.size; i++) {
13547 ibf_dump_write_small_value(dump, entries[i].line_no);
13548 ibf_dump_write_small_value(dump, entries[i].events);
13550#ifdef USE_ISEQ_NODE_ID
13551 if (body->insns_info.node_ids_size > 0) {
13552 ibf_dump_write(dump, body->insns_info.node_ids, body->insns_info.node_ids_size);
13560ibf_load_insns_info_body(
const struct ibf_load *load, ibf_offset_t body_offset,
unsigned int size,
13563 ibf_offset_t reading_pos = body_offset;
13566#ifdef USE_ISEQ_NODE_ID
13567 const unsigned int node_ids_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
13570 for (i = 0; i < size; i++) {
13571 entries[i].line_no = (int)ibf_load_small_value(load, &reading_pos);
13572 entries[i].events = (
rb_event_flag_t)ibf_load_small_value(load, &reading_pos);
13574#ifdef USE_ISEQ_NODE_ID
13575 if (node_ids_size > 0) {
13576 if (node_ids_size > load->current_buffer->size - reading_pos) {
13579 uint8_t *node_ids =
ALLOC_N(uint8_t, node_ids_size);
13580 memcpy(node_ids, load->current_buffer->buff + reading_pos, node_ids_size);
13581 load_body->insns_info.node_ids = node_ids;
13582 load_body->insns_info.node_ids_size = node_ids_size;
13585 load_body->insns_info.body = entries;
13589ibf_dump_insns_info_positions(
struct ibf_dump *dump,
const unsigned int *positions,
unsigned int size)
13591 ibf_offset_t offset = ibf_dump_pos(dump);
13593 unsigned int last = 0;
13595 for (i = 0; i < size; i++) {
13596 ibf_dump_write_small_value(dump, positions[i] - last);
13597 last = positions[i];
13603static unsigned int *
13604ibf_load_insns_info_positions(
const struct ibf_load *load, ibf_offset_t positions_offset,
unsigned int size)
13606 ibf_offset_t reading_pos = positions_offset;
13607 unsigned int *positions =
ALLOC_N(
unsigned int, size);
13609 unsigned int last = 0;
13611 for (i = 0; i < size; i++) {
13612 positions[i] = last + (
unsigned int)ibf_load_small_value(load, &reading_pos);
13613 last = positions[i];
13623 const int size = body->local_table_size;
13627 for (i=0; i<size; i++) {
13628 VALUE v = ibf_dump_id(dump, body->local_table[i]);
13631 v = ibf_dump_object(dump,
ULONG2NUM(body->local_table[i]));
13637 return ibf_dump_write(dump, table,
sizeof(
ID) * size);
13641ibf_load_local_table(
const struct ibf_load *load, ibf_offset_t local_table_offset,
int size)
13644 ID *table = IBF_R(local_table_offset,
ID, size);
13647 for (i=0; i<size; i++) {
13648 table[i] = ibf_load_id(load, table[i]);
13651 if (size == 1 && table[0] == idERROR_INFO) {
13652 ruby_xfree_sized(table,
sizeof(
ID) * size);
13653 return rb_iseq_shared_exc_local_tbl;
13668 const int size = ISEQ_LVAR_STATES_BUFLEN(body->local_table_size);
13669 IBF_W_ALIGN(uint8_t);
13670 if (iseq_has_lvar_states_p(body)) {
13671 return ibf_dump_write(dump, iseq_lvar_states(body),
sizeof(uint8_t) * size);
13674 return ibf_dump_write(dump, NULL, 0);
13679ibf_load_lvar_states(
const struct ibf_load *load,
struct rb_iseq_constant_body *load_body, ibf_offset_t lvar_states_offset,
int size,
const ID *local_table)
13681 if (local_table == rb_iseq_shared_exc_local_tbl ||
13683 load_body->lvar_states.list = NULL;
13685 else if (ISEQ_LVAR_STATES_EMBED_P((
unsigned int)size)) {
13686 ibf_offset_t pos = lvar_states_offset;
13687 const int len =
sizeof(uint8_t) * ISEQ_LVAR_STATES_BUFLEN(size);
13688 memcpy(load_body->lvar_states.single, ibf_load_ptr(load, &pos,
len),
len);
13691 load_body->lvar_states.list = IBF_R(lvar_states_offset, uint8_t, ISEQ_LVAR_STATES_BUFLEN(size));
13701 int *iseq_indices =
ALLOCA_N(
int, table->size);
13704 for (i=0; i<table->size; i++) {
13705 iseq_indices[i] = ibf_dump_iseq(dump, table->entries[i].iseq);
13708 const ibf_offset_t offset = ibf_dump_pos(dump);
13710 for (i=0; i<table->size; i++) {
13711 ibf_dump_write_small_value(dump, iseq_indices[i]);
13712 ibf_dump_write_small_value(dump, table->entries[i].type);
13713 ibf_dump_write_small_value(dump, table->entries[i].start);
13714 ibf_dump_write_small_value(dump, table->entries[i].end);
13715 ibf_dump_write_small_value(dump, table->entries[i].cont);
13716 ibf_dump_write_small_value(dump, table->entries[i].sp);
13721 return ibf_dump_pos(dump);
13726ibf_load_catch_table(
const struct ibf_load *load, ibf_offset_t catch_table_offset,
unsigned int size,
const rb_iseq_t *parent_iseq)
13729 struct iseq_catch_table *table = ruby_xcalloc(1, iseq_catch_table_bytes(size));
13730 table->size = size;
13731 ISEQ_BODY(parent_iseq)->catch_table = table;
13733 ibf_offset_t reading_pos = catch_table_offset;
13736 for (i=0; i<table->size; i++) {
13737 int iseq_index = (int)ibf_load_small_value(load, &reading_pos);
13738 table->entries[i].type = (
enum rb_catch_type)ibf_load_small_value(load, &reading_pos);
13739 table->entries[i].start = (
unsigned int)ibf_load_small_value(load, &reading_pos);
13740 table->entries[i].end = (
unsigned int)ibf_load_small_value(load, &reading_pos);
13741 table->entries[i].cont = (
unsigned int)ibf_load_small_value(load, &reading_pos);
13742 table->entries[i].sp = (
unsigned int)ibf_load_small_value(load, &reading_pos);
13745 RB_OBJ_WRITE(parent_iseq, UNALIGNED_MEMBER_PTR(&table->entries[i], iseq), catch_iseq);
13749 ISEQ_BODY(parent_iseq)->catch_table = NULL;
13757 const unsigned int ci_size = body->ci_size;
13760 ibf_offset_t offset = ibf_dump_pos(dump);
13764 for (i = 0; i < ci_size; i++) {
13767 ibf_dump_write_small_value(dump, ibf_dump_id(dump, vm_ci_mid(ci)));
13768 ibf_dump_write_small_value(dump, vm_ci_flag(ci));
13769 ibf_dump_write_small_value(dump, vm_ci_argc(ci));
13773 int len = kwarg->keyword_len;
13774 ibf_dump_write_small_value(dump,
len);
13775 for (
int j=0; j<
len; j++) {
13776 VALUE keyword = ibf_dump_object(dump, kwarg->keywords[j]);
13777 ibf_dump_write_small_value(dump, keyword);
13781 ibf_dump_write_small_value(dump, 0);
13786 ibf_dump_write_small_value(dump, (
VALUE)-1);
13804static enum rb_id_table_iterator_result
13805store_outer_variable(
ID id,
VALUE val,
void *dump)
13810 pair->name = rb_id2str(
id);
13812 return ID_TABLE_CONTINUE;
13816outer_variable_cmp(
const void *a,
const void *b,
void *arg)
13824 else if (!bp->name) {
13834 struct rb_id_table * ovs = ISEQ_BODY(iseq)->outer_variables;
13836 ibf_offset_t offset = ibf_dump_pos(dump);
13838 size_t size = ovs ? rb_id_table_size(ovs) : 0;
13839 ibf_dump_write_small_value(dump, (
VALUE)size);
13848 rb_id_table_foreach(ovs, store_outer_variable, ovlist);
13850 for (
size_t i = 0; i < size; ++i) {
13851 ID id = ovlist->pairs[i].id;
13852 ID val = ovlist->pairs[i].val;
13853 ibf_dump_write_small_value(dump, ibf_dump_id(dump,
id));
13854 ibf_dump_write_small_value(dump, val);
13864ibf_load_ci_entries(
const struct ibf_load *load,
13865 ibf_offset_t ci_entries_offset,
13866 unsigned int ci_size,
13874 ibf_offset_t reading_pos = ci_entries_offset;
13881 for (i = 0; i < ci_size; i++) {
13882 VALUE mid_index = ibf_load_small_value(load, &reading_pos);
13883 if (mid_index != (
VALUE)-1) {
13884 ID mid = ibf_load_id(load, mid_index);
13885 unsigned int flag = (
unsigned int)ibf_load_small_value(load, &reading_pos);
13886 unsigned int argc = (
unsigned int)ibf_load_small_value(load, &reading_pos);
13889 int kwlen = (int)ibf_load_small_value(load, &reading_pos);
13892 kwarg->references = 0;
13893 kwarg->keyword_len = kwlen;
13894 for (
int j=0; j<kwlen; j++) {
13895 VALUE keyword = ibf_load_small_value(load, &reading_pos);
13896 kwarg->keywords[j] = ibf_load_object(load, keyword);
13900 cds[i].ci = vm_ci_new(mid, flag, argc, kwarg);
13902 cds[i].cc = vm_cc_empty();
13913ibf_load_outer_variables(
const struct ibf_load * load, ibf_offset_t outer_variables_offset)
13915 ibf_offset_t reading_pos = outer_variables_offset;
13919 size_t table_size = (size_t)ibf_load_small_value(load, &reading_pos);
13921 if (table_size > 0) {
13922 tbl = rb_id_table_create(table_size);
13925 for (
size_t i = 0; i < table_size; i++) {
13926 ID key = ibf_load_id(load, (
ID)ibf_load_small_value(load, &reading_pos));
13927 VALUE value = ibf_load_small_value(load, &reading_pos);
13928 if (!key) key = rb_make_temporary_id(i);
13929 rb_id_table_insert(tbl, key, value);
13938 RUBY_ASSERT(dump->current_buffer == &dump->global_buffer);
13940 unsigned int *positions;
13944 const VALUE location_pathobj_index = ibf_dump_object(dump, body->location.pathobj);
13945 const VALUE location_label_index = ibf_dump_object(dump, body->location.label);
13947#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
13948 ibf_offset_t iseq_start = ibf_dump_pos(dump);
13953 buffer.obj_table = ibf_dump_object_table_new();
13954 dump->current_buffer = &buffer;
13957 const ibf_offset_t bytecode_offset = ibf_dump_code(dump, iseq);
13958 const ibf_offset_t bytecode_size = ibf_dump_pos(dump) - bytecode_offset;
13959 const ibf_offset_t param_opt_table_offset = ibf_dump_param_opt_table(dump, iseq);
13960 const ibf_offset_t param_keyword_offset = ibf_dump_param_keyword(dump, iseq);
13961 const ibf_offset_t insns_info_body_offset = ibf_dump_insns_info_body(dump, iseq);
13963 positions = rb_iseq_insns_info_decode_positions(ISEQ_BODY(iseq));
13964 const ibf_offset_t insns_info_positions_offset = ibf_dump_insns_info_positions(dump, positions, body->insns_info.size);
13965 SIZED_FREE_N(positions, ISEQ_BODY(iseq)->insns_info.size);
13967 const ibf_offset_t local_table_offset = ibf_dump_local_table(dump, iseq);
13968 const ibf_offset_t lvar_states_offset = ibf_dump_lvar_states(dump, iseq);
13969 const unsigned int catch_table_size = body->catch_table ? body->catch_table->size : 0;
13970 const ibf_offset_t catch_table_offset = ibf_dump_catch_table(dump, iseq);
13972 const int parent_iseq_index = ibf_table_lookup(dump->iseq_table, (st_data_t)ISEQ_BODY(iseq)->parent_iseq);
13973 const int local_iseq_index = ibf_table_lookup(dump->iseq_table, (st_data_t)ISEQ_BODY(iseq)->local_iseq);
13974 const int mandatory_only_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->mandatory_only_iseq);
13975 const ibf_offset_t ci_entries_offset = ibf_dump_ci_entries(dump, iseq);
13976 const ibf_offset_t outer_variables_offset = ibf_dump_outer_variables(dump, iseq);
13978#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
13979 ibf_offset_t local_obj_list_offset;
13980 unsigned int local_obj_list_size;
13982 ibf_dump_object_list(dump, &local_obj_list_offset, &local_obj_list_size);
13985 ibf_offset_t body_offset = ibf_dump_pos(dump);
13988 unsigned int param_flags =
13989 (body->param.flags.has_lead << 0) |
13990 (body->param.flags.has_opt << 1) |
13991 (body->param.flags.has_rest << 2) |
13992 (body->param.flags.has_post << 3) |
13993 (body->param.flags.has_kw << 4) |
13994 (body->param.flags.has_kwrest << 5) |
13995 (body->param.flags.has_block << 6) |
13996 (body->param.flags.ambiguous_param0 << 7) |
13997 (body->param.flags.accepts_no_kwarg << 8) |
13998 (body->param.flags.ruby2_keywords << 9) |
13999 (body->param.flags.anon_rest << 10) |
14000 (body->param.flags.anon_kwrest << 11) |
14001 (body->param.flags.use_block << 12) |
14002 (body->param.flags.forwardable << 13) |
14003 (body->param.flags.accepts_no_block << 14);
14005#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
14006# define IBF_BODY_OFFSET(x) (x)
14008# define IBF_BODY_OFFSET(x) (body_offset - (x))
14011 ibf_dump_write_small_value(dump, body->type);
14012 ibf_dump_write_small_value(dump, body->iseq_size);
14013 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(bytecode_offset));
14014 ibf_dump_write_small_value(dump, bytecode_size);
14015 ibf_dump_write_small_value(dump, param_flags);
14016 ibf_dump_write_small_value(dump, body->param.size);
14017 ibf_dump_write_small_value(dump, body->param.lead_num);
14018 ibf_dump_write_small_value(dump, body->param.opt_num);
14019 ibf_dump_write_small_value(dump, body->param.rest_start);
14020 ibf_dump_write_small_value(dump, body->param.post_start);
14021 ibf_dump_write_small_value(dump, body->param.post_num);
14022 ibf_dump_write_small_value(dump, body->param.block_start);
14023 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(param_opt_table_offset));
14024 ibf_dump_write_small_value(dump, param_keyword_offset);
14025 ibf_dump_write_small_value(dump, location_pathobj_index);
14026 ibf_dump_write_small_value(dump, body->no_realpath);
14027 ibf_dump_write_small_value(dump, location_label_index);
14028 ibf_dump_write_small_value(dump, body->location.first_lineno);
14029 ibf_dump_write_small_value(dump, body->location.node_id);
14032 ibf_dump_write_small_value(dump, (
VALUE)(uint32_t)(body->source_hash >> 32));
14033 ibf_dump_write_small_value(dump, (
VALUE)(uint32_t)body->source_hash);
14034 ibf_dump_write_small_value(dump, body->location.code_location.beg_pos.lineno);
14035 ibf_dump_write_small_value(dump, body->location.code_location.beg_pos.column);
14036 ibf_dump_write_small_value(dump, body->location.code_location.end_pos.lineno);
14037 ibf_dump_write_small_value(dump, body->location.code_location.end_pos.column);
14038 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(insns_info_body_offset));
14039 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(insns_info_positions_offset));
14040 ibf_dump_write_small_value(dump, body->insns_info.size);
14041 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(local_table_offset));
14042 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(lvar_states_offset));
14043 ibf_dump_write_small_value(dump, catch_table_size);
14044 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(catch_table_offset));
14045 ibf_dump_write_small_value(dump, parent_iseq_index);
14046 ibf_dump_write_small_value(dump, local_iseq_index);
14047 ibf_dump_write_small_value(dump, mandatory_only_iseq_index);
14048 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(ci_entries_offset));
14049 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(outer_variables_offset));
14050 ibf_dump_write_small_value(dump, ISEQ_FLIP_CNT(iseq));
14051 ibf_dump_write_small_value(dump, body->local_table_size);
14052 ibf_dump_write_small_value(dump, body->ivc_size);
14053 ibf_dump_write_small_value(dump, body->icvarc_size);
14054 ibf_dump_write_small_value(dump, body->ise_size);
14055 ibf_dump_write_small_value(dump, body->ic_size);
14056 ibf_dump_write_small_value(dump, body->ci_size);
14057 ibf_dump_write_small_value(dump, body->stack_max);
14058 ibf_dump_write_small_value(dump, body->builtin_attrs);
14059 ibf_dump_write_small_value(dump, body->prism ? 1 : 0);
14061#undef IBF_BODY_OFFSET
14063#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
14064 ibf_offset_t iseq_length_bytes = ibf_dump_pos(dump);
14066 dump->current_buffer = saved_buffer;
14067 ibf_dump_write(dump, RSTRING_PTR(buffer.str), iseq_length_bytes);
14069 ibf_offset_t offset = ibf_dump_pos(dump);
14070 ibf_dump_write_small_value(dump, iseq_start);
14071 ibf_dump_write_small_value(dump, iseq_length_bytes);
14072 ibf_dump_write_small_value(dump, body_offset);
14074 ibf_dump_write_small_value(dump, local_obj_list_offset);
14075 ibf_dump_write_small_value(dump, local_obj_list_size);
14077 st_free_table(buffer.obj_table);
14081 return body_offset;
14086ibf_load_location_str(
const struct ibf_load *load,
VALUE str_index)
14088 VALUE str = ibf_load_object(load, str_index);
14090 str = rb_fstring(str);
14100 ibf_offset_t reading_pos = offset;
14102#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
14104 load->current_buffer = &load->global_buffer;
14106 const ibf_offset_t iseq_start = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
14107 const ibf_offset_t iseq_length_bytes = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
14108 const ibf_offset_t body_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
14111 buffer.buff = load->global_buffer.buff + iseq_start;
14112 buffer.size = iseq_length_bytes;
14113 buffer.obj_list_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
14114 buffer.obj_list_size = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
14115 buffer.obj_list = pinned_list_new(buffer.obj_list_size);
14117 load->current_buffer = &buffer;
14118 reading_pos = body_offset;
14121#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
14122# define IBF_BODY_OFFSET(x) (x)
14124# define IBF_BODY_OFFSET(x) (offset - (x))
14127 const unsigned int type = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14128 const unsigned int iseq_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14129 const ibf_offset_t bytecode_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14130 const ibf_offset_t bytecode_size = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
14131 const unsigned int param_flags = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14132 const unsigned int param_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14133 const int param_lead_num = (int)ibf_load_small_value(load, &reading_pos);
14134 const int param_opt_num = (int)ibf_load_small_value(load, &reading_pos);
14135 const int param_rest_start = (int)ibf_load_small_value(load, &reading_pos);
14136 const int param_post_start = (int)ibf_load_small_value(load, &reading_pos);
14137 const int param_post_num = (int)ibf_load_small_value(load, &reading_pos);
14138 const int param_block_start = (int)ibf_load_small_value(load, &reading_pos);
14139 const ibf_offset_t param_opt_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14140 const ibf_offset_t param_keyword_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
14141 const VALUE location_pathobj_index = ibf_load_small_value(load, &reading_pos);
14142 const bool no_realpath = (bool)ibf_load_small_value(load, &reading_pos);
14143 const VALUE location_label_index = ibf_load_small_value(load, &reading_pos);
14144 const int location_first_lineno = (int)ibf_load_small_value(load, &reading_pos);
14145 const int location_node_id = (int)ibf_load_small_value(load, &reading_pos);
14146 const uint64_t source_hash_hi = (uint64_t)ibf_load_small_value(load, &reading_pos);
14147 const uint64_t source_hash_lo = (uint64_t)ibf_load_small_value(load, &reading_pos);
14148 const uint64_t source_hash = (source_hash_hi << 32) | (uint32_t)source_hash_lo;
14149 const int location_code_location_beg_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
14150 const int location_code_location_beg_pos_column = (int)ibf_load_small_value(load, &reading_pos);
14151 const int location_code_location_end_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
14152 const int location_code_location_end_pos_column = (int)ibf_load_small_value(load, &reading_pos);
14153 const ibf_offset_t insns_info_body_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14154 const ibf_offset_t insns_info_positions_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14155 const unsigned int insns_info_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14156 const ibf_offset_t local_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14157 const ibf_offset_t lvar_states_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14158 const unsigned int catch_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14159 const ibf_offset_t catch_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14160 const int parent_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
14161 const int local_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
14162 const int mandatory_only_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
14163 const ibf_offset_t ci_entries_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14164 const ibf_offset_t outer_variables_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
14165 const rb_snum_t variable_flip_count = (rb_snum_t)ibf_load_small_value(load, &reading_pos);
14166 const unsigned int local_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14168 const unsigned int ivc_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14169 const unsigned int icvarc_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14170 const unsigned int ise_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14171 const unsigned int ic_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14173 const unsigned int ci_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14174 const unsigned int stack_max = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14175 const unsigned int builtin_attrs = (
unsigned int)ibf_load_small_value(load, &reading_pos);
14176 const bool prism = (bool)ibf_load_small_value(load, &reading_pos);
14179 VALUE path = ibf_load_object(load, location_pathobj_index);
14184 path = rb_fstring(path);
14185 realpath = no_realpath ?
Qnil : path;
14188 VALUE pathobj = path;
14194 if (!
NIL_P(realpath)) {
14196 rb_raise(rb_eArgError,
"unexpected realpath %"PRIxVALUE
14197 "(%x), path=%+"PRIsVALUE,
14198 realpath,
TYPE(realpath), path);
14200 realpath = rb_fstring(realpath);
14206 rb_iseq_pathobj_set(iseq, path, realpath);
14211 VALUE dummy_frame = rb_vm_push_frame_fname(ec, path);
14213#undef IBF_BODY_OFFSET
14215 load_body->type =
type;
14216 load_body->stack_max = stack_max;
14217 load_body->param.flags.has_lead = (param_flags >> 0) & 1;
14218 load_body->param.flags.has_opt = (param_flags >> 1) & 1;
14219 load_body->param.flags.has_rest = (param_flags >> 2) & 1;
14220 load_body->param.flags.has_post = (param_flags >> 3) & 1;
14221 load_body->param.flags.has_kw = FALSE;
14222 load_body->param.flags.has_kwrest = (param_flags >> 5) & 1;
14223 load_body->param.flags.has_block = (param_flags >> 6) & 1;
14224 load_body->param.flags.ambiguous_param0 = (param_flags >> 7) & 1;
14225 load_body->param.flags.accepts_no_kwarg = (param_flags >> 8) & 1;
14226 load_body->param.flags.ruby2_keywords = (param_flags >> 9) & 1;
14227 load_body->param.flags.anon_rest = (param_flags >> 10) & 1;
14228 load_body->param.flags.anon_kwrest = (param_flags >> 11) & 1;
14229 load_body->param.flags.use_block = (param_flags >> 12) & 1;
14230 load_body->param.flags.forwardable = (param_flags >> 13) & 1;
14231 load_body->param.flags.accepts_no_block = (param_flags >> 14) & 1;
14232 load_body->param.size = param_size;
14233 load_body->param.lead_num = param_lead_num;
14234 load_body->param.opt_num = param_opt_num;
14235 load_body->param.rest_start = param_rest_start;
14236 load_body->param.post_start = param_post_start;
14237 load_body->param.post_num = param_post_num;
14238 load_body->param.block_start = param_block_start;
14239 load_body->local_table_size = local_table_size;
14240 load_body->ci_size = ci_size;
14241 load_body->insns_info.size = insns_info_size;
14244 ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
14245 if (variable_flip_count) {
14247 v->flip_count = variable_flip_count;
14250 load_body->location.first_lineno = location_first_lineno;
14251 load_body->location.node_id = location_node_id;
14252 load_body->source_hash = source_hash;
14253 load_body->location.code_location.beg_pos.lineno = location_code_location_beg_pos_lineno;
14254 load_body->location.code_location.beg_pos.column = location_code_location_beg_pos_column;
14255 load_body->location.code_location.end_pos.lineno = location_code_location_end_pos_lineno;
14256 load_body->location.code_location.end_pos.column = location_code_location_end_pos_column;
14257 load_body->builtin_attrs = builtin_attrs;
14258 load_body->prism = prism;
14260 load_body->ivc_size = ivc_size;
14261 load_body->icvarc_size = icvarc_size;
14262 load_body->ise_size = ise_size;
14263 load_body->ic_size = ic_size;
14265 if (ISEQ_IS_SIZE(load_body)) {
14269 load_body->is_entries = NULL;
14271 ibf_load_ci_entries(load, ci_entries_offset, ci_size, &load_body->call_data);
14272 load_body->outer_variables = ibf_load_outer_variables(load, outer_variables_offset);
14273 load_body->param.opt_table = ibf_load_param_opt_table(load, param_opt_table_offset, param_opt_num);
14274 load_body->param.keyword = ibf_load_param_keyword(load, param_keyword_offset);
14275 load_body->param.flags.has_kw = (param_flags >> 4) & 1;
14276 ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size, load_body);
14277 load_body->insns_info.positions_or_succ_index_table.positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size);
14278 load_body->local_table = ibf_load_local_table(load, local_table_offset, local_table_size);
14279 ibf_load_lvar_states(load, load_body, lvar_states_offset, local_table_size, load_body->local_table);
14280 ibf_load_catch_table(load, catch_table_offset, catch_table_size, iseq);
14284 const rb_iseq_t *mandatory_only_iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)mandatory_only_iseq_index);
14286 RB_OBJ_WRITE(iseq, &load_body->parent_iseq, parent_iseq);
14287 RB_OBJ_WRITE(iseq, &load_body->local_iseq, local_iseq);
14288 RB_OBJ_WRITE(iseq, &load_body->mandatory_only_iseq, mandatory_only_iseq);
14291 if (load_body->param.keyword != NULL) {
14293 struct rb_iseq_param_keyword *keyword = (
struct rb_iseq_param_keyword *) load_body->param.keyword;
14294 keyword->table = &load_body->local_table[keyword->bits_start - keyword->num];
14297 ibf_load_code(load, iseq, bytecode_offset, bytecode_size, iseq_size);
14298#if VM_INSN_INFO_TABLE_IMPL == 2
14299 rb_iseq_insns_info_encode_positions(iseq);
14302 rb_iseq_translate_threaded_code(iseq);
14304#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
14305 load->current_buffer = &load->global_buffer;
14308 RB_OBJ_WRITE(iseq, &load_body->location.label, ibf_load_location_str(load, location_label_index));
14310#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
14311 load->current_buffer = saved_buffer;
14313 verify_call_cache(iseq);
14316 rb_vm_pop_frame_no_int(ec);
14326ibf_dump_iseq_list_i(st_data_t key, st_data_t val, st_data_t ptr)
14331 ibf_offset_t offset = ibf_dump_iseq_each(args->dump, iseq);
14334 return ST_CONTINUE;
14344 args.offset_list = offset_list;
14346 st_foreach(dump->iseq_table, ibf_dump_iseq_list_i, (st_data_t)&args);
14349 st_index_t size = dump->iseq_table->num_entries;
14350 ibf_offset_t *offsets =
ALLOCA_N(ibf_offset_t, size);
14352 for (i = 0; i < size; i++) {
14356 ibf_dump_align(dump,
sizeof(ibf_offset_t));
14357 header->iseq_list_offset = ibf_dump_write(dump, offsets,
sizeof(ibf_offset_t) * size);
14358 header->iseq_list_size = (
unsigned int)size;
14368 unsigned int type: 5;
14369 unsigned int special_const: 1;
14370 unsigned int frozen: 1;
14371 unsigned int internal: 1;
14374enum ibf_object_class_index {
14375 IBF_OBJECT_CLASS_OBJECT,
14376 IBF_OBJECT_CLASS_ARRAY,
14377 IBF_OBJECT_CLASS_STANDARD_ERROR,
14378 IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR,
14379 IBF_OBJECT_CLASS_TYPE_ERROR,
14380 IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR,
14390 long keyval[FLEX_ARY_LEN];
14403 BDIGIT digits[FLEX_ARY_LEN];
14406enum ibf_object_data_type {
14407 IBF_OBJECT_DATA_ENCODING,
14418#define IBF_ALIGNED_OFFSET(align, offset) \
14419 ((((offset) - 1) / (align) + 1) * (align))
14424#define IBF_OBJBODY(type, offset) \
14425 ibf_load_check_offset(load, IBF_ALIGNED_OFFSET(RUBY_ALIGNOF(type), offset))
14428ibf_load_check_offset(
const struct ibf_load *load,
size_t offset)
14430 if (offset >= load->current_buffer->size) {
14431 rb_raise(
rb_eIndexError,
"object offset out of range: %"PRIdSIZE, offset);
14433 return load->current_buffer->buff + offset;
14436NORETURN(
static void ibf_dump_object_unsupported(
struct ibf_dump *dump,
VALUE obj));
14439ibf_dump_object_unsupported(
struct ibf_dump *dump,
VALUE obj)
14442 rb_raw_obj_info(buff,
sizeof(buff), obj);
14451 rb_raise(rb_eArgError,
"unsupported");
14458 enum ibf_object_class_index cindex;
14460 cindex = IBF_OBJECT_CLASS_OBJECT;
14463 cindex = IBF_OBJECT_CLASS_ARRAY;
14466 cindex = IBF_OBJECT_CLASS_STANDARD_ERROR;
14469 cindex = IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR;
14472 cindex = IBF_OBJECT_CLASS_TYPE_ERROR;
14475 cindex = IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR;
14478 rb_obj_info_dump(obj);
14480 rb_bug(
"unsupported class");
14482 ibf_dump_write_small_value(dump, (
VALUE)cindex);
14488 enum ibf_object_class_index cindex = (
enum ibf_object_class_index)ibf_load_small_value(load, &offset);
14491 case IBF_OBJECT_CLASS_OBJECT:
14493 case IBF_OBJECT_CLASS_ARRAY:
14495 case IBF_OBJECT_CLASS_STANDARD_ERROR:
14497 case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR:
14499 case IBF_OBJECT_CLASS_TYPE_ERROR:
14501 case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR:
14505 rb_raise(rb_eArgError,
"ibf_load_object_class: unknown class (%d)", (
int)cindex);
14513 (void)IBF_W(&dbl,
double, 1);
14521 memcpy(&d, IBF_OBJBODY(
double, offset),
sizeof(d));
14530 long encindex = (long)rb_enc_get_index(obj);
14532 const char *ptr = RSTRING_PTR(obj);
14534 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
14535 rb_encoding *enc = rb_enc_from_index((
int)encindex);
14536 const char *enc_name = rb_enc_name(enc);
14537 encindex = RUBY_ENCINDEX_BUILTIN_MAX + ibf_dump_object(dump,
rb_str_new2(enc_name));
14540 ibf_dump_write_small_value(dump, encindex);
14541 ibf_dump_write_small_value(dump,
len);
14542 IBF_WP(ptr,
char,
len);
14548 ibf_offset_t reading_pos = offset;
14550 int encindex = (int)ibf_load_small_value(load, &reading_pos);
14552 const char *ptr = load->current_buffer->buff + reading_pos;
14554 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
14555 VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX);
14556 encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str));
14560 if (header->frozen && !header->internal) {
14561 str = rb_enc_literal_str(ptr,
len, rb_enc_from_index(encindex));
14564 str = rb_enc_str_new(ptr,
len, rb_enc_from_index(encindex));
14567 if (header->frozen) str = rb_fstring(str);
14578 regexp.srcstr = (long)ibf_dump_object(dump, srcstr);
14580 ibf_dump_write_byte(dump, (
unsigned char)regexp.option);
14581 ibf_dump_write_small_value(dump, regexp.srcstr);
14588 regexp.option = ibf_load_byte(load, &offset);
14589 regexp.srcstr = ibf_load_small_value(load, &offset);
14591 VALUE srcstr = ibf_load_object(load, regexp.srcstr);
14592 VALUE reg = rb_reg_compile(srcstr, (
int)regexp.option, NULL, 0);
14604 ibf_dump_write_small_value(dump,
len);
14605 for (i=0; i<
len; i++) {
14606 long index = (long)ibf_dump_object(dump,
RARRAY_AREF(obj, i));
14607 ibf_dump_write_small_value(dump, index);
14614 ibf_offset_t reading_pos = offset;
14621 for (i=0; i<
len; i++) {
14622 const VALUE index = ibf_load_small_value(load, &reading_pos);
14626 if (header->frozen) {
14635ibf_dump_object_hash_i(st_data_t key, st_data_t val, st_data_t ptr)
14639 VALUE key_index = ibf_dump_object(dump, (
VALUE)key);
14640 VALUE val_index = ibf_dump_object(dump, (
VALUE)val);
14642 ibf_dump_write_small_value(dump, key_index);
14643 ibf_dump_write_small_value(dump, val_index);
14644 return ST_CONTINUE;
14651 ibf_dump_write_small_value(dump, (
VALUE)
len);
14659 long len = (long)ibf_load_small_value(load, &offset);
14660 VALUE obj = header->frozen ? rb_hash_alloc_fixed_size(
rb_cHash,
len) : rb_hash_new_capa(
len);
14663 for (i = 0; i <
len; i++) {
14664 VALUE key_index = ibf_load_small_value(load, &offset);
14665 VALUE val_index = ibf_load_small_value(load, &offset);
14667 VALUE key = ibf_load_object(load, key_index);
14668 VALUE val = ibf_load_object(load, val_index);
14669 rb_hash_aset(obj, key, val);
14673 if (header->frozen) {
14681ibf_dump_cdhash_i(st_data_t key, st_data_t val, st_data_t ptr)
14685 VALUE key_index = ibf_dump_object(dump, (
VALUE)key);
14687 ibf_dump_write_small_value(dump, key_index);
14688 ibf_dump_write_small_value(dump, val);
14689 return ST_CONTINUE;
14695 switch (imemo_type(obj)) {
14696 case imemo_cdhash: {
14697 st_table *tbl = rb_imemo_cdhash_tbl(obj);
14699 long len = tbl->num_entries;
14700 ibf_dump_write_small_value(dump, (
VALUE)
len);
14701 if (
len > 0) st_foreach(tbl, ibf_dump_cdhash_i, (
VALUE)dump);
14705 ibf_dump_object_unsupported(dump, obj);
14713 long len = (long)ibf_load_small_value(load, &offset);
14717 for (i = 0; i <
len; i++) {
14718 VALUE key_index = ibf_load_small_value(load, &offset);
14719 VALUE val = ibf_load_small_value(load, &offset);
14721 VALUE key = ibf_load_object(load, key_index);
14722 cdhash_aset(obj, key, val);
14736 range.class_index = 0;
14739 range.beg = (long)ibf_dump_object(dump, beg);
14740 range.end = (long)ibf_dump_object(dump, end);
14746 rb_raise(
rb_eNotImpError,
"ibf_dump_object_struct: unsupported class %"PRIsVALUE,
14755 VALUE beg = ibf_load_object(load, range->beg);
14756 VALUE end = ibf_load_object(load, range->end);
14766 ssize_t
len = BIGNUM_LEN(obj);
14767 ssize_t slen = BIGNUM_SIGN(obj) > 0 ?
len :
len * -1;
14768 BDIGIT *d = BIGNUM_DIGITS(obj);
14770 (void)IBF_W(&slen, ssize_t, 1);
14771 IBF_WP(d, BDIGIT,
len);
14778 int sign = bignum->slen > 0;
14779 ssize_t
len = sign > 0 ? bignum->slen : -1 * bignum->slen;
14780 const int big_unpack_flags =
14783 VALUE obj = rb_integer_unpack(bignum->digits,
len,
sizeof(BDIGIT), 0,
14794 if (rb_data_is_encoding(obj)) {
14796 const char *name = rb_enc_name(enc);
14797 long len = strlen(name) + 1;
14799 data[0] = IBF_OBJECT_DATA_ENCODING;
14801 (void)IBF_W(data,
long, 2);
14802 IBF_WP(name,
char,
len);
14805 ibf_dump_object_unsupported(dump, obj);
14812 const long *body = IBF_OBJBODY(
long, offset);
14813 const enum ibf_object_data_type
type = (
enum ibf_object_data_type)body[0];
14815 const char *data = (
const char *)&body[2];
14818 case IBF_OBJECT_DATA_ENCODING:
14820 VALUE encobj = rb_enc_from_encoding(rb_enc_find(data));
14825 return ibf_load_object_unsupported(load, header, offset);
14829ibf_dump_object_complex_rational(
struct ibf_dump *dump,
VALUE obj)
14832 data[0] = (long)ibf_dump_object(dump, RCOMPLEX(obj)->real);
14833 data[1] = (long)ibf_dump_object(dump, RCOMPLEX(obj)->imag);
14835 (void)IBF_W(data,
long, 2);
14839ibf_load_object_complex_rational(
const struct ibf_load *load,
const struct ibf_object_header *header, ibf_offset_t offset)
14842 VALUE a = ibf_load_object(load, nums->a);
14843 VALUE b = ibf_load_object(load, nums->b);
14855 ibf_dump_object_string(dump,
rb_sym2str(obj));
14861 ibf_offset_t reading_pos = offset;
14863 int encindex = (int)ibf_load_small_value(load, &reading_pos);
14865 const char *ptr = load->current_buffer->buff + reading_pos;
14867 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
14868 VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX);
14869 encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str));
14872 ID id = rb_intern3(ptr,
len, rb_enc_from_index(encindex));
14876typedef void (*ibf_dump_object_function)(
struct ibf_dump *dump,
VALUE obj);
14877static const ibf_dump_object_function dump_object_functions[
RUBY_T_MASK+1] = {
14878 ibf_dump_object_unsupported,
14879 ibf_dump_object_unsupported,
14880 ibf_dump_object_class,
14881 ibf_dump_object_unsupported,
14882 ibf_dump_object_float,
14883 ibf_dump_object_string,
14884 ibf_dump_object_regexp,
14885 ibf_dump_object_array,
14886 ibf_dump_object_hash,
14887 ibf_dump_object_struct,
14888 ibf_dump_object_bignum,
14889 ibf_dump_object_unsupported,
14890 ibf_dump_object_data,
14891 ibf_dump_object_unsupported,
14892 ibf_dump_object_complex_rational,
14893 ibf_dump_object_complex_rational,
14894 ibf_dump_object_unsupported,
14895 ibf_dump_object_unsupported,
14896 ibf_dump_object_unsupported,
14897 ibf_dump_object_unsupported,
14898 ibf_dump_object_symbol,
14899 ibf_dump_object_unsupported,
14900 ibf_dump_object_unsupported,
14901 ibf_dump_object_unsupported,
14902 ibf_dump_object_unsupported,
14903 ibf_dump_object_unsupported,
14904 ibf_dump_object_imemo,
14905 ibf_dump_object_unsupported,
14906 ibf_dump_object_unsupported,
14907 ibf_dump_object_unsupported,
14908 ibf_dump_object_unsupported,
14909 ibf_dump_object_unsupported,
14915 unsigned char byte =
14916 (header.type << 0) |
14917 (header.special_const << 5) |
14918 (header.frozen << 6) |
14919 (header.internal << 7);
14925ibf_load_object_object_header(const struct
ibf_load *load, ibf_offset_t *offset)
14927 unsigned char byte = ibf_load_byte(load, offset);
14930 header.type = (
byte >> 0) & 0x1f;
14931 header.special_const = (
byte >> 5) & 0x01;
14932 header.frozen = (
byte >> 6) & 0x01;
14933 header.internal = (
byte >> 7) & 0x01;
14942 ibf_offset_t current_offset;
14943 IBF_ZERO(obj_header);
14944 obj_header.type =
TYPE(obj);
14946 IBF_W_ALIGN(ibf_offset_t);
14947 current_offset = ibf_dump_pos(dump);
14952 obj_header.special_const = TRUE;
14953 obj_header.frozen = TRUE;
14954 obj_header.internal = TRUE;
14955 ibf_dump_object_object_header(dump, obj_header);
14956 ibf_dump_write_small_value(dump, obj);
14960 obj_header.special_const = FALSE;
14961 obj_header.frozen =
OBJ_FROZEN(obj) ? TRUE : FALSE;
14962 ibf_dump_object_object_header(dump, obj_header);
14963 (*dump_object_functions[obj_header.type])(dump, obj);
14966 return current_offset;
14970static const ibf_load_object_function load_object_functions[
RUBY_T_MASK+1] = {
14971 ibf_load_object_unsupported,
14972 ibf_load_object_unsupported,
14973 ibf_load_object_class,
14974 ibf_load_object_unsupported,
14975 ibf_load_object_float,
14976 ibf_load_object_string,
14977 ibf_load_object_regexp,
14978 ibf_load_object_array,
14979 ibf_load_object_hash,
14980 ibf_load_object_struct,
14981 ibf_load_object_bignum,
14982 ibf_load_object_unsupported,
14983 ibf_load_object_data,
14984 ibf_load_object_unsupported,
14985 ibf_load_object_complex_rational,
14986 ibf_load_object_complex_rational,
14987 ibf_load_object_unsupported,
14988 ibf_load_object_unsupported,
14989 ibf_load_object_unsupported,
14990 ibf_load_object_unsupported,
14991 ibf_load_object_symbol,
14992 ibf_load_object_unsupported,
14993 ibf_load_object_unsupported,
14994 ibf_load_object_unsupported,
14995 ibf_load_object_unsupported,
14996 ibf_load_object_unsupported,
14997 ibf_load_object_imemo,
14998 ibf_load_object_unsupported,
14999 ibf_load_object_unsupported,
15000 ibf_load_object_unsupported,
15001 ibf_load_object_unsupported,
15002 ibf_load_object_unsupported,
15006ibf_load_object(
const struct ibf_load *load,
VALUE object_index)
15008 if (object_index == 0) {
15012 VALUE obj = pinned_list_fetch(load->current_buffer->obj_list, (
long)object_index);
15014 ibf_offset_t *offsets = (ibf_offset_t *)(load->current_buffer->obj_list_offset + load->current_buffer->buff);
15015 ibf_offset_t offset = offsets[object_index];
15016 const struct ibf_object_header header = ibf_load_object_object_header(load, &offset);
15019 fprintf(stderr,
"ibf_load_object: list=%#x offsets=%p offset=%#x\n",
15020 load->current_buffer->obj_list_offset, (
void *)offsets, offset);
15021 fprintf(stderr,
"ibf_load_object: type=%#x special=%d frozen=%d internal=%d\n",
15022 header.type, header.special_const, header.frozen, header.internal);
15024 if (offset >= load->current_buffer->size) {
15025 rb_raise(
rb_eIndexError,
"object offset out of range: %u", offset);
15028 if (header.special_const) {
15029 ibf_offset_t reading_pos = offset;
15031 obj = ibf_load_small_value(load, &reading_pos);
15034 obj = (*load_object_functions[header.type])(load, &header, offset);
15037 pinned_list_store(load->current_buffer->obj_list, (
long)object_index, obj);
15040 fprintf(stderr,
"ibf_load_object: index=%#"PRIxVALUE
" obj=%#"PRIxVALUE
"\n",
15041 object_index, obj);
15054ibf_dump_object_list_i(st_data_t key, st_data_t val, st_data_t ptr)
15059 ibf_offset_t offset = ibf_dump_object_object(args->dump, obj);
15062 return ST_CONTINUE;
15066ibf_dump_object_list(
struct ibf_dump *dump, ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size)
15068 st_table *obj_table = dump->current_buffer->obj_table;
15073 args.offset_list = offset_list;
15075 st_foreach(obj_table, ibf_dump_object_list_i, (st_data_t)&args);
15077 IBF_W_ALIGN(ibf_offset_t);
15078 *obj_list_offset = ibf_dump_pos(dump);
15080 st_index_t size = obj_table->num_entries;
15083 for (i=0; i<size; i++) {
15088 *obj_list_size = (
unsigned int)size;
15092ibf_dump_mark(
void *ptr)
15095 rb_gc_mark(dump->global_buffer.str);
15097 rb_mark_set(dump->global_buffer.obj_table);
15098 rb_mark_set(dump->iseq_table);
15102ibf_dump_free(
void *ptr)
15105 if (dump->global_buffer.obj_table) {
15106 st_free_table(dump->global_buffer.obj_table);
15107 dump->global_buffer.obj_table = 0;
15109 if (dump->iseq_table) {
15110 st_free_table(dump->iseq_table);
15111 dump->iseq_table = 0;
15116ibf_dump_memsize(
const void *ptr)
15120 if (dump->iseq_table) size += st_memsize(dump->iseq_table);
15121 if (dump->global_buffer.obj_table) size += st_memsize(dump->global_buffer.obj_table);
15127 {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
15128 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_EMBEDDABLE
15134 dump->global_buffer.obj_table = NULL;
15135 dump->iseq_table = NULL;
15138 dump->global_buffer.obj_table = ibf_dump_object_table_new();
15139 dump->iseq_table = st_init_numtable();
15141 dump->current_buffer = &dump->global_buffer;
15149 ibf_dump_write(dump, &header,
sizeof(header));
15150 ibf_dump_iseq(dump, iseq);
15152 header.magic[0] =
'Y';
15153 header.magic[1] =
'A';
15154 header.magic[2] =
'R';
15155 header.magic[3] =
'B';
15156 header.major_version = IBF_MAJOR_VERSION;
15157 header.minor_version = IBF_MINOR_VERSION;
15158 header.endian = IBF_ENDIAN_MARK;
15160 ibf_dump_iseq_list(dump, &header);
15161 ibf_dump_object_list(dump, &header.global_object_list_offset, &header.global_object_list_size);
15162 header.size = ibf_dump_pos(dump);
15165 VALUE opt_str = opt;
15168 ibf_dump_write(dump, ptr, header.extra_size);
15171 header.extra_size = 0;
15174 ibf_dump_overwrite(dump, &header,
sizeof(header), 0);
15176 return dump->global_buffer.str;
15186 if (ISEQ_BODY(iseq)->parent_iseq != NULL ||
15187 ISEQ_BODY(iseq)->local_iseq != iseq) {
15190 if (
RTEST(ISEQ_COVERAGE(iseq))) {
15195 ibf_dump_setup(dump, dump_obj);
15197 str = iseq_ibf_dump_0(dump, iseq, opt);
15202static const ibf_offset_t *
15203ibf_iseq_list(
const struct ibf_load *load)
15205 return (
const ibf_offset_t *)(load->global_buffer.buff + load->header->iseq_list_offset);
15209rb_ibf_load_iseq_complete(
rb_iseq_t *iseq)
15213 ibf_offset_t offset = ibf_iseq_list(load)[iseq->aux.loader.index];
15216 fprintf(stderr,
"rb_ibf_load_iseq_complete: index=%#x offset=%#x size=%#x\n",
15217 iseq->aux.loader.index, offset,
15218 load->header->size);
15220 ibf_load_iseq_each(load, iseq, offset);
15221 ISEQ_COMPILE_DATA_CLEAR(iseq);
15223 rb_iseq_init_trace(iseq);
15224 load->iseq = prev_src_iseq;
15231 rb_ibf_load_iseq_complete((
rb_iseq_t *)iseq);
15239 int iseq_index = (int)(
VALUE)index_iseq;
15242 fprintf(stderr,
"ibf_load_iseq: index_iseq=%p iseq_list=%p\n",
15243 (
void *)index_iseq, (
void *)load->iseq_list);
15245 if (iseq_index == -1) {
15249 VALUE iseqv = pinned_list_fetch(load->iseq_list, iseq_index);
15252 fprintf(stderr,
"ibf_load_iseq: iseqv=%p\n", (
void *)iseqv);
15260 fprintf(stderr,
"ibf_load_iseq: new iseq=%p\n", (
void *)iseq);
15264 iseq->aux.loader.index = iseq_index;
15266 fprintf(stderr,
"ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n",
15267 (
void *)iseq, (
void *)load->loader_obj, iseq_index);
15269 pinned_list_store(load->iseq_list, iseq_index, (
VALUE)iseq);
15271 if (!USE_LAZY_LOAD || GET_VM()->builtin_function_table) {
15273 fprintf(stderr,
"ibf_load_iseq: loading iseq=%p\n", (
void *)iseq);
15275 rb_ibf_load_iseq_complete(iseq);
15279 fprintf(stderr,
"ibf_load_iseq: iseq=%p loaded %p\n",
15280 (
void *)iseq, (
void *)load->iseq);
15288ibf_load_setup_bytes(
struct ibf_load *load,
VALUE loader_obj,
const char *bytes,
size_t size)
15291 load->loader_obj = loader_obj;
15292 load->global_buffer.buff = bytes;
15293 load->header = header;
15294 load->global_buffer.size = header->size;
15295 load->global_buffer.obj_list_offset = header->global_object_list_offset;
15296 load->global_buffer.obj_list_size = header->global_object_list_size;
15297 RB_OBJ_WRITE(loader_obj, &load->iseq_list, pinned_list_new(header->iseq_list_size));
15298 RB_OBJ_WRITE(loader_obj, &load->global_buffer.obj_list, pinned_list_new(load->global_buffer.obj_list_size));
15301 load->current_buffer = &load->global_buffer;
15303 if (size < header->size) {
15306 if (strncmp(header->magic,
"YARB", 4) != 0) {
15309 if (header->major_version != IBF_MAJOR_VERSION ||
15310 header->minor_version != IBF_MINOR_VERSION) {
15312 header->major_version, header->minor_version, IBF_MAJOR_VERSION, IBF_MINOR_VERSION);
15314 if (header->endian != IBF_ENDIAN_MARK) {
15320 if (header->iseq_list_offset %
RUBY_ALIGNOF(ibf_offset_t)) {
15321 rb_raise(rb_eArgError,
"unaligned iseq list offset: %u",
15322 header->iseq_list_offset);
15324 if (load->global_buffer.obj_list_offset %
RUBY_ALIGNOF(ibf_offset_t)) {
15325 rb_raise(rb_eArgError,
"unaligned object list offset: %u",
15326 load->global_buffer.obj_list_offset);
15339 if (USE_LAZY_LOAD) {
15340 str =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
15343 ibf_load_setup_bytes(load, loader_obj, RSTRING_PTR(str), RSTRING_LEN(str));
15348ibf_loader_mark(
void *ptr)
15351 rb_gc_mark(load->str);
15352 rb_gc_mark(load->iseq_list);
15353 rb_gc_mark(load->global_buffer.obj_list);
15357ibf_loader_free(
void *ptr)
15364ibf_loader_memsize(
const void *ptr)
15371 {ibf_loader_mark, ibf_loader_free, ibf_loader_memsize,},
15372 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_THREAD_SAFE_FREE
15376rb_iseq_ibf_load(
VALUE str)
15382 ibf_load_setup(load, loader_obj, str);
15383 iseq = ibf_load_iseq(load, 0);
15390rb_iseq_ibf_load_bytes(
const char *bytes,
size_t size)
15396 ibf_load_setup_bytes(load, loader_obj, bytes, size);
15397 iseq = ibf_load_iseq(load, 0);
15405ibf_dump_iseq_table_collect_i(st_data_t key, st_data_t val, st_data_t arg)
15408 srcs[(int)val] = (
const rb_iseq_t *)key;
15409 return ST_CONTINUE;
15415iseq_subtree_copy_pc2branchindex(
const struct ibf_dump *dump,
const struct ibf_load *load)
15417 unsigned int iseq_count = (
unsigned int)dump->iseq_table->num_entries;
15420 st_foreach(dump->iseq_table, ibf_dump_iseq_table_collect_i, (st_data_t)srcs);
15422 for (
unsigned int i = 0; i < iseq_count; i++) {
15424 VALUE pc2branchindex = ISEQ_PC2BRANCHINDEX(srcs[i]);
15425 if (pc2branchindex !=
Qnil) {
15426 ISEQ_PC2BRANCHINDEX_SET(copy, pc2branchindex);
15435rb_iseq_dup_with_independent_caches(
const rb_iseq_t *src_root)
15443 ibf_dump_setup(dump, dump_obj);
15445 str = iseq_ibf_dump_0(dump, src_root,
Qnil);
15450 ibf_load_setup(load, loader_obj, str);
15458 unsigned int iseq_count = (
unsigned int)dump->iseq_table->num_entries;
15460 for (
unsigned int i = 0; i < iseq_count; i++) {
15464 rb_ibf_load_iseq_complete(copy);
15470 if (!cb->local_iseq)
RB_OBJ_WRITE(copy, &cb->local_iseq, sb->local_iseq);
15471 RB_OBJ_WRITE(copy, &cb->location.pathobj, sb->location.pathobj);
15472 cb->no_realpath = sb->no_realpath;
15473 VALUE sl = ISEQ_SCRIPT_LINES(src_root);
15474 VALUE cov = ISEQ_COVERAGE(src_root);
15482 RB_OBJ_WRITE(copy, &cb->parent_iseq, sb->parent_iseq);
15491 if (ISEQ_PC2BRANCHINDEX(src_root) !=
Qnil) {
15492 iseq_subtree_copy_pc2branchindex(dump, load);
15501rb_iseq_ibf_load_extra_data(
VALUE str)
15507 ibf_load_setup(load, loader_obj, str);
15508 extra_str =
rb_str_new(load->global_buffer.buff + load->header->size, load->header->extra_size);
15513#include "prism_compile.c"
#define RUBY_ATOMIC_PTR_LOAD(var)
Identical to RUBY_ATOMIC_LOAD, except it expects its arguments are void*.
#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 NUM2ULONG
Old name of RB_NUM2ULONG.
#define NUM2LL
Old name of RB_NUM2LL.
#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 Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
#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 ULONG2NUM
Old name of RB_ULONG2NUM.
#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 FLONUM_P
Old name of RB_FLONUM_P.
#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 ALLOCV_N
Old name of RB_ALLOCV_N.
#define NUM2ULL
Old name of RB_NUM2ULL.
#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 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.
@ RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK
Warning is for checking unused block strictly.
VALUE rb_obj_reveal(VALUE obj, VALUE klass)
Make a hidden object visible again.
VALUE rb_cArray
Array class.
VALUE rb_cObject
Object class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_cHash
Hash 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.
VALUE rb_obj_freeze(VALUE obj)
Same as RB_OBJ_FREEZE(), but returns the given object.
#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.
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RB_POSFIXABLE(_)
Checks if the passed value is in range of fixnum, assuming it is a positive number.
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_reverse(VALUE ary)
Destructively reverses the passed array in-place.
VALUE rb_ary_resurrect(VALUE ary)
I guess there is no use case of this function in extension libraries, but this is a routine identical...
VALUE rb_ary_entry(VALUE ary, rb_len_t off)
Queries an element of an array.
VALUE rb_ary_new_capa(rb_len_t capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
void rb_ary_store(VALUE ary, rb_len_t key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
VALUE rb_ary_hidden_new(rb_len_t capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_freeze(VALUE obj)
Freeze an array, preventing further modifications.
VALUE rb_ary_cat(VALUE ary, const VALUE *train, rb_len_t len)
Destructively appends multiple elements at the end of the array.
VALUE rb_ary_join(VALUE ary, VALUE sep)
Recursively stringises the elements of the passed array, flattens that result, then joins the sequenc...
#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.
VALUE rb_rational_new(VALUE num, VALUE den)
Constructs a Rational, with reduction.
int rb_reg_options(VALUE re)
Queries the options of the passed regular expression.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_tmp_new(rb_len_t 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.
VALUE rb_str_cat(VALUE dst, const char *src, rb_len_t srclen)
Destructively appends the passed contents to the string.
VALUE rb_str_resurrect(VALUE str)
Like rb_str_dup(), but always create an instance of rb_cString regardless of the given object's class...
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
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_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_id2sym(ID id)
Allocates an instance of rb_cSymbol that has the given id.
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
ID rb_sym2id(VALUE obj)
Converts an instance of rb_cSymbol into an ID.
int len
Length of the buffer.
#define RB_OBJ_SET_SHAREABLE(obj)
Wrapper of rb_obj_set_shareable().
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
static VALUE RB_OBJ_SET_FROZEN_SHAREABLE(VALUE obj)
Freezes and marks the object as shareable.
VALUE rb_ractor_make_shareable(VALUE obj)
Destructively transforms the passed object so that multiple Ractors can share it.
#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]]
#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.
#define RARRAY_AREF(a, i)
References an object in an array.
static void RARRAY_ASET(VALUE ary, rb_len_t i, VALUE v)
Assigns an object in an array.
#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 RUBY_DEFAULT_FREE
This is a value you can set to RData::dfree.
void(* RUBY_DATA_FUNC)(void *)
This is the type of callbacks registered to RData.
#define RHASH_SIZE(h)
Queries the size of the hash.
static VALUE RREGEXP_SRC(VALUE rexp)
Convenient getter function.
#define StringValue(v)
Ensures that the parameter object is a String.
#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.
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
#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.
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
#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 ::...
This is the struct that holds necessary info for a struct.
const char * wrap_struct_name
Name of structs of this kind.
long rb_len_t
A signed integer type for lengths and indices of objects such as String and Array.
unsigned long rb_ulen_t
An unsigned integer type that has the same width with rb_len_t.
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.
static bool rb_integer_type_p(VALUE obj)
Queries if the object is an instance of rb_cInteger.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
@ RUBY_T_MASK
Bitmask of ruby_value_type.