12#include "ruby/internal/config.h"
23#include "internal/array.h"
24#include "internal/compile.h"
25#include "internal/complex.h"
26#include "internal/encoding.h"
27#include "internal/error.h"
28#include "internal/hash.h"
29#include "internal/numeric.h"
30#include "internal/object.h"
31#include "internal/rational.h"
32#include "internal/re.h"
33#include "internal/symbol.h"
34#include "internal/thread.h"
35#include "internal/variable.h"
40#include "vm_callinfo.h"
45#include "insns_info.inc"
47#undef RUBY_UNTYPED_DATA_WARNING
48#define RUBY_UNTYPED_DATA_WARNING 0
50#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
51#define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
85 unsigned int rescued: 2;
86 unsigned int unremovable: 1;
91 enum ruby_vminsn_type insn_id;
121 const NODE *ensure_node;
126const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO};
146#define compile_debug CPDEBUG
148#define compile_debug ISEQ_COMPILE_DATA(iseq)->option->debug_level
153#define compile_debug_print_indent(level) \
154 ruby_debug_print_indent((level), compile_debug, gl_node_level * 2)
156#define debugp(header, value) (void) \
157 (compile_debug_print_indent(1) && \
158 ruby_debug_print_value(1, compile_debug, (header), (value)))
160#define debugi(header, id) (void) \
161 (compile_debug_print_indent(1) && \
162 ruby_debug_print_id(1, compile_debug, (header), (id)))
164#define debugp_param(header, value) (void) \
165 (compile_debug_print_indent(1) && \
166 ruby_debug_print_value(1, compile_debug, (header), (value)))
168#define debugp_verbose(header, value) (void) \
169 (compile_debug_print_indent(2) && \
170 ruby_debug_print_value(2, compile_debug, (header), (value)))
172#define debugp_verbose_node(header, value) (void) \
173 (compile_debug_print_indent(10) && \
174 ruby_debug_print_value(10, compile_debug, (header), (value)))
176#define debug_node_start(node) ((void) \
177 (compile_debug_print_indent(1) && \
178 (ruby_debug_print_node(1, CPDEBUG, "", (const NODE *)(node)), gl_node_level)), \
181#define debug_node_end() gl_node_level --
185#define debugi(header, id) ((void)0)
186#define debugp(header, value) ((void)0)
187#define debugp_verbose(header, value) ((void)0)
188#define debugp_verbose_node(header, value) ((void)0)
189#define debugp_param(header, value) ((void)0)
190#define debug_node_start(node) ((void)0)
191#define debug_node_end() ((void)0)
194#if CPDEBUG > 1 || CPDEBUG < 0
196#define printf ruby_debug_printf
197#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
198#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v))
200#define debugs if(0)printf
201#define debug_compile(msg, v) (v)
204#define LVAR_ERRINFO (1)
207#define NEW_LABEL(l) new_label_body(iseq, (l))
208#define LABEL_FORMAT "<L%03d>"
210#define NEW_ISEQ(node, name, type, line_no) \
211 new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no))
213#define NEW_CHILD_ISEQ(node, name, type, line_no) \
214 new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no))
217#define ADD_SEQ(seq1, seq2) \
218 APPEND_LIST((seq1), (seq2))
221#define ADD_INSN(seq, line_node, insn) \
222 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
225#define INSERT_BEFORE_INSN(next, line_node, insn) \
226 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
229#define INSERT_AFTER_INSN(prev, line_node, insn) \
230 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
233#define ADD_INSN1(seq, line_node, insn, op1) \
234 ADD_ELEM((seq), (LINK_ELEMENT *) \
235 new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
238#define INSERT_BEFORE_INSN1(next, line_node, insn, op1) \
239 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) \
240 new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
243#define INSERT_AFTER_INSN1(prev, line_node, insn, op1) \
244 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) \
245 new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
247#define LABEL_REF(label) ((label)->refcnt++)
250#define ADD_INSNL(seq, line_node, insn, label) (ADD_INSN1(seq, line_node, insn, label), LABEL_REF(label))
252#define ADD_INSN2(seq, line_node, insn, op1, op2) \
253 ADD_ELEM((seq), (LINK_ELEMENT *) \
254 new_insn_body(iseq, (line_node), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
256#define ADD_INSN3(seq, line_node, insn, op1, op2, op3) \
257 ADD_ELEM((seq), (LINK_ELEMENT *) \
258 new_insn_body(iseq, (line_node), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
261#define ADD_SEND(seq, line_node, id, argc) \
262 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL)
264#define ADD_SEND_WITH_FLAG(seq, line_node, id, argc, flag) \
265 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)(flag), NULL)
267#define ADD_SEND_WITH_BLOCK(seq, line_node, id, argc, block) \
268 ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(0), NULL)
270#define ADD_CALL_RECEIVER(seq, line_node) \
271 ADD_INSN((seq), (line_node), putself)
273#define ADD_CALL(seq, line_node, id, argc) \
274 ADD_SEND_R((seq), (line_node), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
276#define ADD_CALL_WITH_BLOCK(seq, line_node, id, argc, block) \
277 ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
279#define ADD_SEND_R(seq, line_node, id, argc, block, flag, keywords) \
280 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line_node), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
282#define ADD_TRACE(seq, event) \
283 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), 0))
284#define ADD_TRACE_WITH_DATA(seq, event, data) \
285 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), (data)))
287static void iseq_add_getlocal(
rb_iseq_t *iseq,
LINK_ANCHOR *
const seq,
const NODE *
const line_node,
int idx,
int level);
288static void iseq_add_setlocal(
rb_iseq_t *iseq,
LINK_ANCHOR *
const seq,
const NODE *
const line_node,
int idx,
int level);
290#define ADD_GETLOCAL(seq, line_node, idx, level) iseq_add_getlocal(iseq, (seq), (line_node), (idx), (level))
291#define ADD_SETLOCAL(seq, line_node, idx, level) iseq_add_setlocal(iseq, (seq), (line_node), (idx), (level))
294#define ADD_LABEL(seq, label) \
295 ADD_ELEM((seq), (LINK_ELEMENT *) (label))
297#define APPEND_LABEL(seq, before, label) \
298 APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label))
300#define ADD_ADJUST(seq, line_node, label) \
301 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), nd_line(line_node)))
303#define ADD_ADJUST_RESTORE(seq, label) \
304 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1))
306#define LABEL_UNREMOVABLE(label) \
307 ((label) ? (LABEL_REF(label), (label)->unremovable=1) : 0)
308#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \
309 VALUE _e = rb_ary_new3(5, (type), \
310 (VALUE)(ls) | 1, (VALUE)(le) | 1, \
311 (VALUE)(iseqv), (VALUE)(lc) | 1); \
312 LABEL_UNREMOVABLE(ls); \
315 if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) \
316 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, rb_ary_hidden_new(3)); \
317 rb_ary_push(ISEQ_COMPILE_DATA(iseq)->catch_table_ary, freeze_hide_obj(_e)); \
321#define COMPILE(anchor, desc, node) \
322 (debug_compile("== " desc "\n", \
323 iseq_compile_each(iseq, (anchor), (node), 0)))
326#define COMPILE_POPPED(anchor, desc, node) \
327 (debug_compile("== " desc "\n", \
328 iseq_compile_each(iseq, (anchor), (node), 1)))
331#define COMPILE_(anchor, desc, node, popped) \
332 (debug_compile("== " desc "\n", \
333 iseq_compile_each(iseq, (anchor), (node), (popped))))
335#define COMPILE_RECV(anchor, desc, node) \
336 (private_recv_p(node) ? \
337 (ADD_INSN(anchor, node, putself), VM_CALL_FCALL) : \
338 COMPILE(anchor, desc, node->nd_recv) ? 0 : -1)
340#define OPERAND_AT(insn, idx) \
341 (((INSN*)(insn))->operands[(idx)])
343#define INSN_OF(insn) \
344 (((INSN*)(insn))->insn_id)
346#define IS_INSN(link) ((link)->type == ISEQ_ELEMENT_INSN)
347#define IS_LABEL(link) ((link)->type == ISEQ_ELEMENT_LABEL)
348#define IS_ADJUST(link) ((link)->type == ISEQ_ELEMENT_ADJUST)
349#define IS_TRACE(link) ((link)->type == ISEQ_ELEMENT_TRACE)
350#define IS_INSN_ID(iobj, insn) (INSN_OF(iobj) == BIN(insn))
351#define IS_NEXT_INSN_ID(link, insn) \
352 ((link)->next && IS_INSN((link)->next) && IS_INSN_ID((link)->next, insn))
360append_compile_error(const
rb_iseq_t *iseq,
int line, const
char *fmt, ...)
362 VALUE err_info = ISEQ_COMPILE_DATA(iseq)->err_info;
363 VALUE file = rb_iseq_path(iseq);
368 err = rb_syntax_error_append(err, file, line, -1, NULL, fmt, args);
370 if (
NIL_P(err_info)) {
371 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err);
374 else if (!err_info) {
385compile_bug(
rb_iseq_t *iseq,
int line,
const char *fmt, ...)
389 rb_report_bug_valist(rb_iseq_path(iseq), line, fmt, args);
395#define COMPILE_ERROR append_compile_error
397#define ERROR_ARGS_AT(n) iseq, nd_line(n),
398#define ERROR_ARGS ERROR_ARGS_AT(node)
400#define EXPECT_NODE(prefix, node, ndtype, errval) \
402 const NODE *error_node = (node); \
403 enum node_type error_type = nd_type(error_node); \
404 if (error_type != (ndtype)) { \
405 COMPILE_ERROR(ERROR_ARGS_AT(error_node) \
406 prefix ": " #ndtype " is expected, but %s", \
407 ruby_node_name(error_type)); \
412#define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval) \
414 COMPILE_ERROR(ERROR_ARGS_AT(parent) \
415 prefix ": must be " #ndtype ", but 0"); \
419#define UNKNOWN_NODE(prefix, node, errval) \
421 const NODE *error_node = (node); \
422 COMPILE_ERROR(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \
423 ruby_node_name(nd_type(error_node))); \
430#define CHECK(sub) if (!(sub)) {BEFORE_RETURN;return COMPILE_NG;}
431#define NO_CHECK(sub) (void)(sub)
436#define DECL_ANCHOR(name) \
437 LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},}}
438#define INIT_ANCHOR(name) \
439 (name->last = &name->anchor)
442freeze_hide_obj(
VALUE obj)
445 RBASIC_CLEAR_CLASS(obj);
449#include "optinsn.inc"
450#if OPT_INSTRUCTIONS_UNIFICATION
451#include "optunifs.inc"
456#define ISEQ_ARG iseq,
457#define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
460#define ISEQ_ARG_DECLARE
464#define gl_node_level ISEQ_COMPILE_DATA(iseq)->node_level
470static int insn_data_length(
INSN *iobj);
471static int calc_sp_depth(
int depth,
INSN *iobj);
473static INSN *new_insn_body(
rb_iseq_t *iseq,
const NODE *
const line_node,
enum ruby_vminsn_type insn_id,
int argc, ...);
486static int iseq_set_exception_local_table(
rb_iseq_t *iseq);
491static int iseq_set_exception_table(
rb_iseq_t *iseq);
492static int iseq_set_optargs_table(
rb_iseq_t *iseq);
495static int compile_hash(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *node,
int method_call_keywords,
int popped);
502verify_list(ISEQ_ARG_DECLARE
const char *info,
LINK_ANCHOR *
const anchor)
508 if (!compile_debug)
return;
510 list = anchor->anchor.next;
511 plist = &anchor->anchor;
513 if (plist != list->prev) {
520 if (anchor->last != plist && anchor->last != 0) {
525 rb_bug(
"list verify error: %08x (%s)", flag, info);
530#define verify_list(info, anchor) verify_list(iseq, (info), (anchor))
537 VALUE *original = rb_iseq_original_iseq(iseq);
539 while (i < ISEQ_BODY(iseq)->iseq_size) {
540 VALUE insn = original[i];
541 const char *types = insn_op_types(insn);
543 for (
int j=0; types[j]; j++) {
544 if (types[j] == TS_CALLDATA) {
548 if (cc != vm_cc_empty()) {
550 rb_bug(
"call cache is not initialized by vm_cc_empty()");
557 for (
unsigned int i=0; i<ISEQ_BODY(iseq)->ci_size; i++) {
558 struct rb_call_data *cd = &ISEQ_BODY(iseq)->call_data[i];
561 if (cc != NULL && cc != vm_cc_empty()) {
563 rb_bug(
"call cache is not initialized by vm_cc_empty()");
575 elem->prev = anchor->last;
576 anchor->last->next = elem;
578 verify_list(
"add", anchor);
588 elem->next = before->next;
589 elem->next->prev = elem;
591 if (before == anchor->last) anchor->last = elem;
592 verify_list(
"add", anchor);
595#define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem))
596#define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem))
600branch_coverage_valid_p(
rb_iseq_t *iseq,
int first_line)
602 if (!ISEQ_COVERAGE(iseq))
return 0;
603 if (!ISEQ_BRANCH_COVERAGE(iseq))
return 0;
604 if (first_line <= 0)
return 0;
611 const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
612 const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
614 if (!branch_coverage_valid_p(iseq, first_lineno))
return Qundef;
626 VALUE branch_base = rb_hash_aref(structure, key);
629 if (
NIL_P(branch_base)) {
630 branch_base = rb_ary_hidden_new(6);
631 rb_hash_aset(structure, key, branch_base);
632 rb_ary_push(branch_base,
ID2SYM(rb_intern(
type)));
633 rb_ary_push(branch_base,
INT2FIX(first_lineno));
634 rb_ary_push(branch_base,
INT2FIX(first_column));
635 rb_ary_push(branch_base,
INT2FIX(last_lineno));
636 rb_ary_push(branch_base,
INT2FIX(last_column));
637 branches = rb_hash_new();
639 rb_ary_push(branch_base, branches);
649generate_dummy_line_node(
int lineno,
int node_id)
652 nd_set_line(&dummy, lineno);
653 nd_set_node_id(&dummy, node_id);
660 const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
661 const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
663 if (!branch_coverage_valid_p(iseq, first_lineno))
return;
674 VALUE branch = rb_hash_aref(branches, key);
678 branch = rb_ary_hidden_new(6);
679 rb_hash_aset(branches, key, branch);
681 rb_ary_push(branch,
INT2FIX(first_lineno));
682 rb_ary_push(branch,
INT2FIX(first_column));
683 rb_ary_push(branch,
INT2FIX(last_lineno));
684 rb_ary_push(branch,
INT2FIX(last_column));
687 rb_ary_push(branch,
LONG2FIX(counter_idx));
688 rb_ary_push(counters,
INT2FIX(0));
694 ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx);
696 NODE dummy_line_node = generate_dummy_line_node(last_lineno, nd_node_id(node));
697 ADD_INSN(seq, &dummy_line_node, nop);
700#define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line)
703validate_label(st_data_t name, st_data_t label, st_data_t arg)
707 if (!lobj->link.next) {
709 COMPILE_ERROR(iseq, lobj->position,
710 "%"PRIsVALUE
": undefined label",
720 st_foreach(labels_table, validate_label, (st_data_t)iseq);
721 st_free_table(labels_table);
730 (*ifunc->func)(iseq, ret, ifunc->data);
732 NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1);
733 ADD_INSN(ret, &dummy_line_node, leave);
735 CHECK(iseq_setup_insn(iseq, ret));
736 return iseq_setup(iseq, ret);
745 if (IMEMO_TYPE_P(node, imemo_ifunc)) {
750 NO_CHECK(COMPILE(ret,
"nil", node));
751 iseq_set_local_table(iseq, 0);
754 else if (nd_type_p(node, NODE_SCOPE)) {
756 iseq_set_local_table(iseq, node->nd_tbl);
757 iseq_set_arguments(iseq, ret, node->nd_args);
759 switch (ISEQ_BODY(iseq)->
type) {
760 case ISEQ_TYPE_BLOCK:
762 LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(0);
763 LABEL *end = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(0);
765 start->rescued = LABEL_RESCUE_BEG;
766 end->rescued = LABEL_RESCUE_END;
769 NODE dummy_line_node = generate_dummy_line_node(ISEQ_BODY(iseq)->location.first_lineno, -1);
770 ADD_INSN (ret, &dummy_line_node, nop);
771 ADD_LABEL(ret, start);
772 CHECK(COMPILE(ret,
"block body", node->nd_body));
775 ISEQ_COMPILE_DATA(iseq)->last_line = ISEQ_BODY(iseq)->location.code_location.end_pos.lineno;
778 ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
779 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
782 case ISEQ_TYPE_CLASS:
785 CHECK(COMPILE(ret,
"scoped node", node->nd_body));
787 ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
790 case ISEQ_TYPE_METHOD:
792 ISEQ_COMPILE_DATA(iseq)->root_node = node->nd_body;
794 CHECK(COMPILE(ret,
"scoped node", node->nd_body));
795 ISEQ_COMPILE_DATA(iseq)->root_node = node->nd_body;
797 ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
801 CHECK(COMPILE(ret,
"scoped node", node->nd_body));
808#define INVALID_ISEQ_TYPE(type) \
809 ISEQ_TYPE_##type: m = #type; goto invalid_iseq_type
810 switch (ISEQ_BODY(iseq)->
type) {
811 case INVALID_ISEQ_TYPE(
METHOD);
812 case INVALID_ISEQ_TYPE(CLASS);
813 case INVALID_ISEQ_TYPE(BLOCK);
814 case INVALID_ISEQ_TYPE(EVAL);
815 case INVALID_ISEQ_TYPE(MAIN);
816 case INVALID_ISEQ_TYPE(TOP);
817#undef INVALID_ISEQ_TYPE
818 case ISEQ_TYPE_RESCUE:
819 iseq_set_exception_local_table(iseq);
820 CHECK(COMPILE(ret,
"rescue", node));
822 case ISEQ_TYPE_ENSURE:
823 iseq_set_exception_local_table(iseq);
824 CHECK(COMPILE_POPPED(ret,
"ensure", node));
826 case ISEQ_TYPE_PLAIN:
827 CHECK(COMPILE(ret,
"ensure", node));
830 COMPILE_ERROR(ERROR_ARGS
"unknown scope: %d", ISEQ_BODY(iseq)->
type);
833 COMPILE_ERROR(ERROR_ARGS
"compile/ISEQ_TYPE_%s should not be reached", m);
838 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE || ISEQ_BODY(iseq)->
type == ISEQ_TYPE_ENSURE) {
839 NODE dummy_line_node = generate_dummy_line_node(0, -1);
840 ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
841 ADD_INSN1(ret, &dummy_line_node,
throw,
INT2FIX(0) );
844 NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1);
845 ADD_INSN(ret, &dummy_line_node, leave);
849 if (ISEQ_COMPILE_DATA(iseq)->labels_table) {
850 st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
851 ISEQ_COMPILE_DATA(iseq)->labels_table = 0;
852 validate_labels(iseq, labels_table);
855 CHECK(iseq_setup_insn(iseq, ret));
856 return iseq_setup(iseq, ret);
860rb_iseq_translate_threaded_code(
rb_iseq_t *iseq)
862#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
863 const void *
const *table = rb_vm_get_insns_address_table();
865 VALUE *encoded = (
VALUE *)ISEQ_BODY(iseq)->iseq_encoded;
867 for (i = 0; i < ISEQ_BODY(iseq)->iseq_size; ) {
868 int insn = (int)ISEQ_BODY(iseq)->iseq_encoded[i];
869 int len = insn_len(insn);
870 encoded[i] = (
VALUE)table[insn];
879rb_iseq_original_iseq(
const rb_iseq_t *iseq)
881 VALUE *original_code;
883 if (ISEQ_ORIGINAL_ISEQ(iseq))
return ISEQ_ORIGINAL_ISEQ(iseq);
884 original_code = ISEQ_ORIGINAL_ISEQ_ALLOC(iseq, ISEQ_BODY(iseq)->iseq_size);
885 MEMCPY(original_code, ISEQ_BODY(iseq)->iseq_encoded,
VALUE, ISEQ_BODY(iseq)->iseq_size);
887#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
891 for (i = 0; i < ISEQ_BODY(iseq)->iseq_size; ) {
892 const void *addr = (
const void *)original_code[i];
893 const int insn = rb_vm_insn_addr2insn(addr);
895 original_code[i] = insn;
900 return original_code;
913#if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__)
914 #define STRICT_ALIGNMENT
920#if defined(__OpenBSD__)
921 #include <sys/endian.h>
922 #ifdef __STRICT_ALIGNMENT
923 #define STRICT_ALIGNMENT
927#ifdef STRICT_ALIGNMENT
928 #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE
929 #define ALIGNMENT_SIZE SIZEOF_LONG_LONG
931 #define ALIGNMENT_SIZE SIZEOF_VALUE
933 #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1))
934 #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX
937 #define PADDING_SIZE_MAX 0
940#ifdef STRICT_ALIGNMENT
943calc_padding(
void *ptr,
size_t size)
948 mis = (size_t)ptr & ALIGNMENT_SIZE_MASK;
950 padding = ALIGNMENT_SIZE - mis;
956#if ALIGNMENT_SIZE > SIZEOF_VALUE
957 if (size ==
sizeof(
VALUE) && padding ==
sizeof(
VALUE)) {
971#ifdef STRICT_ALIGNMENT
972 size_t padding = calc_padding((
void *)&storage->buff[storage->pos], size);
974 const size_t padding = 0;
977 if (size >= INT_MAX - padding) rb_memerror();
978 if (storage->pos + size + padding > storage->size) {
979 unsigned int alloc_size = storage->size;
981 while (alloc_size < size + PADDING_SIZE_MAX) {
982 if (alloc_size >= INT_MAX / 2) rb_memerror();
985 storage->next = (
void *)
ALLOC_N(
char, alloc_size +
987 storage = *arena = storage->next;
990 storage->size = alloc_size;
991#ifdef STRICT_ALIGNMENT
992 padding = calc_padding((
void *)&storage->buff[storage->pos], size);
996#ifdef STRICT_ALIGNMENT
997 storage->pos += (int)padding;
1000 ptr = (
void *)&storage->buff[storage->pos];
1001 storage->pos += (
int)size;
1006compile_data_alloc(
rb_iseq_t *iseq,
size_t size)
1009 return compile_data_alloc_with_arena(arena, size);
1013compile_data_alloc2(
rb_iseq_t *iseq,
size_t x,
size_t y)
1016 return compile_data_alloc(iseq, size);
1020compile_data_calloc2(
rb_iseq_t *iseq,
size_t x,
size_t y)
1023 void *p = compile_data_alloc(iseq, size);
1032 return (
INSN *)compile_data_alloc_with_arena(arena,
sizeof(
INSN));
1036compile_data_alloc_label(
rb_iseq_t *iseq)
1038 return (
LABEL *)compile_data_alloc(iseq,
sizeof(
LABEL));
1042compile_data_alloc_adjust(
rb_iseq_t *iseq)
1044 return (
ADJUST *)compile_data_alloc(iseq,
sizeof(
ADJUST));
1048compile_data_alloc_trace(
rb_iseq_t *iseq)
1050 return (
TRACE *)compile_data_alloc(iseq,
sizeof(
TRACE));
1059 elem2->next = elem1->next;
1060 elem2->prev = elem1;
1061 elem1->next = elem2;
1063 elem2->next->prev = elem2;
1073 elem2->prev = elem1->prev;
1074 elem2->next = elem1;
1075 elem1->prev = elem2;
1077 elem2->prev->next = elem2;
1087 elem2->prev = elem1->prev;
1088 elem2->next = elem1->next;
1090 elem1->prev->next = elem2;
1093 elem1->next->prev = elem2;
1100 elem->prev->next = elem->next;
1102 elem->next->prev = elem->prev;
1109 return anchor->anchor.next;
1115 return anchor->last;
1122 switch (elem->type) {
1123 case ISEQ_ELEMENT_INSN:
1124 case ISEQ_ELEMENT_ADJUST:
1134LIST_INSN_SIZE_ONE(
const LINK_ANCHOR *
const anchor)
1136 LINK_ELEMENT *first_insn = ELEM_FIRST_INSN(FIRST_ELEMENT(anchor));
1137 if (first_insn != NULL &&
1138 ELEM_FIRST_INSN(first_insn->next) == NULL) {
1147LIST_INSN_SIZE_ZERO(
const LINK_ANCHOR *
const anchor)
1149 if (ELEM_FIRST_INSN(FIRST_ELEMENT(anchor)) == NULL) {
1167 if (anc2->anchor.next) {
1168 anc1->last->next = anc2->anchor.next;
1169 anc2->anchor.next->prev = anc1->last;
1170 anc1->last = anc2->last;
1172 verify_list(
"append", anc1);
1175#define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
1184 printf(
"anch: %p, frst: %p, last: %p\n", (
void *)&anchor->anchor,
1185 (
void *)anchor->anchor.next, (
void *)anchor->last);
1187 printf(
"curr: %p, next: %p, prev: %p, type: %d\n", (
void *)list, (
void *)list->next,
1188 (
void *)list->prev, (
int)list->type);
1193 dump_disasm_list_with_cursor(anchor->anchor.next, cur, 0);
1194 verify_list(
"debug list", anchor);
1197#define debug_list(anc, cur) debug_list(iseq, (anc), (cur))
1200#define debug_list(anc, cur) ((void)0)
1206 TRACE *trace = compile_data_alloc_trace(iseq);
1208 trace->link.type = ISEQ_ELEMENT_TRACE;
1209 trace->link.next = NULL;
1210 trace->event = event;
1217new_label_body(
rb_iseq_t *iseq,
long line)
1219 LABEL *labelobj = compile_data_alloc_label(iseq);
1221 labelobj->link.type = ISEQ_ELEMENT_LABEL;
1222 labelobj->link.next = 0;
1224 labelobj->label_no = ISEQ_COMPILE_DATA(iseq)->label_no++;
1225 labelobj->sc_state = 0;
1227 labelobj->refcnt = 0;
1229 labelobj->rescued = LABEL_RESCUE_NONE;
1230 labelobj->unremovable = 0;
1237 ADJUST *adjust = compile_data_alloc_adjust(iseq);
1238 adjust->link.type = ISEQ_ELEMENT_ADJUST;
1239 adjust->link.next = 0;
1240 adjust->label = label;
1241 adjust->line_no = line;
1242 LABEL_UNREMOVABLE(label);
1248 int insn_id,
int argc,
VALUE *argv)
1250 INSN *iobj = compile_data_alloc_insn(iseq);
1254 iobj->link.type = ISEQ_ELEMENT_INSN;
1255 iobj->link.next = 0;
1256 iobj->insn_id = insn_id;
1257 iobj->insn_info.line_no = nd_line(line_node);
1258 iobj->insn_info.node_id = nd_node_id(line_node);
1259 iobj->insn_info.events = 0;
1260 iobj->operands = argv;
1261 iobj->operand_size = argc;
1267new_insn_body(
rb_iseq_t *iseq,
const NODE *
const line_node,
enum ruby_vminsn_type insn_id,
int argc, ...)
1269 VALUE *operands = 0;
1273 va_start(argv, argc);
1274 operands = compile_data_alloc2(iseq,
sizeof(
VALUE), argc);
1275 for (i = 0; i < argc; i++) {
1281 return new_insn_core(iseq, line_node, insn_id, argc, operands);
1287 VM_ASSERT(argc >= 0);
1289 if (!(flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) &&
1290 kw_arg == NULL && !has_blockiseq) {
1291 flag |= VM_CALL_ARGS_SIMPLE;
1295 flag |= VM_CALL_KWARG;
1296 argc += kw_arg->keyword_len;
1299 ISEQ_BODY(iseq)->ci_size++;
1300 const struct rb_callinfo *ci = vm_ci_new(mid, flag, argc, kw_arg);
1308 VALUE *operands = compile_data_calloc2(iseq,
sizeof(
VALUE), 2);
1311 operands[1] = (
VALUE)blockiseq;
1315 INSN *insn = new_insn_core(iseq, line_node, BIN(send), 2, operands);
1329 ast.compile_option = 0;
1330 ast.script_lines = ISEQ_BODY(iseq)->variable.script_lines;
1332 debugs(
"[new_child_iseq]> ---------------------------------------\n");
1333 int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
1334 ret_iseq = rb_iseq_new_with_opt(&ast, name,
1335 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
1337 isolated_depth ? isolated_depth + 1 : 0,
1338 type, ISEQ_COMPILE_DATA(iseq)->option);
1339 debugs(
"[new_child_iseq]< ---------------------------------------\n");
1349 debugs(
"[new_child_iseq_with_callback]> ---------------------------------------\n");
1350 ret_iseq = rb_iseq_new_with_callback(ifunc, name,
1351 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
1352 line_no, parent,
type, ISEQ_COMPILE_DATA(iseq)->option);
1353 debugs(
"[new_child_iseq_with_callback]< ---------------------------------------\n");
1360 body->catch_except_p =
true;
1361 if (body->parent_iseq != NULL) {
1362 set_catch_except_p(ISEQ_BODY(body->parent_iseq));
1384 while (pos < body->iseq_size) {
1385 insn = rb_vm_insn_decode(body->iseq_encoded[pos]);
1386 if (insn == BIN(
throw)) {
1387 set_catch_except_p(body);
1390 pos += insn_len(insn);
1396 for (i = 0; i < ct->size; i++) {
1398 UNALIGNED_MEMBER_PTR(ct, entries[i]);
1399 if (entry->type != CATCH_TYPE_BREAK
1400 && entry->type != CATCH_TYPE_NEXT
1401 && entry->type != CATCH_TYPE_REDO) {
1402 body->catch_except_p =
true;
1409iseq_insert_nop_between_end_and_cont(
rb_iseq_t *iseq)
1411 VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
1412 if (
NIL_P(catch_table_ary))
return;
1413 unsigned int i, tlen = (
unsigned int)
RARRAY_LEN(catch_table_ary);
1415 for (i = 0; i < tlen; i++) {
1421 enum rb_catch_type ct = (
enum rb_catch_type)(ptr[0] & 0xffff);
1423 if (ct != CATCH_TYPE_BREAK
1424 && ct != CATCH_TYPE_NEXT
1425 && ct != CATCH_TYPE_REDO) {
1427 for (e = end; e && (IS_LABEL(e) || IS_TRACE(e)); e = e->next) {
1429 NODE dummy_line_node = generate_dummy_line_node(0, -1);
1430 INSN *nop = new_insn_core(iseq, &dummy_line_node, BIN(nop), 0, 0);
1431 ELEM_INSERT_NEXT(end, &nop->link);
1442 if (
RTEST(ISEQ_COMPILE_DATA(iseq)->err_info))
1447 if (compile_debug > 5)
1448 dump_disasm_list(FIRST_ELEMENT(anchor));
1450 debugs(
"[compile step 3.1 (iseq_optimize)]\n");
1451 iseq_optimize(iseq, anchor);
1453 if (compile_debug > 5)
1454 dump_disasm_list(FIRST_ELEMENT(anchor));
1456 if (ISEQ_COMPILE_DATA(iseq)->option->instructions_unification) {
1457 debugs(
"[compile step 3.2 (iseq_insns_unification)]\n");
1458 iseq_insns_unification(iseq, anchor);
1459 if (compile_debug > 5)
1460 dump_disasm_list(FIRST_ELEMENT(anchor));
1463 if (ISEQ_COMPILE_DATA(iseq)->option->stack_caching) {
1464 debugs(
"[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
1465 iseq_set_sequence_stackcaching(iseq, anchor);
1466 if (compile_debug > 5)
1467 dump_disasm_list(FIRST_ELEMENT(anchor));
1470 debugs(
"[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n");
1471 iseq_insert_nop_between_end_and_cont(iseq);
1472 if (compile_debug > 5)
1473 dump_disasm_list(FIRST_ELEMENT(anchor));
1481 if (
RTEST(ISEQ_COMPILE_DATA(iseq)->err_info))
1484 debugs(
"[compile step 4.1 (iseq_set_sequence)]\n");
1485 if (!iseq_set_sequence(iseq, anchor))
return COMPILE_NG;
1486 if (compile_debug > 5)
1487 dump_disasm_list(FIRST_ELEMENT(anchor));
1489 debugs(
"[compile step 4.2 (iseq_set_exception_table)]\n");
1490 if (!iseq_set_exception_table(iseq))
return COMPILE_NG;
1492 debugs(
"[compile step 4.3 (set_optargs_table)] \n");
1493 if (!iseq_set_optargs_table(iseq))
return COMPILE_NG;
1495 debugs(
"[compile step 5 (iseq_translate_threaded_code)] \n");
1496 if (!rb_iseq_translate_threaded_code(iseq))
return COMPILE_NG;
1498 debugs(
"[compile step 6 (update_catch_except_flags)] \n");
1499 update_catch_except_flags(ISEQ_BODY(iseq));
1501 debugs(
"[compile step 6.1 (remove unused catch tables)] \n");
1502 if (!ISEQ_BODY(iseq)->catch_except_p && ISEQ_BODY(iseq)->catch_table) {
1503 xfree(ISEQ_BODY(iseq)->catch_table);
1504 ISEQ_BODY(iseq)->catch_table = NULL;
1507#if VM_INSN_INFO_TABLE_IMPL == 2
1508 if (ISEQ_BODY(iseq)->insns_info.succ_index_table == NULL) {
1509 debugs(
"[compile step 7 (rb_iseq_insns_info_encode_positions)] \n");
1510 rb_iseq_insns_info_encode_positions(iseq);
1514 if (compile_debug > 1) {
1515 VALUE str = rb_iseq_disasm(iseq);
1518 verify_call_cache(iseq);
1519 debugs(
"[compile step: finish]\n");
1525iseq_set_exception_local_table(
rb_iseq_t *iseq)
1527 ISEQ_BODY(iseq)->local_table_size = numberof(rb_iseq_shared_exc_local_tbl);
1528 ISEQ_BODY(iseq)->local_table = rb_iseq_shared_exc_local_tbl;
1536 while (iseq != ISEQ_BODY(iseq)->local_iseq) {
1538 iseq = ISEQ_BODY(iseq)->parent_iseq;
1544get_dyna_var_idx_at_raw(
const rb_iseq_t *iseq,
ID id)
1548 for (i = 0; i < ISEQ_BODY(iseq)->local_table_size; i++) {
1549 if (ISEQ_BODY(iseq)->local_table[i] == id) {
1559 int idx = get_dyna_var_idx_at_raw(ISEQ_BODY(iseq)->local_iseq,
id);
1562 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
1563 "get_local_var_idx: %d", idx);
1570get_dyna_var_idx(
const rb_iseq_t *iseq,
ID id,
int *level,
int *ls)
1572 int lv = 0, idx = -1;
1573 const rb_iseq_t *
const topmost_iseq = iseq;
1576 idx = get_dyna_var_idx_at_raw(iseq,
id);
1580 iseq = ISEQ_BODY(iseq)->parent_iseq;
1585 COMPILE_ERROR(topmost_iseq, ISEQ_LAST_LINE(topmost_iseq),
1586 "get_dyna_var_idx: -1");
1590 *ls = ISEQ_BODY(iseq)->local_table_size;
1595iseq_local_block_param_p(
const rb_iseq_t *iseq,
unsigned int idx,
unsigned int level)
1599 iseq = ISEQ_BODY(iseq)->parent_iseq;
1602 body = ISEQ_BODY(iseq);
1603 if (body->local_iseq == iseq &&
1604 body->param.flags.has_block &&
1605 body->local_table_size - body->param.block_start == idx) {
1614iseq_block_param_id_p(
const rb_iseq_t *iseq,
ID id,
int *pidx,
int *plevel)
1617 int idx = get_dyna_var_idx(iseq,
id, &level, &ls);
1618 if (iseq_local_block_param_p(iseq, ls - idx, level)) {
1629access_outer_variables(
const rb_iseq_t *iseq,
int level,
ID id,
bool write)
1631 int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
1633 if (isolated_depth && level >= isolated_depth) {
1634 if (
id == rb_intern(
"yield")) {
1635 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
"can not yield from isolated Proc");
1638 COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
"can not access variable `%s' from isolated Proc",
rb_id2name(
id));
1642 for (
int i=0; i<level; i++) {
1644 struct rb_id_table *ovs = ISEQ_BODY(iseq)->outer_variables;
1647 ovs = ISEQ_BODY(iseq)->outer_variables = rb_id_table_create(8);
1650 if (rb_id_table_lookup(ISEQ_BODY(iseq)->outer_variables,
id, &val)) {
1651 if (write && !val) {
1652 rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables,
id,
Qtrue);
1656 rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables,
id, RBOOL(write));
1659 iseq = ISEQ_BODY(iseq)->parent_iseq;
1664iseq_lvar_id(
const rb_iseq_t *iseq,
int idx,
int level)
1666 for (
int i=0; i<level; i++) {
1667 iseq = ISEQ_BODY(iseq)->parent_iseq;
1670 ID id = ISEQ_BODY(iseq)->local_table[ISEQ_BODY(iseq)->local_table_size - idx];
1678 if (iseq_local_block_param_p(iseq, idx, level)) {
1679 ADD_INSN2(seq, line_node, getblockparam,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1682 ADD_INSN2(seq, line_node, getlocal,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1684 if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level),
Qfalse);
1690 if (iseq_local_block_param_p(iseq, idx, level)) {
1691 ADD_INSN2(seq, line_node, setblockparam,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1694 ADD_INSN2(seq, line_node, setlocal,
INT2FIX((idx) + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
1696 if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level),
Qtrue);
1705 if (body->param.flags.has_opt ||
1706 body->param.flags.has_post ||
1707 body->param.flags.has_rest ||
1708 body->param.flags.has_block ||
1709 body->param.flags.has_kw ||
1710 body->param.flags.has_kwrest) {
1712 if (body->param.flags.has_block) {
1713 body->param.size = body->param.block_start + 1;
1715 else if (body->param.flags.has_kwrest) {
1716 body->param.size = body->param.keyword->rest_start + 1;
1718 else if (body->param.flags.has_kw) {
1719 body->param.size = body->param.keyword->bits_start + 1;
1721 else if (body->param.flags.has_post) {
1722 body->param.size = body->param.post_start + body->param.post_num;
1724 else if (body->param.flags.has_rest) {
1725 body->param.size = body->param.rest_start + 1;
1727 else if (body->param.flags.has_opt) {
1728 body->param.size = body->param.lead_num + body->param.opt_num;
1735 body->param.size = body->param.lead_num;
1743 const NODE *node = args->kw_args;
1745 struct rb_iseq_param_keyword *keyword;
1746 const VALUE default_values = rb_ary_hidden_new(1);
1748 int kw = 0, rkw = 0, di = 0, i;
1750 body->param.flags.has_kw = TRUE;
1751 body->param.keyword = keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
1755 node = node->nd_next;
1758 keyword->bits_start = arg_size++;
1760 node = args->kw_args;
1762 const NODE *val_node = node->nd_body->nd_value;
1765 if (val_node == NODE_SPECIAL_REQUIRED_KEYWORD) {
1769 switch (nd_type(val_node)) {
1771 dv = val_node->nd_lit;
1783 NO_CHECK(COMPILE_POPPED(optargs,
"kwarg", node));
1787 keyword->num = ++di;
1788 rb_ary_push(default_values, dv);
1791 node = node->nd_next;
1796 if (args->kw_rest_arg->nd_vid != 0) {
1797 keyword->rest_start = arg_size++;
1798 body->param.flags.has_kwrest = TRUE;
1800 keyword->required_num = rkw;
1801 keyword->table = &body->local_table[keyword->bits_start - keyword->num];
1806 for (i = 0; i <
RARRAY_LEN(default_values); i++) {
1808 if (dv == complex_mark) dv =
Qundef;
1815 keyword->default_values = dvs;
1823 debugs(
"iseq_set_arguments: %s\n", node_args ?
"" :
"0");
1833 EXPECT_NODE(
"iseq_set_arguments", node_args, NODE_ARGS, COMPILE_NG);
1835 body->param.flags.ruby2_keywords = args->ruby2_keywords;
1836 body->param.lead_num = arg_size = (int)args->pre_args_num;
1837 if (body->param.lead_num > 0) body->param.flags.has_lead = TRUE;
1838 debugs(
" - argc: %d\n", body->param.lead_num);
1840 rest_id = args->rest_arg;
1841 if (rest_id == NODE_SPECIAL_EXCESSIVE_COMMA) {
1845 block_id = args->block_arg;
1847 if (args->opt_args) {
1848 const NODE *node = args->opt_args;
1850 VALUE labels = rb_ary_hidden_new(1);
1855 label = NEW_LABEL(nd_line(node));
1856 rb_ary_push(labels, (
VALUE)label | 1);
1857 ADD_LABEL(optargs, label);
1858 NO_CHECK(COMPILE_POPPED(optargs,
"optarg", node->nd_body));
1859 node = node->nd_next;
1864 label = NEW_LABEL(nd_line(node_args));
1865 rb_ary_push(labels, (
VALUE)label | 1);
1866 ADD_LABEL(optargs, label);
1871 for (j = 0; j < i+1; j++) {
1874 rb_ary_clear(labels);
1876 body->param.flags.has_opt = TRUE;
1877 body->param.opt_num = i;
1878 body->param.opt_table = opt_table;
1883 body->param.rest_start = arg_size++;
1884 body->param.flags.has_rest = TRUE;
1885 assert(body->param.rest_start != -1);
1888 if (args->first_post_arg) {
1889 body->param.post_start = arg_size;
1890 body->param.post_num = args->post_args_num;
1891 body->param.flags.has_post = TRUE;
1892 arg_size += args->post_args_num;
1894 if (body->param.flags.has_rest) {
1895 body->param.post_start = body->param.rest_start + 1;
1899 if (args->kw_args) {
1900 arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size);
1902 else if (args->kw_rest_arg) {
1903 struct rb_iseq_param_keyword *keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
1904 keyword->rest_start = arg_size++;
1905 body->param.keyword = keyword;
1906 body->param.flags.has_kwrest = TRUE;
1908 else if (args->no_kwarg) {
1909 body->param.flags.accepts_no_kwarg = TRUE;
1913 body->param.block_start = arg_size++;
1914 body->param.flags.has_block = TRUE;
1917 iseq_calc_param_size(iseq);
1918 body->param.size = arg_size;
1920 if (args->pre_init) {
1921 NO_CHECK(COMPILE_POPPED(optargs,
"init arguments (m)", args->pre_init));
1923 if (args->post_init) {
1924 NO_CHECK(COMPILE_POPPED(optargs,
"init arguments (p)", args->post_init));
1927 if (body->type == ISEQ_TYPE_BLOCK) {
1928 if (body->param.flags.has_opt == FALSE &&
1929 body->param.flags.has_post == FALSE &&
1930 body->param.flags.has_rest == FALSE &&
1931 body->param.flags.has_kw == FALSE &&
1932 body->param.flags.has_kwrest == FALSE) {
1934 if (body->param.lead_num == 1 && last_comma == 0) {
1936 body->param.flags.ambiguous_param0 = TRUE;
1948 unsigned int size = tbl ? tbl->size : 0;
1953 ISEQ_BODY(iseq)->local_table = ids;
1955 ISEQ_BODY(iseq)->local_table_size = size;
1957 debugs(
"iseq_set_local_table: %u\n", ISEQ_BODY(iseq)->local_table_size);
1969 else if ((tlit = OBJ_BUILTIN_TYPE(lit)) == -1) {
1972 else if ((tval = OBJ_BUILTIN_TYPE(val)) == -1) {
1975 else if (tlit != tval) {
1985 long x =
FIX2LONG(rb_big_cmp(lit, val));
1993 return rb_float_cmp(lit, val);
1996 const struct RRational *rat1 = RRATIONAL(val);
1997 const struct RRational *rat2 = RRATIONAL(lit);
1998 return rb_iseq_cdhash_cmp(rat1->num, rat2->num) || rb_iseq_cdhash_cmp(rat1->den, rat2->den);
2001 const struct RComplex *comp1 = RCOMPLEX(val);
2002 const struct RComplex *comp2 = RCOMPLEX(lit);
2003 return rb_iseq_cdhash_cmp(comp1->real, comp2->real) || rb_iseq_cdhash_cmp(comp1->imag, comp2->imag);
2006 return rb_reg_equal(val, lit) ? 0 : -1;
2014rb_iseq_cdhash_hash(
VALUE a)
2016 switch (OBJ_BUILTIN_TYPE(a)) {
2019 return (st_index_t)a;
2027 return rb_rational_hash(a);
2029 return rb_complex_hash(a);
2039 rb_iseq_cdhash_hash,
2053 rb_hash_aset(data->hash, key,
INT2FIX(lobj->position - (data->pos+data->len)));
2061 return INT2FIX(ISEQ_BODY(iseq)->ivc_size++);
2068 struct rb_id_table *tbl = ISEQ_COMPILE_DATA(iseq)->ivar_cache_table;
2070 if (rb_id_table_lookup(tbl,
id,&val)) {
2075 tbl = rb_id_table_create(1);
2076 ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
2078 val =
INT2FIX(ISEQ_BODY(iseq)->icvarc_size++);
2079 rb_id_table_insert(tbl,
id,val);
2083#define BADINSN_DUMP(anchor, list, dest) \
2084 dump_disasm_list_with_cursor(FIRST_ELEMENT(anchor), list, dest)
2086#define BADINSN_ERROR \
2087 (xfree(generated_iseq), \
2088 xfree(insns_info), \
2089 BADINSN_DUMP(anchor, list, NULL), \
2095 int stack_max = 0, sp = 0, line = 0;
2098 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2099 if (IS_LABEL(list)) {
2105 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2106 switch (list->type) {
2107 case ISEQ_ELEMENT_INSN:
2115 sp = calc_sp_depth(sp, iobj);
2117 BADINSN_DUMP(anchor, list, NULL);
2118 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2119 "argument stack underflow (%d)", sp);
2122 if (sp > stack_max) {
2126 line = iobj->insn_info.line_no;
2128 operands = iobj->operands;
2129 insn = iobj->insn_id;
2130 types = insn_op_types(insn);
2131 len = insn_len(insn);
2134 if (iobj->operand_size != len - 1) {
2136 BADINSN_DUMP(anchor, list, NULL);
2137 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2138 "operand size miss! (%d for %d)",
2139 iobj->operand_size, len - 1);
2143 for (j = 0; types[j]; j++) {
2144 if (types[j] == TS_OFFSET) {
2148 BADINSN_DUMP(anchor, list, NULL);
2149 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2150 "unknown label: "LABEL_FORMAT, lobj->label_no);
2153 if (lobj->sp == -1) {
2156 else if (lobj->sp != sp) {
2157 debugs(
"%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2158 RSTRING_PTR(rb_iseq_path(iseq)), line,
2159 lobj->label_no, lobj->sp, sp);
2165 case ISEQ_ELEMENT_LABEL:
2168 if (lobj->sp == -1) {
2172 if (lobj->sp != sp) {
2173 debugs(
"%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2174 RSTRING_PTR(rb_iseq_path(iseq)), line,
2175 lobj->label_no, lobj->sp, sp);
2181 case ISEQ_ELEMENT_TRACE:
2186 case ISEQ_ELEMENT_ADJUST:
2191 sp = adjust->label ? adjust->label->sp : 0;
2192 if (adjust->line_no != -1 && orig_sp - sp < 0) {
2193 BADINSN_DUMP(anchor, list, NULL);
2194 COMPILE_ERROR(iseq, adjust->line_no,
2195 "iseq_set_sequence: adjust bug %d < %d",
2202 BADINSN_DUMP(anchor, list, NULL);
2203 COMPILE_ERROR(iseq, line,
"unknown list type: %d", list->type);
2212 int insns_info_index,
int code_index,
const INSN *iobj)
2214 if (insns_info_index == 0 ||
2215 insns_info[insns_info_index-1].line_no != iobj->insn_info.line_no ||
2216#ifdef USE_ISEQ_NODE_ID
2217 insns_info[insns_info_index-1].node_id != iobj->insn_info.node_id ||
2219 insns_info[insns_info_index-1].events != iobj->insn_info.events) {
2220 insns_info[insns_info_index].line_no = iobj->insn_info.line_no;
2221#ifdef USE_ISEQ_NODE_ID
2222 insns_info[insns_info_index].node_id = iobj->insn_info.node_id;
2224 insns_info[insns_info_index].events = iobj->insn_info.events;
2225 positions[insns_info_index] = code_index;
2233 int insns_info_index,
int code_index,
const ADJUST *adjust)
2235 insns_info[insns_info_index].line_no = adjust->line_no;
2236 insns_info[insns_info_index].events = 0;
2237 positions[insns_info_index] = code_index;
2242array_to_idlist(
VALUE arr)
2247 for (
int i = 0; i < size; i++) {
2256idlist_to_array(
const ID *ids)
2258 VALUE arr = rb_ary_new();
2260 rb_ary_push(arr,
ID2SYM(*ids++));
2273 unsigned int *positions;
2275 VALUE *generated_iseq;
2279 int insn_num, code_index, insns_info_index, sp = 0;
2280 int stack_max = fix_sp_depth(iseq, anchor);
2282 if (stack_max < 0)
return COMPILE_NG;
2285 insn_num = code_index = 0;
2286 for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
2287 switch (list->type) {
2288 case ISEQ_ELEMENT_INSN:
2292 sp = calc_sp_depth(sp, iobj);
2294 events = iobj->insn_info.events |= events;
2295 if (ISEQ_COVERAGE(iseq)) {
2296 if (ISEQ_LINE_COVERAGE(iseq) && (events & RUBY_EVENT_COVERAGE_LINE) &&
2297 !(rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES)) {
2298 int line = iobj->insn_info.line_no - 1;
2299 if (line >= 0 && line <
RARRAY_LEN(ISEQ_LINE_COVERAGE(iseq))) {
2300 RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), line,
INT2FIX(0));
2303 if (ISEQ_BRANCH_COVERAGE(iseq) && (events & RUBY_EVENT_COVERAGE_BRANCH)) {
2304 while (
RARRAY_LEN(ISEQ_PC2BRANCHINDEX(iseq)) <= code_index) {
2305 rb_ary_push(ISEQ_PC2BRANCHINDEX(iseq),
Qnil);
2307 RARRAY_ASET(ISEQ_PC2BRANCHINDEX(iseq), code_index,
INT2FIX(data));
2310 code_index += insn_data_length(iobj);
2315 case ISEQ_ELEMENT_LABEL:
2318 lobj->position = code_index;
2319 if (lobj->sp != sp) {
2320 debugs(
"%s: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2321 RSTRING_PTR(rb_iseq_path(iseq)),
2322 lobj->label_no, lobj->sp, sp);
2327 case ISEQ_ELEMENT_TRACE:
2330 events |= trace->event;
2331 if (trace->event & RUBY_EVENT_COVERAGE_BRANCH) data = trace->data;
2334 case ISEQ_ELEMENT_ADJUST:
2337 if (adjust->line_no != -1) {
2339 sp = adjust->label ? adjust->label->sp : 0;
2340 if (orig_sp - sp > 0) {
2341 if (orig_sp - sp > 1) code_index++;
2355 positions =
ALLOC_N(
unsigned int, insn_num);
2358 ISEQ_COMPILE_DATA(iseq)->ci_index = 0;
2365 iseq_bits_t * mark_offset_bits;
2366 int code_size = code_index;
2368 iseq_bits_t tmp[1] = {0};
2369 bool needs_bitmap =
false;
2371 if (ISEQ_MBITS_BUFLEN(code_index) == 1) {
2372 mark_offset_bits = tmp;
2375 mark_offset_bits =
ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(code_index));
2378 list = FIRST_ELEMENT(anchor);
2379 insns_info_index = code_index = sp = 0;
2382 switch (list->type) {
2383 case ISEQ_ELEMENT_INSN:
2391 sp = calc_sp_depth(sp, iobj);
2393 operands = iobj->operands;
2394 insn = iobj->insn_id;
2395 generated_iseq[code_index] = insn;
2396 types = insn_op_types(insn);
2397 len = insn_len(insn);
2399 for (j = 0; types[j]; j++) {
2400 char type = types[j];
2408 generated_iseq[code_index + 1 + j] = lobj->position - (code_index + len);
2413 VALUE map = operands[j];
2416 data.pos = code_index;
2418 rb_hash_foreach(map, cdhash_set_label_i, (
VALUE)&data);
2420 rb_hash_rehash(map);
2421 freeze_hide_obj(map);
2422 generated_iseq[code_index + 1 + j] = map;
2423 ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
2425 needs_bitmap =
true;
2430 generated_iseq[code_index + 1 + j] =
FIX2INT(operands[j]);
2435 VALUE v = operands[j];
2436 generated_iseq[code_index + 1 + j] = v;
2440 ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
2441 needs_bitmap =
true;
2448 unsigned int ic_index = ISEQ_COMPILE_DATA(iseq)->ic_index++;
2449 IC ic = &ISEQ_IS_ENTRY_START(body,
type)[ic_index].ic_cache;
2450 if (UNLIKELY(ic_index >= body->ic_size)) {
2451 BADINSN_DUMP(anchor, &iobj->link, 0);
2452 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2453 "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
2454 ic_index, ISEQ_IS_SIZE(body));
2457 ic->segments = array_to_idlist(operands[j]);
2459 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
2464 unsigned int ic_index =
FIX2UINT(operands[j]);
2466 IVC cache = ((
IVC)&body->is_entries[ic_index]);
2468 if (insn == BIN(setinstancevariable)) {
2469 cache->iv_set_name =
SYM2ID(operands[j - 1]);
2472 cache->iv_set_name = 0;
2475 vm_ic_attr_index_initialize(cache, INVALID_SHAPE_ID);
2480 unsigned int ic_index =
FIX2UINT(operands[j]);
2481 IC ic = &ISEQ_IS_ENTRY_START(body,
type)[ic_index].ic_cache;
2482 if (UNLIKELY(ic_index >= ISEQ_IS_SIZE(body))) {
2483 BADINSN_DUMP(anchor, &iobj->link, 0);
2484 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
2485 "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
2486 ic_index, ISEQ_IS_SIZE(body));
2488 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
2495 struct rb_call_data *cd = &body->call_data[ISEQ_COMPILE_DATA(iseq)->ci_index++];
2496 assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size);
2498 cd->cc = vm_cc_empty();
2499 generated_iseq[code_index + 1 + j] = (
VALUE)cd;
2503 generated_iseq[code_index + 1 + j] =
SYM2ID(operands[j]);
2506 generated_iseq[code_index + 1 + j] = operands[j];
2509 generated_iseq[code_index + 1 + j] = operands[j];
2512 BADINSN_ERROR(iseq, iobj->insn_info.line_no,
2513 "unknown operand type: %c",
type);
2517 if (add_insn_info(insns_info, positions, insns_info_index, code_index, iobj)) insns_info_index++;
2521 case ISEQ_ELEMENT_LABEL:
2524 if (lobj->sp != sp) {
2525 debugs(
"%s: sp inconsistency found but ignored (" LABEL_FORMAT
" sp: %d, calculated sp: %d)\n",
2526 RSTRING_PTR(rb_iseq_path(iseq)),
2527 lobj->label_no, lobj->sp, sp);
2532 case ISEQ_ELEMENT_ADJUST:
2537 if (adjust->label) {
2538 sp = adjust->label->sp;
2544 if (adjust->line_no != -1) {
2545 const int diff = orig_sp - sp;
2547 if (insns_info_index == 0) {
2548 COMPILE_ERROR(iseq, adjust->line_no,
2549 "iseq_set_sequence: adjust bug (ISEQ_ELEMENT_ADJUST must not be the first in iseq)");
2551 if (add_adjust_info(insns_info, positions, insns_info_index, code_index, adjust)) insns_info_index++;
2554 generated_iseq[code_index++] = BIN(adjuststack);
2555 generated_iseq[code_index++] = orig_sp - sp;
2557 else if (diff == 1) {
2558 generated_iseq[code_index++] = BIN(pop);
2560 else if (diff < 0) {
2561 int label_no = adjust->label ? adjust->label->label_no : -1;
2562 xfree(generated_iseq);
2565 if (ISEQ_MBITS_BUFLEN(code_size) > 1) {
2566 xfree(mark_offset_bits);
2568 debug_list(anchor, list);
2569 COMPILE_ERROR(iseq, adjust->line_no,
2570 "iseq_set_sequence: adjust bug to %d %d < %d",
2571 label_no, orig_sp, sp);
2584 body->iseq_encoded = (
void *)generated_iseq;
2585 body->iseq_size = code_index;
2586 body->stack_max = stack_max;
2588 if (ISEQ_MBITS_BUFLEN(body->iseq_size) == 1) {
2589 body->mark_bits.single = mark_offset_bits[0];
2593 body->mark_bits.list = mark_offset_bits;
2596 body->mark_bits.list = 0;
2597 ruby_xfree(mark_offset_bits);
2602 body->insns_info.body = insns_info;
2603 body->insns_info.positions = positions;
2606 body->insns_info.body = insns_info;
2607 REALLOC_N(positions,
unsigned int, insns_info_index);
2608 body->insns_info.positions = positions;
2609 body->insns_info.size = insns_info_index;
2615label_get_position(
LABEL *lobj)
2617 return lobj->position;
2621label_get_sp(
LABEL *lobj)
2627iseq_set_exception_table(
rb_iseq_t *iseq)
2629 const VALUE *tptr, *ptr;
2630 unsigned int tlen, i;
2633 ISEQ_BODY(iseq)->catch_table = NULL;
2634 if (
NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary))
return COMPILE_OK;
2635 tlen = (int)
RARRAY_LEN(ISEQ_COMPILE_DATA(iseq)->catch_table_ary);
2642 for (i = 0; i < table->size; i++) {
2644 entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
2645 entry->type = (
enum rb_catch_type)(ptr[0] & 0xffff);
2646 entry->start = label_get_position((
LABEL *)(ptr[1] & ~1));
2647 entry->end = label_get_position((
LABEL *)(ptr[2] & ~1));
2654 entry->cont = label_get_position(lobj);
2655 entry->sp = label_get_sp(lobj);
2658 if (entry->type == CATCH_TYPE_RESCUE ||
2659 entry->type == CATCH_TYPE_BREAK ||
2660 entry->type == CATCH_TYPE_NEXT) {
2668 ISEQ_BODY(iseq)->catch_table = table;
2669 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0);
2688 VALUE *opt_table = (
VALUE *)ISEQ_BODY(iseq)->param.opt_table;
2690 if (ISEQ_BODY(iseq)->param.flags.has_opt) {
2691 for (i = 0; i < ISEQ_BODY(iseq)->param.opt_num + 1; i++) {
2692 opt_table[i] = label_get_position((
LABEL *)opt_table[i]);
2699get_destination_insn(
INSN *iobj)
2705 list = lobj->link.next;
2707 switch (list->type) {
2708 case ISEQ_ELEMENT_INSN:
2709 case ISEQ_ELEMENT_ADJUST:
2711 case ISEQ_ELEMENT_LABEL:
2714 case ISEQ_ELEMENT_TRACE:
2717 events |= trace->event;
2725 if (list && IS_INSN(list)) {
2727 iobj->insn_info.events |= events;
2733get_next_insn(
INSN *iobj)
2738 if (IS_INSN(list) || IS_ADJUST(list)) {
2747get_prev_insn(
INSN *iobj)
2752 if (IS_INSN(list) || IS_ADJUST(list)) {
2761unref_destination(
INSN *iobj,
int pos)
2763 LABEL *lobj = (
LABEL *)OPERAND_AT(iobj, pos);
2765 if (!lobj->refcnt) ELEM_REMOVE(&lobj->link);
2769replace_destination(
INSN *dobj,
INSN *nobj)
2771 VALUE n = OPERAND_AT(nobj, 0);
2776 OPERAND_AT(dobj, 0) = n;
2777 if (!dl->refcnt) ELEM_REMOVE(&dl->link);
2781find_destination(
INSN *i)
2783 int pos, len = insn_len(i->insn_id);
2784 for (pos = 0; pos < len; ++pos) {
2785 if (insn_op_types(i->insn_id)[pos] == TS_OFFSET) {
2786 return (
LABEL *)OPERAND_AT(i, pos);
2796 int *unref_counts = 0, nlabels = ISEQ_COMPILE_DATA(iseq)->label_no;
2799 unref_counts =
ALLOCA_N(
int, nlabels);
2800 MEMZERO(unref_counts,
int, nlabels);
2805 if (IS_INSN_ID(i, leave)) {
2809 else if ((lab = find_destination((
INSN *)i)) != 0) {
2810 if (lab->unremovable)
break;
2811 unref_counts[lab->label_no]++;
2814 else if (IS_LABEL(i)) {
2816 if (lab->unremovable)
return 0;
2817 if (lab->refcnt > unref_counts[lab->label_no]) {
2818 if (i == first)
return 0;
2823 else if (IS_TRACE(i)) {
2826 else if (IS_ADJUST(i)) {
2828 if (dest && dest->unremovable)
return 0;
2831 }
while ((i = i->next) != 0);
2836 VALUE insn = INSN_OF(i);
2837 int pos, len = insn_len(insn);
2838 for (pos = 0; pos < len; ++pos) {
2839 switch (insn_op_types(insn)[pos]) {
2841 unref_destination((
INSN *)i, pos);
2850 }
while ((i != end) && (i = i->next) != 0);
2857 switch (OPERAND_AT(iobj, 0)) {
2859 ELEM_REMOVE(&iobj->link);
2862 ELEM_REMOVE(&iobj->link);
2865 iobj->insn_id = BIN(adjuststack);
2871is_frozen_putstring(
INSN *insn,
VALUE *op)
2873 if (IS_INSN_ID(insn, putstring)) {
2874 *op = OPERAND_AT(insn, 0);
2877 else if (IS_INSN_ID(insn, putobject)) {
2878 *op = OPERAND_AT(insn, 0);
2909 INSN *niobj, *ciobj, *dup = 0;
2913 switch (INSN_OF(iobj)) {
2914 case BIN(putstring):
2920 case BIN(putobject):
2923 default:
return FALSE;
2926 ciobj = (
INSN *)get_next_insn(iobj);
2927 if (IS_INSN_ID(ciobj, jump)) {
2928 ciobj = (
INSN *)get_next_insn((
INSN*)OPERAND_AT(ciobj, 0));
2930 if (IS_INSN_ID(ciobj, dup)) {
2931 ciobj = (
INSN *)get_next_insn(dup = ciobj);
2933 if (!ciobj || !IS_INSN_ID(ciobj, checktype))
return FALSE;
2934 niobj = (
INSN *)get_next_insn(ciobj);
2939 switch (INSN_OF(niobj)) {
2941 if (OPERAND_AT(ciobj, 0) ==
type) {
2942 dest = (
LABEL *)OPERAND_AT(niobj, 0);
2945 case BIN(branchunless):
2946 if (OPERAND_AT(ciobj, 0) !=
type) {
2947 dest = (
LABEL *)OPERAND_AT(niobj, 0);
2953 line = ciobj->insn_info.line_no;
2954 node_id = ciobj->insn_info.node_id;
2955 NODE dummy_line_node = generate_dummy_line_node(line, node_id);
2957 if (niobj->link.next && IS_LABEL(niobj->link.next)) {
2958 dest = (
LABEL *)niobj->link.next;
2961 dest = NEW_LABEL(line);
2962 ELEM_INSERT_NEXT(&niobj->link, &dest->link);
2965 INSERT_AFTER_INSN1(iobj, &dummy_line_node, jump, dest);
2967 if (!dup) INSERT_AFTER_INSN(iobj, &dummy_line_node, pop);
2974 const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
2975 vm_ci_flag(ci) | add,
2985 const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
2999 optimize_checktype(iseq, iobj);
3001 if (IS_INSN_ID(iobj, jump)) {
3002 INSN *niobj, *diobj, *piobj;
3003 diobj = (
INSN *)get_destination_insn(iobj);
3004 niobj = (
INSN *)get_next_insn(iobj);
3006 if (diobj == niobj) {
3013 unref_destination(iobj, 0);
3014 ELEM_REMOVE(&iobj->link);
3017 else if (iobj != diobj && IS_INSN(&diobj->link) &&
3018 IS_INSN_ID(diobj, jump) &&
3019 OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0) &&
3020 diobj->insn_info.events == 0) {
3031 replace_destination(iobj, diobj);
3032 remove_unreachable_chunk(iseq, iobj->link.next);
3035 else if (IS_INSN_ID(diobj, leave)) {
3048 unref_destination(iobj, 0);
3049 iobj->insn_id = BIN(leave);
3050 iobj->operand_size = 0;
3051 iobj->insn_info = diobj->insn_info;
3054 else if (IS_INSN(iobj->link.prev) &&
3055 (piobj = (
INSN *)iobj->link.prev) &&
3056 (IS_INSN_ID(piobj, branchif) ||
3057 IS_INSN_ID(piobj, branchunless))) {
3058 INSN *pdiobj = (
INSN *)get_destination_insn(piobj);
3059 if (niobj == pdiobj) {
3060 int refcnt = IS_LABEL(piobj->link.next) ?
3061 ((
LABEL *)piobj->link.next)->refcnt : 0;
3076 piobj->insn_id = (IS_INSN_ID(piobj, branchif))
3077 ? BIN(branchunless) : BIN(branchif);
3078 replace_destination(piobj, iobj);
3080 ELEM_REMOVE(&iobj->link);
3087 else if (diobj == pdiobj) {
3101 NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
3102 INSN *popiobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, 0);
3103 ELEM_REPLACE(&piobj->link, &popiobj->link);
3106 if (remove_unreachable_chunk(iseq, iobj->link.next)) {
3120 if (IS_INSN_ID(iobj, newrange)) {
3121 INSN *
const range = iobj;
3123 VALUE str_beg, str_end;
3125 if ((end = (
INSN *)get_prev_insn(range)) != 0 &&
3126 is_frozen_putstring(end, &str_end) &&
3127 (beg = (
INSN *)get_prev_insn(end)) != 0 &&
3128 is_frozen_putstring(beg, &str_beg)) {
3129 int excl =
FIX2INT(OPERAND_AT(range, 0));
3132 ELEM_REMOVE(&beg->link);
3133 ELEM_REMOVE(&end->link);
3134 range->insn_id = BIN(putobject);
3135 OPERAND_AT(range, 0) = lit_range;
3140 if (IS_INSN_ID(iobj, leave)) {
3141 remove_unreachable_chunk(iseq, iobj->link.next);
3153 if (IS_INSN_ID(iobj, duparray)) {
3155 if (IS_INSN(next) && IS_INSN_ID(next, concatarray)) {
3156 iobj->insn_id = BIN(putobject);
3160 if (IS_INSN_ID(iobj, branchif) ||
3161 IS_INSN_ID(iobj, branchnil) ||
3162 IS_INSN_ID(iobj, branchunless)) {
3171 INSN *nobj = (
INSN *)get_destination_insn(iobj);
3193 int stop_optimization =
3194 ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq) &&
3195 nobj->link.type == ISEQ_ELEMENT_INSN &&
3196 nobj->insn_info.events;
3197 if (!stop_optimization) {
3198 INSN *pobj = (
INSN *)iobj->link.prev;
3201 if (!IS_INSN(&pobj->link))
3203 else if (IS_INSN_ID(pobj, dup))
3208 if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) {
3209 replace_destination(iobj, nobj);
3211 else if (prev_dup && IS_INSN_ID(nobj, dup) &&
3212 !!(nobj = (
INSN *)nobj->link.next) &&
3214 nobj->insn_id == iobj->insn_id) {
3230 replace_destination(iobj, nobj);
3258 if (prev_dup && IS_INSN(pobj->link.prev)) {
3259 pobj = (
INSN *)pobj->link.prev;
3261 if (IS_INSN_ID(pobj, putobject)) {
3262 cond = (IS_INSN_ID(iobj, branchif) ?
3263 OPERAND_AT(pobj, 0) !=
Qfalse :
3264 IS_INSN_ID(iobj, branchunless) ?
3265 OPERAND_AT(pobj, 0) ==
Qfalse :
3268 else if (IS_INSN_ID(pobj, putstring) ||
3269 IS_INSN_ID(pobj, duparray) ||
3270 IS_INSN_ID(pobj, newarray)) {
3271 cond = IS_INSN_ID(iobj, branchif);
3273 else if (IS_INSN_ID(pobj, putnil)) {
3274 cond = !IS_INSN_ID(iobj, branchif);
3277 if (prev_dup || !IS_INSN_ID(pobj, newarray)) {
3278 ELEM_REMOVE(iobj->link.prev);
3280 else if (!iseq_pop_newarray(iseq, pobj)) {
3281 NODE dummy_line_node = generate_dummy_line_node(pobj->insn_info.line_no, pobj->insn_info.node_id);
3282 pobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, NULL);
3283 ELEM_INSERT_PREV(&iobj->link, &pobj->link);
3287 NODE dummy_line_node = generate_dummy_line_node(pobj->insn_info.line_no, pobj->insn_info.node_id);
3288 pobj = new_insn_core(iseq, &dummy_line_node, BIN(putnil), 0, NULL);
3289 ELEM_INSERT_NEXT(&iobj->link, &pobj->link);
3291 iobj->insn_id = BIN(jump);
3295 unref_destination(iobj, 0);
3296 ELEM_REMOVE(&iobj->link);
3301 nobj = (
INSN *)get_destination_insn(nobj);
3306 if (IS_INSN_ID(iobj, pop)) {
3314 if (IS_INSN(prev)) {
3315 enum ruby_vminsn_type previ = ((
INSN *)prev)->insn_id;
3316 if (previ == BIN(putobject) || previ == BIN(putnil) ||
3317 previ == BIN(putself) || previ == BIN(putstring) ||
3318 previ == BIN(dup) ||
3319 previ == BIN(getlocal) ||
3320 previ == BIN(getblockparam) ||
3321 previ == BIN(getblockparamproxy) ||
3323 previ == BIN(duparray)) {
3327 ELEM_REMOVE(&iobj->link);
3329 else if (previ == BIN(newarray) && iseq_pop_newarray(iseq, (
INSN*)prev)) {
3330 ELEM_REMOVE(&iobj->link);
3332 else if (previ == BIN(concatarray)) {
3334 NODE dummy_line_node = generate_dummy_line_node(piobj->insn_info.line_no, piobj->insn_info.node_id);
3335 INSERT_BEFORE_INSN1(piobj, &dummy_line_node, splatarray,
Qfalse);
3336 INSN_OF(piobj) = BIN(pop);
3338 else if (previ == BIN(concatstrings)) {
3339 if (OPERAND_AT(prev, 0) ==
INT2FIX(1)) {
3343 ELEM_REMOVE(&iobj->link);
3344 INSN_OF(prev) = BIN(adjuststack);
3350 if (IS_INSN_ID(iobj, newarray) ||
3351 IS_INSN_ID(iobj, duparray) ||
3352 IS_INSN_ID(iobj, expandarray) ||
3353 IS_INSN_ID(iobj, concatarray) ||
3354 IS_INSN_ID(iobj, splatarray) ||
3364 if (IS_INSN(next) && IS_INSN_ID(next, splatarray)) {
3370 if (IS_INSN_ID(iobj, newarray)) {
3372 if (IS_INSN(next) && IS_INSN_ID(next, expandarray) &&
3373 OPERAND_AT(next, 1) ==
INT2FIX(0)) {
3375 op1 = OPERAND_AT(iobj, 0);
3376 op2 = OPERAND_AT(next, 0);
3387 INSN_OF(iobj) = BIN(swap);
3388 iobj->operand_size = 0;
3397 INSN_OF(iobj) = BIN(opt_reverse);
3401 NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
3403 INSN_OF(iobj) = BIN(opt_reverse);
3404 OPERAND_AT(iobj, 0) = OPERAND_AT(next, 0);
3414 for (; diff > 0; diff--) {
3415 INSERT_BEFORE_INSN(iobj, &dummy_line_node, pop);
3426 for (; diff < 0; diff++) {
3427 INSERT_BEFORE_INSN(iobj, &dummy_line_node, putnil);
3434 if (IS_INSN_ID(iobj, duparray)) {
3443 if (IS_INSN(next) && IS_INSN_ID(next, expandarray)) {
3444 INSN_OF(iobj) = BIN(putobject);
3448 if (IS_INSN_ID(iobj, anytostring)) {
3456 if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) &&
3457 OPERAND_AT(next, 0) ==
INT2FIX(1)) {
3462 if (IS_INSN_ID(iobj, putstring) ||
3463 (IS_INSN_ID(iobj, putobject) && RB_TYPE_P(OPERAND_AT(iobj, 0),
T_STRING))) {
3470 if (IS_NEXT_INSN_ID(&iobj->link, concatstrings) &&
3471 RSTRING_LEN(OPERAND_AT(iobj, 0)) == 0) {
3472 INSN *next = (
INSN *)iobj->link.next;
3473 if ((OPERAND_AT(next, 0) = FIXNUM_INC(OPERAND_AT(next, 0), -1)) ==
INT2FIX(1)) {
3474 ELEM_REMOVE(&next->link);
3476 ELEM_REMOVE(&iobj->link);
3480 if (IS_INSN_ID(iobj, concatstrings)) {
3489 if (IS_INSN(next) && IS_INSN_ID(next, jump))
3490 next = get_destination_insn(jump = (
INSN *)next);
3491 if (IS_INSN(next) && IS_INSN_ID(next, concatstrings)) {
3492 int n =
FIX2INT(OPERAND_AT(iobj, 0)) +
FIX2INT(OPERAND_AT(next, 0)) - 1;
3493 OPERAND_AT(iobj, 0) =
INT2FIX(n);
3495 LABEL *label = ((
LABEL *)OPERAND_AT(jump, 0));
3496 if (!--label->refcnt) {
3497 ELEM_REMOVE(&label->link);
3500 label = NEW_LABEL(0);
3501 OPERAND_AT(jump, 0) = (
VALUE)label;
3504 ELEM_INSERT_NEXT(next, &label->link);
3505 CHECK(iseq_peephole_optimize(iseq, get_next_insn(jump), do_tailcallopt));
3513 if (do_tailcallopt &&
3514 (IS_INSN_ID(iobj, send) ||
3515 IS_INSN_ID(iobj, opt_aref_with) ||
3516 IS_INSN_ID(iobj, opt_aset_with) ||
3517 IS_INSN_ID(iobj, invokesuper))) {
3526 if (iobj->link.next) {
3529 if (!IS_INSN(next)) {
3533 switch (INSN_OF(next)) {
3542 next = get_destination_insn((
INSN *)next);
3556 if (IS_INSN_ID(piobj, send) ||
3557 IS_INSN_ID(piobj, invokesuper)) {
3558 if (OPERAND_AT(piobj, 1) == 0) {
3559 ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
3560 OPERAND_AT(piobj, 0) = (
VALUE)ci;
3565 ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
3566 OPERAND_AT(piobj, 0) = (
VALUE)ci;
3572 if (IS_INSN_ID(iobj, dup)) {
3573 if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) {
3584 if (IS_NEXT_INSN_ID(set1, setlocal)) {
3586 if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
3587 OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
3589 ELEM_REMOVE(&iobj->link);
3602 else if (IS_NEXT_INSN_ID(set1, dup) &&
3603 IS_NEXT_INSN_ID(set1->next, setlocal)) {
3604 set2 = set1->next->next;
3605 if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
3606 OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
3607 ELEM_REMOVE(set1->next);
3621 if (IS_INSN_ID(iobj, getlocal)) {
3623 if (IS_NEXT_INSN_ID(niobj, dup)) {
3624 niobj = niobj->next;
3626 if (IS_NEXT_INSN_ID(niobj, setlocal)) {
3628 if (OPERAND_AT(iobj, 0) == OPERAND_AT(set1, 0) &&
3629 OPERAND_AT(iobj, 1) == OPERAND_AT(set1, 1)) {
3645 if (IS_INSN_ID(iobj, opt_invokebuiltin_delegate)) {
3646 if (IS_TRACE(iobj->link.next)) {
3647 if (IS_NEXT_INSN_ID(iobj->link.next, leave)) {
3648 iobj->insn_id = BIN(opt_invokebuiltin_delegate_leave);
3660 if (IS_INSN_ID(iobj, getblockparam)) {
3661 if (IS_NEXT_INSN_ID(&iobj->link, branchif) || IS_NEXT_INSN_ID(&iobj->link, branchunless)) {
3662 iobj->insn_id = BIN(getblockparamproxy);
3670insn_set_specialized_instruction(
rb_iseq_t *iseq,
INSN *iobj,
int insn_id)
3672 iobj->insn_id = insn_id;
3673 iobj->operand_size = insn_len(insn_id) - 1;
3676 if (insn_id == BIN(opt_neq)) {
3677 VALUE original_ci = iobj->operands[0];
3678 iobj->operand_size = 2;
3679 iobj->operands = compile_data_calloc2(iseq, iobj->operand_size,
sizeof(
VALUE));
3680 iobj->operands[0] = (
VALUE)new_callinfo(iseq, idEq, 1, 0, NULL, FALSE);
3681 iobj->operands[1] = original_ci;
3690 if (IS_INSN_ID(iobj, newarray) && iobj->link.next &&
3691 IS_INSN(iobj->link.next)) {
3695 INSN *niobj = (
INSN *)iobj->link.next;
3696 if (IS_INSN_ID(niobj, send)) {
3698 if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) {
3699 switch (vm_ci_mid(ci)) {
3701 iobj->insn_id = BIN(opt_newarray_max);
3702 ELEM_REMOVE(&niobj->link);
3705 iobj->insn_id = BIN(opt_newarray_min);
3706 ELEM_REMOVE(&niobj->link);
3713 if (IS_INSN_ID(iobj, send)) {
3717#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
3718 if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) {
3719 switch (vm_ci_argc(ci)) {
3721 switch (vm_ci_mid(ci)) {
3722 case idLength: SP_INSN(length);
return COMPILE_OK;
3723 case idSize: SP_INSN(size);
return COMPILE_OK;
3724 case idEmptyP: SP_INSN(empty_p);
return COMPILE_OK;
3725 case idNilP: SP_INSN(nil_p);
return COMPILE_OK;
3726 case idSucc: SP_INSN(succ);
return COMPILE_OK;
3727 case idNot: SP_INSN(not);
return COMPILE_OK;
3731 switch (vm_ci_mid(ci)) {
3732 case idPLUS: SP_INSN(plus);
return COMPILE_OK;
3733 case idMINUS: SP_INSN(minus);
return COMPILE_OK;
3734 case idMULT: SP_INSN(mult);
return COMPILE_OK;
3735 case idDIV: SP_INSN(div);
return COMPILE_OK;
3736 case idMOD: SP_INSN(mod);
return COMPILE_OK;
3737 case idEq: SP_INSN(eq);
return COMPILE_OK;
3738 case idNeq: SP_INSN(neq);
return COMPILE_OK;
3739 case idEqTilde:SP_INSN(regexpmatch2);
return COMPILE_OK;
3740 case idLT: SP_INSN(lt);
return COMPILE_OK;
3741 case idLE: SP_INSN(le);
return COMPILE_OK;
3742 case idGT: SP_INSN(gt);
return COMPILE_OK;
3743 case idGE: SP_INSN(ge);
return COMPILE_OK;
3744 case idLTLT: SP_INSN(ltlt);
return COMPILE_OK;
3745 case idAREF: SP_INSN(aref);
return COMPILE_OK;
3746 case idAnd: SP_INSN(and);
return COMPILE_OK;
3747 case idOr: SP_INSN(or);
return COMPILE_OK;
3751 switch (vm_ci_mid(ci)) {
3752 case idASET: SP_INSN(aset);
return COMPILE_OK;
3758 if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) {
3759 iobj->insn_id = BIN(opt_send_without_block);
3760 iobj->operand_size = insn_len(iobj->insn_id) - 1;
3771 switch (ISEQ_BODY(iseq)->
type) {
3773 case ISEQ_TYPE_EVAL:
3774 case ISEQ_TYPE_MAIN:
3776 case ISEQ_TYPE_RESCUE:
3777 case ISEQ_TYPE_ENSURE:
3789 const int do_peepholeopt = ISEQ_COMPILE_DATA(iseq)->option->peephole_optimization;
3790 const int do_tailcallopt = tailcallable_p(iseq) &&
3791 ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization;
3792 const int do_si = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction;
3793 const int do_ou = ISEQ_COMPILE_DATA(iseq)->option->operands_unification;
3794 int rescue_level = 0;
3795 int tailcallopt = do_tailcallopt;
3797 list = FIRST_ELEMENT(anchor);
3799 int do_block_optimization = 0;
3801 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_BLOCK && !ISEQ_BODY(iseq)->catch_except_p) {
3802 do_block_optimization = 1;
3806 if (IS_INSN(list)) {
3807 if (do_peepholeopt) {
3808 iseq_peephole_optimize(iseq, list, tailcallopt);
3811 iseq_specialized_instruction(iseq, (
INSN *)list);
3814 insn_operands_unification((
INSN *)list);
3817 if (do_block_optimization) {
3819 if (IS_INSN_ID(item, jump)) {
3820 do_block_optimization = 0;
3824 if (IS_LABEL(list)) {
3825 switch (((
LABEL *)list)->rescued) {
3826 case LABEL_RESCUE_BEG:
3828 tailcallopt = FALSE;
3830 case LABEL_RESCUE_END:
3831 if (!--rescue_level) tailcallopt = do_tailcallopt;
3838 if (do_block_optimization) {
3840 if (IS_INSN(le) && IS_INSN_ID((
INSN *)le, nop)) {
3847#if OPT_INSTRUCTIONS_UNIFICATION
3855 VALUE *operands = 0, *ptr = 0;
3859 for (i = 0; i < size; i++) {
3860 iobj = (
INSN *)list;
3861 argc += iobj->operand_size;
3866 ptr = operands = compile_data_alloc2(iseq,
sizeof(
VALUE), argc);
3871 for (i = 0; i < size; i++) {
3872 iobj = (
INSN *)list;
3873 MEMCPY(ptr, iobj->operands,
VALUE, iobj->operand_size);
3874 ptr += iobj->operand_size;
3878 NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
3879 return new_insn_core(iseq, &dummy_line_node, insn_id, argc, operands);
3891#if OPT_INSTRUCTIONS_UNIFICATION
3897 list = FIRST_ELEMENT(anchor);
3899 if (IS_INSN(list)) {
3900 iobj = (
INSN *)list;
3902 if (unified_insns_data[
id] != 0) {
3903 const int *
const *entry = unified_insns_data[id];
3904 for (j = 1; j < (intptr_t)entry[0]; j++) {
3905 const int *unified = entry[j];
3907 for (k = 2; k < unified[1]; k++) {
3909 ((
INSN *)li)->insn_id != unified[k]) {
3916 new_unified_insn(iseq, unified[0], unified[1] - 1,
3921 niobj->link.next = li;
3939#if OPT_STACK_CACHING
3941#define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
3942#define SC_NEXT(insn) sc_insn_next[(insn)]
3944#include "opt_sc.inc"
3952 insn_id = iobj->insn_id;
3953 iobj->insn_id = SC_INSN(insn_id, state);
3954 nstate = SC_NEXT(iobj->insn_id);
3956 if (insn_id == BIN(jump) ||
3957 insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
3960 if (lobj->sc_state != 0) {
3961 if (lobj->sc_state != nstate) {
3962 BADINSN_DUMP(anchor, iobj, lobj);
3963 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
3964 "insn_set_sc_state error: %d at "LABEL_FORMAT
3966 lobj->sc_state, lobj->label_no, nstate);
3971 lobj->sc_state = nstate;
3973 if (insn_id == BIN(jump)) {
3977 else if (insn_id == BIN(leave)) {
3985label_set_sc_state(
LABEL *lobj,
int state)
3987 if (lobj->sc_state != 0) {
3988 if (lobj->sc_state != state) {
3989 state = lobj->sc_state;
3993 lobj->sc_state = state;
4005#if OPT_STACK_CACHING
4011 list = FIRST_ELEMENT(anchor);
4017 switch (list->type) {
4018 case ISEQ_ELEMENT_INSN:
4021 insn_id = iobj->insn_id;
4029 if (state != SCS_AX) {
4030 NODE dummy_line_node = generate_dummy_line_node(0, -1);
4032 new_insn_body(iseq, &dummy_line_node, BIN(reput), 0);
4043 if (state == SCS_AB || state == SCS_BA) {
4044 state = (state == SCS_AB ? SCS_BA : SCS_AB);
4068 COMPILE_ERROR(iseq, iobj->insn_info.line_no,
4081 state = insn_set_sc_state(iseq, anchor, iobj, state);
4084 case ISEQ_ELEMENT_LABEL:
4087 lobj = (
LABEL *)list;
4089 state = label_set_sc_state(lobj, state);
4101all_string_result_p(
const NODE *node)
4103 if (!node)
return FALSE;
4104 switch (nd_type(node)) {
4105 case NODE_STR:
case NODE_DSTR:
4107 case NODE_IF:
case NODE_UNLESS:
4108 if (!node->nd_body || !node->nd_else)
return FALSE;
4109 if (all_string_result_p(node->nd_body))
4110 return all_string_result_p(node->nd_else);
4112 case NODE_AND:
case NODE_OR:
4114 return all_string_result_p(node->nd_1st);
4115 if (!all_string_result_p(node->nd_1st))
4117 return all_string_result_p(node->nd_2nd);
4126 const NODE *list = node->nd_next;
4127 VALUE lit = node->nd_lit;
4131 debugp_param(
"nd_lit", lit);
4135 COMPILE_ERROR(ERROR_ARGS
"dstr: must be string: %s",
4136 rb_builtin_type_name(
TYPE(lit)));
4139 lit = rb_fstring(lit);
4140 ADD_INSN1(ret, node, putobject, lit);
4142 if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
4146 const NODE *
const head = list->nd_head;
4147 if (nd_type_p(head, NODE_STR)) {
4148 lit = rb_fstring(head->nd_lit);
4149 ADD_INSN1(ret, head, putobject, lit);
4154 CHECK(COMPILE(ret,
"each string", head));
4157 list = list->nd_next;
4159 if (
NIL_P(lit) && first_lit) {
4160 ELEM_REMOVE(first_lit);
4171 while (node && nd_type_p(node, NODE_BLOCK)) {
4172 CHECK(COMPILE_(ret,
"BLOCK body", node->nd_head,
4173 (node->nd_next ? 1 : popped)));
4174 node = node->nd_next;
4177 CHECK(COMPILE_(ret,
"BLOCK next", node->nd_next, popped));
4186 if (!node->nd_next) {
4187 VALUE lit = rb_fstring(node->nd_lit);
4188 ADD_INSN1(ret, node, putstring, lit);
4192 CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
4193 ADD_INSN1(ret, node, concatstrings,
INT2FIX(cnt));
4202 CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
4203 ADD_INSN2(ret, node, toregexp,
INT2FIX(node->nd_cflag),
INT2FIX(cnt));
4211 const int line = nd_line(node);
4212 LABEL *lend = NEW_LABEL(line);
4213 rb_num_t cnt = ISEQ_FLIP_CNT_INCREMENT(ISEQ_BODY(iseq)->local_iseq)
4214 + VM_SVAR_FLIPFLOP_START;
4217 ADD_INSN2(ret, node, getspecial, key,
INT2FIX(0));
4218 ADD_INSNL(ret, node, branchif, lend);
4221 CHECK(COMPILE(ret,
"flip2 beg", node->nd_beg));
4222 ADD_INSNL(ret, node, branchunless, else_label);
4223 ADD_INSN1(ret, node, putobject,
Qtrue);
4224 ADD_INSN1(ret, node, setspecial, key);
4226 ADD_INSNL(ret, node, jump, then_label);
4230 ADD_LABEL(ret, lend);
4231 CHECK(COMPILE(ret,
"flip2 end", node->nd_end));
4232 ADD_INSNL(ret, node, branchunless, then_label);
4233 ADD_INSN1(ret, node, putobject,
Qfalse);
4234 ADD_INSN1(ret, node, setspecial, key);
4235 ADD_INSNL(ret, node, jump, then_label);
4245 switch (nd_type(cond)) {
4248 LABEL *label = NEW_LABEL(nd_line(cond));
4249 CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label,
4251 if (!label->refcnt) {
4252 ADD_INSN(ret, cond, putnil);
4255 ADD_LABEL(ret, label);
4256 cond = cond->nd_2nd;
4261 LABEL *label = NEW_LABEL(nd_line(cond));
4262 CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label,
4264 if (!label->refcnt) {
4265 ADD_INSN(ret, cond, putnil);
4268 ADD_LABEL(ret, label);
4269 cond = cond->nd_2nd;
4278 ADD_INSNL(ret, cond, jump, then_label);
4283 ADD_INSNL(ret, cond, jump, else_label);
4289 CHECK(COMPILE_POPPED(ret,
"branch condition", cond));
4290 ADD_INSNL(ret, cond, jump, then_label);
4293 CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label));
4296 CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
4299 CHECK(compile_defined_expr(iseq, ret, cond,
Qfalse));
4302 CHECK(COMPILE(ret,
"branch condition", cond));
4306 ADD_INSNL(ret, cond, branchunless, else_label);
4307 ADD_INSNL(ret, cond, jump, then_label);
4314keyword_node_p(
const NODE *
const node)
4316 return nd_type_p(node, NODE_HASH) && (node->nd_brace & HASH_BRACE) != HASH_BRACE;
4321 const NODE *
const root_node,
4325 if (kw_arg_ptr == NULL)
return FALSE;
4327 if (root_node->nd_head && nd_type_p(root_node->nd_head, NODE_LIST)) {
4328 const NODE *node = root_node->nd_head;
4332 const NODE *key_node = node->nd_head;
4335 assert(nd_type_p(node, NODE_LIST));
4336 if (key_node && nd_type_p(key_node, NODE_LIT) &&
SYMBOL_P(key_node->nd_lit)) {
4341 *flag |= VM_CALL_KW_SPLAT;
4342 if (seen_nodes > 1 || node->nd_next->nd_next) {
4347 *flag |= VM_CALL_KW_SPLAT_MUT;
4352 node = node->nd_next;
4353 node = node->nd_next;
4357 node = root_node->nd_head;
4359 int len = (int)node->nd_alen / 2;
4362 VALUE *keywords = kw_arg->keywords;
4364 kw_arg->keyword_len = len;
4366 *kw_arg_ptr = kw_arg;
4368 for (i=0; node != NULL; i++, node = node->nd_next->nd_next) {
4369 const NODE *key_node = node->nd_head;
4370 const NODE *val_node = node->nd_next->nd_head;
4371 keywords[i] = key_node->nd_lit;
4372 NO_CHECK(COMPILE(ret,
"keyword values", val_node));
4387 for (; node; len++, node = node->nd_next) {
4389 EXPECT_NODE(
"compile_args", node, NODE_LIST, -1);
4392 if (node->nd_next == NULL && keyword_node_p(node->nd_head)) {
4393 if (compile_keyword_arg(iseq, ret, node->nd_head, keywords_ptr, flag)) {
4397 compile_hash(iseq, ret, node->nd_head, TRUE, FALSE);
4401 NO_CHECK(COMPILE_(ret,
"array element", node->nd_head, FALSE));
4409static_literal_node_p(
const NODE *node,
const rb_iseq_t *iseq)
4411 switch (nd_type(node)) {
4418 return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal;
4427 switch (nd_type(node)) {
4435 if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal ||
RTEST(
ruby_debug)) {
4437 VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq),
INT2FIX((
int)nd_line(node)));
4443 return rb_fstring(node->nd_lit);
4446 return node->nd_lit;
4453 const NODE *line_node = node;
4455 if (nd_type_p(node, NODE_ZLIST)) {
4457 ADD_INSN1(ret, line_node, newarray,
INT2FIX(0));
4462 EXPECT_NODE(
"compile_array", node, NODE_LIST, -1);
4465 for (; node; node = node->nd_next) {
4466 NO_CHECK(COMPILE_(ret,
"array element", node->nd_head, popped));
4508 const int max_stack_len = 0x100;
4509 const int min_tmp_ary_len = 0x40;
4511 int first_chunk = 1;
4514#define FLUSH_CHUNK(newarrayinsn) \
4516 ADD_INSN1(ret, line_node, newarrayinsn, INT2FIX(stack_len)); \
4517 if (!first_chunk) ADD_INSN(ret, line_node, concatarray); \
4518 first_chunk = stack_len = 0; \
4525 if (static_literal_node_p(node->nd_head, iseq)) {
4527 const NODE *node_tmp = node->nd_next;
4528 for (; node_tmp && static_literal_node_p(node_tmp->nd_head, iseq); node_tmp = node_tmp->nd_next)
4531 if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_ary_len) {
4533 VALUE ary = rb_ary_hidden_new(count);
4536 for (; count; count--, node = node->nd_next)
4537 rb_ary_push(ary, static_literal_value(node->nd_head, iseq));
4541 FLUSH_CHUNK(newarray);
4543 ADD_INSN1(ret, line_node, duparray, ary);
4547 ADD_INSN1(ret, line_node, putobject, ary);
4548 ADD_INSN(ret, line_node, concatarray);
4555 for (; count; count--, node = node->nd_next) {
4557 EXPECT_NODE(
"compile_array", node, NODE_LIST, -1);
4560 NO_CHECK(COMPILE_(ret,
"array element", node->nd_head, 0));
4563 if (!node->nd_next && keyword_node_p(node->nd_head)) {
4565 FLUSH_CHUNK(newarraykwsplat);
4570 if (stack_len >= max_stack_len) FLUSH_CHUNK(newarray);
4574 FLUSH_CHUNK(newarray);
4583 if (static_literal_node_p(node, iseq)) {
4584 VALUE ary = rb_ary_hidden_new(1);
4585 rb_ary_push(ary, static_literal_value(node, iseq));
4588 ADD_INSN1(ret, node, duparray, ary);
4591 CHECK(COMPILE_(ret,
"array element", node, FALSE));
4592 ADD_INSN1(ret, node, newarray,
INT2FIX(1));
4599static_literal_node_pair_p(
const NODE *node,
const rb_iseq_t *iseq)
4601 return node->nd_head && static_literal_node_p(node->nd_head, iseq) && static_literal_node_p(node->nd_next->nd_head, iseq);
4607 const NODE *line_node = node;
4609 node = node->nd_head;
4611 if (!node || nd_type_p(node, NODE_ZLIST)) {
4613 ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
4618 EXPECT_NODE(
"compile_hash", node, NODE_LIST, -1);
4621 for (; node; node = node->nd_next) {
4622 NO_CHECK(COMPILE_(ret,
"hash element", node->nd_head, popped));
4645 const int max_stack_len = 0x100;
4646 const int min_tmp_hash_len = 0x800;
4648 int first_chunk = 1;
4649 DECL_ANCHOR(anchor);
4650 INIT_ANCHOR(anchor);
4653#define FLUSH_CHUNK() \
4655 if (first_chunk) { \
4656 APPEND_LIST(ret, anchor); \
4657 ADD_INSN1(ret, line_node, newhash, INT2FIX(stack_len)); \
4660 ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \
4661 ADD_INSN(ret, line_node, swap); \
4662 APPEND_LIST(ret, anchor); \
4663 ADD_SEND(ret, line_node, id_core_hash_merge_ptr, INT2FIX(stack_len + 1)); \
4665 INIT_ANCHOR(anchor); \
4666 first_chunk = stack_len = 0; \
4673 if (static_literal_node_pair_p(node, iseq)) {
4675 const NODE *node_tmp = node->nd_next->nd_next;
4676 for (; node_tmp && static_literal_node_pair_p(node_tmp, iseq); node_tmp = node_tmp->nd_next->nd_next)
4679 if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_hash_len) {
4681 VALUE ary = rb_ary_hidden_new(count);
4684 for (; count; count--, node = node->nd_next->nd_next) {
4686 elem[0] = static_literal_value(node->nd_head, iseq);
4687 elem[1] = static_literal_value(node->nd_next->nd_head, iseq);
4688 rb_ary_cat(ary, elem, 2);
4698 ADD_INSN1(ret, line_node, duphash, hash);
4702 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
4703 ADD_INSN(ret, line_node, swap);
4705 ADD_INSN1(ret, line_node, putobject, hash);
4707 ADD_SEND(ret, line_node, id_core_hash_merge_kwd,
INT2FIX(2));
4714 for (; count; count--, node = node->nd_next->nd_next) {
4717 EXPECT_NODE(
"compile_hash", node, NODE_LIST, -1);
4720 if (node->nd_head) {
4722 NO_CHECK(COMPILE_(anchor,
"hash key element", node->nd_head, 0));
4723 NO_CHECK(COMPILE_(anchor,
"hash value element", node->nd_next->nd_head, 0));
4727 if (stack_len >= max_stack_len) FLUSH_CHUNK();
4733 const NODE *kw = node->nd_next->nd_head;
4734 int empty_kw = nd_type_p(kw, NODE_LIT) && RB_TYPE_P(kw->nd_lit,
T_HASH);
4735 int first_kw = first_chunk && stack_len == 0;
4736 int last_kw = !node->nd_next->nd_next;
4737 int only_kw = last_kw && first_kw;
4740 if (only_kw && method_call_keywords) {
4748 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
4750 else if (first_kw) {
4754 ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
4761 if (only_kw && method_call_keywords) {
4767 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
4774 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
4775 if (first_kw) ADD_INSN1(ret, line_node, newhash,
INT2FIX(0));
4776 else ADD_INSN(ret, line_node, swap);
4778 NO_CHECK(COMPILE(ret,
"keyword splat", kw));
4780 ADD_SEND(ret, line_node, id_core_hash_merge_kwd,
INT2FIX(2));
4795rb_node_case_when_optimizable_literal(
const NODE *
const node)
4797 switch (nd_type(node)) {
4799 VALUE v = node->nd_lit;
4801 if (RB_FLOAT_TYPE_P(v) &&
4820 return rb_fstring(node->nd_lit);
4827 LABEL *l1,
int only_special_literals,
VALUE literals)
4830 const NODE *val = vals->nd_head;
4831 VALUE lit = rb_node_case_when_optimizable_literal(val);
4834 only_special_literals = 0;
4836 else if (
NIL_P(rb_hash_lookup(literals, lit))) {
4837 rb_hash_aset(literals, lit, (
VALUE)(l1) | 1);
4840 if (nd_type_p(val, NODE_STR)) {
4841 debugp_param(
"nd_lit", val->nd_lit);
4842 lit = rb_fstring(val->nd_lit);
4843 ADD_INSN1(cond_seq, val, putobject, lit);
4847 if (!COMPILE(cond_seq,
"when cond", val))
return -1;
4851 ADD_INSN1(cond_seq, vals, topn,
INT2FIX(1));
4852 ADD_CALL(cond_seq, vals, idEqq,
INT2FIX(1));
4853 ADD_INSNL(cond_seq, val, branchif, l1);
4854 vals = vals->nd_next;
4856 return only_special_literals;
4861 LABEL *l1,
int only_special_literals,
VALUE literals)
4863 const NODE *line_node = vals;
4865 switch (nd_type(vals)) {
4867 if (when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals) < 0)
4871 ADD_INSN (cond_seq, line_node, dup);
4872 CHECK(COMPILE(cond_seq,
"when splat", vals->nd_head));
4873 ADD_INSN1(cond_seq, line_node, splatarray,
Qfalse);
4874 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
4875 ADD_INSNL(cond_seq, line_node, branchif, l1);
4878 CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
4879 CHECK(when_splat_vals(iseq, cond_seq, vals->nd_body, l1, only_special_literals, literals));
4882 CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
4883 ADD_INSN (cond_seq, line_node, dup);
4884 CHECK(COMPILE(cond_seq,
"when argspush body", vals->nd_body));
4885 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
4886 ADD_INSNL(cond_seq, line_node, branchif, l1);
4889 ADD_INSN (cond_seq, line_node, dup);
4890 CHECK(COMPILE(cond_seq,
"when val", vals));
4891 ADD_INSN1(cond_seq, line_node, splatarray,
Qfalse);
4892 ADD_INSN1(cond_seq, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
4893 ADD_INSNL(cond_seq, line_node, branchif, l1);
4986 const NODE *line_node;
5001add_masgn_lhs_node(
struct masgn_state *state,
int lhs_pos,
const NODE *line_node,
int argc,
INSN *before_insn)
5004 rb_bug(
"no masgn_state");
5013 memo->before_insn = before_insn;
5014 memo->line_node = line_node;
5015 memo->argn = state->num_args + 1;
5016 memo->num_args = argc;
5017 state->num_args += argc;
5018 memo->lhs_pos = lhs_pos;
5020 if (!state->first_memo) {
5021 state->first_memo = memo;
5024 state->last_memo->next = memo;
5026 state->last_memo = memo;
5036 switch (nd_type(node)) {
5037 case NODE_ATTRASGN: {
5039 const NODE *line_node = node;
5041 CHECK(COMPILE_POPPED(pre,
"masgn lhs (NODE_ATTRASGN)", node));
5044 iobj = (
INSN *)get_prev_insn((
INSN *)insn_element);
5046 ELEM_REMOVE(LAST_ELEMENT(pre));
5048 pre->last = iobj->link.prev;
5051 int argc = vm_ci_argc(ci) + 1;
5052 ci = ci_argc_set(iseq, ci, argc);
5053 OPERAND_AT(iobj, 0) = (
VALUE)ci;
5057 ADD_INSN(lhs, line_node, swap);
5060 ADD_INSN1(lhs, line_node, topn,
INT2FIX(argc));
5063 if (!add_masgn_lhs_node(state, lhs_pos, line_node, argc, (
INSN *)LAST_ELEMENT(lhs))) {
5068 if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
5069 int argc = vm_ci_argc(ci);
5070 ci = ci_argc_set(iseq, ci, argc - 1);
5071 OPERAND_AT(iobj, 0) = (
VALUE)ci;
5073 INSERT_BEFORE_INSN1(iobj, line_node, newarray,
INT2FIX(1));
5074 INSERT_BEFORE_INSN(iobj, line_node, concatarray);
5076 ADD_INSN(lhs, line_node, pop);
5078 ADD_INSN(lhs, line_node, pop);
5080 for (
int i=0; i < argc; i++) {
5081 ADD_INSN(post, line_node, pop);
5086 DECL_ANCHOR(nest_rhs);
5087 INIT_ANCHOR(nest_rhs);
5088 DECL_ANCHOR(nest_lhs);
5089 INIT_ANCHOR(nest_lhs);
5091 int prev_level = state->lhs_level;
5092 bool prev_nested = state->nested;
5094 state->lhs_level = lhs_pos - 1;
5095 CHECK(compile_massign0(iseq, pre, nest_rhs, nest_lhs, post, node, state, 1));
5096 state->lhs_level = prev_level;
5097 state->nested = prev_nested;
5099 ADD_SEQ(lhs, nest_rhs);
5100 ADD_SEQ(lhs, nest_lhs);
5104 if (!node->nd_vid) {
5108 CHECK(COMPILE_POPPED(pre,
"masgn lhs (NODE_CDECL)", node));
5111 iobj = (
INSN *)insn_element;
5114 ELEM_REMOVE(insn_element);
5115 pre->last = iobj->link.prev;
5118 if (!add_masgn_lhs_node(state, lhs_pos, node, 1, (
INSN *)LAST_ELEMENT(lhs))) {
5122 ADD_INSN(post, node, pop);
5127 DECL_ANCHOR(anchor);
5128 INIT_ANCHOR(anchor);
5129 CHECK(COMPILE_POPPED(anchor,
"masgn lhs", node));
5130 ELEM_REMOVE(FIRST_ELEMENT(anchor));
5131 ADD_SEQ(lhs, anchor);
5142 CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next));
5143 CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, lhsn->nd_head, NULL, 0));
5150 const NODE *rhsn,
const NODE *orig_lhsn)
5153 const int memsize = numberof(mem);
5155 int llen = 0, rlen = 0;
5157 const NODE *lhsn = orig_lhsn;
5159#define MEMORY(v) { \
5161 if (memindex == memsize) return 0; \
5162 for (i=0; i<memindex; i++) { \
5163 if (mem[i] == (v)) return 0; \
5165 mem[memindex++] = (v); \
5168 if (rhsn == 0 || !nd_type_p(rhsn, NODE_LIST)) {
5173 const NODE *ln = lhsn->nd_head;
5174 switch (nd_type(ln)) {
5186 lhsn = lhsn->nd_next;
5192 NO_CHECK(COMPILE_POPPED(ret,
"masgn val (popped)", rhsn->nd_head));
5195 NO_CHECK(COMPILE(ret,
"masgn val", rhsn->nd_head));
5197 rhsn = rhsn->nd_next;
5202 for (i=0; i<llen-rlen; i++) {
5203 ADD_INSN(ret, orig_lhsn, putnil);
5207 compile_massign_opt_lhs(iseq, ret, orig_lhsn);
5214 const NODE *rhsn = node->nd_value;
5215 const NODE *splatn = node->nd_args;
5216 const NODE *lhsn = node->nd_head;
5217 const NODE *lhsn_count = lhsn;
5218 int lhs_splat = (splatn && NODE_NAMED_REST_P(splatn)) ? 1 : 0;
5224 while (lhsn_count) {
5226 lhsn_count = lhsn_count->nd_next;
5229 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, lhsn->nd_head, state, (llen - lpos) + lhs_splat + state->lhs_level));
5231 lhsn = lhsn->nd_next;
5235 if (nd_type_p(splatn, NODE_POSTARG)) {
5237 const NODE *postn = splatn->nd_2nd;
5238 const NODE *restn = splatn->nd_1st;
5239 int plen = (int)postn->nd_alen;
5241 int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00);
5243 ADD_INSN2(lhs, splatn, expandarray,
INT2FIX(plen),
INT2FIX(flag));
5245 if (NODE_NAMED_REST_P(restn)) {
5246 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, restn, state, 1 + plen + state->lhs_level));
5249 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, postn->nd_head, state, (plen - ppos) + state->lhs_level));
5251 postn = postn->nd_next;
5256 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, splatn, state, 1 + state->lhs_level));
5261 if (!state->nested) {
5262 NO_CHECK(COMPILE(rhs,
"normal masgn rhs", rhsn));
5266 ADD_INSN(rhs, node, dup);
5269 ADD_INSN2(rhs, node, expandarray,
INT2FIX(llen),
INT2FIX(lhs_splat));
5277 if (!popped || node->nd_args || !compile_massign_opt(iseq, ret, node->nd_value, node->nd_head)) {
5279 state.lhs_level = popped ? 0 : 1;
5282 state.first_memo = NULL;
5283 state.last_memo = NULL;
5293 int ok = compile_massign0(iseq, pre, rhs, lhs, post, node, &state, popped);
5297 VALUE topn_arg =
INT2FIX((state.num_args - memo->argn) + memo->lhs_pos);
5298 for (
int i = 0; i < memo->num_args; i++) {
5299 INSERT_BEFORE_INSN1(memo->before_insn, memo->line_node, topn, topn_arg);
5301 tmp_memo = memo->next;
5310 if (!popped && state.num_args >= 1) {
5312 ADD_INSN1(ret, node, setn,
INT2FIX(state.num_args));
5322 VALUE arr = rb_ary_new();
5324 switch (nd_type(node)) {
5326 rb_ary_unshift(arr,
ID2SYM(node->nd_vid));
5329 rb_ary_unshift(arr,
ID2SYM(node->nd_mid));
5330 rb_ary_unshift(arr,
ID2SYM(idNULL));
5333 rb_ary_unshift(arr,
ID2SYM(node->nd_mid));
5334 node = node->nd_head;
5343compile_const_prefix(
rb_iseq_t *iseq,
const NODE *
const node,
5346 switch (nd_type(node)) {
5348 debugi(
"compile_const_prefix - colon", node->nd_vid);
5349 ADD_INSN1(body, node, putobject,
Qtrue);
5350 ADD_INSN1(body, node, getconstant,
ID2SYM(node->nd_vid));
5353 debugi(
"compile_const_prefix - colon3", node->nd_mid);
5354 ADD_INSN(body, node, pop);
5355 ADD_INSN1(body, node, putobject, rb_cObject);
5356 ADD_INSN1(body, node, putobject,
Qtrue);
5357 ADD_INSN1(body, node, getconstant,
ID2SYM(node->nd_mid));
5360 CHECK(compile_const_prefix(iseq, node->nd_head, pref, body));
5361 debugi(
"compile_const_prefix - colon2", node->nd_mid);
5362 ADD_INSN1(body, node, putobject,
Qfalse);
5363 ADD_INSN1(body, node, getconstant,
ID2SYM(node->nd_mid));
5366 CHECK(COMPILE(pref,
"const colon2 prefix", node));
5375 if (nd_type_p(cpath, NODE_COLON3)) {
5377 ADD_INSN1(ret, cpath, putobject, rb_cObject);
5378 return VM_DEFINECLASS_FLAG_SCOPED;
5380 else if (cpath->nd_head) {
5382 NO_CHECK(COMPILE(ret,
"nd_else->nd_head", cpath->nd_head));
5383 return VM_DEFINECLASS_FLAG_SCOPED;
5387 ADD_INSN1(ret, cpath, putspecialobject,
5388 INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
5394private_recv_p(
const NODE *node)
5396 if (nd_type_p(node->nd_recv, NODE_SELF)) {
5397 NODE *self = node->nd_recv;
5398 return self->nd_state != 0;
5408compile_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);
5415 enum defined_type expr_type = DEFINED_NOT_DEFINED;
5416 enum node_type
type;
5417 const int line = nd_line(node);
5418 const NODE *line_node = node;
5420 switch (
type = nd_type(node)) {
5424 expr_type = DEFINED_NIL;
5427 expr_type = DEFINED_SELF;
5430 expr_type = DEFINED_TRUE;
5433 expr_type = DEFINED_FALSE;
5437 const NODE *vals = node;
5440 defined_expr0(iseq, ret, vals->nd_head, lfinish,
Qfalse,
false);
5443 lfinish[1] = NEW_LABEL(line);
5445 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
5446 }
while ((vals = vals->nd_next) != NULL);
5455 expr_type = DEFINED_EXPR;
5461 expr_type = DEFINED_LVAR;
5464#define PUSH_VAL(type) (needstr == Qfalse ? Qtrue : rb_iseq_defined_string(type))
5466 ADD_INSN(ret, line_node, putnil);
5467 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_IVAR),
5468 ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_IVAR));
5472 ADD_INSN(ret, line_node, putnil);
5473 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_GVAR),
5474 ID2SYM(node->nd_entry), PUSH_VAL(DEFINED_GVAR));
5478 ADD_INSN(ret, line_node, putnil);
5479 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CVAR),
5480 ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CVAR));
5484 ADD_INSN(ret, line_node, putnil);
5485 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CONST),
5486 ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CONST));
5490 lfinish[1] = NEW_LABEL(line);
5492 defined_expr0(iseq, ret, node->nd_head, lfinish,
Qfalse,
false);
5493 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
5494 NO_CHECK(COMPILE(ret,
"defined/colon2#nd_head", node->nd_head));
5497 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_CONST_FROM),
5498 ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_CONST));
5501 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_METHOD),
5502 ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
5506 ADD_INSN1(ret, line_node, putobject, rb_cObject);
5507 ADD_INSN3(ret, line_node, defined,
5508 INT2FIX(DEFINED_CONST_FROM),
ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_CONST));
5516 case NODE_ATTRASGN:{
5517 const int explicit_receiver =
5518 (
type == NODE_CALL ||
type == NODE_OPCALL ||
5519 (
type == NODE_ATTRASGN && !private_recv_p(node)));
5521 if (node->nd_args || explicit_receiver) {
5523 lfinish[1] = NEW_LABEL(line);
5526 lfinish[2] = NEW_LABEL(line);
5529 if (node->nd_args) {
5530 defined_expr0(iseq, ret, node->nd_args, lfinish,
Qfalse,
false);
5531 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
5533 if (explicit_receiver) {
5534 defined_expr0(iseq, ret, node->nd_recv, lfinish,
Qfalse,
true);
5535 switch (nd_type(node->nd_recv)) {
5541 ADD_INSNL(ret, line_node, branchunless, lfinish[2]);
5542 compile_call(iseq, ret, node->nd_recv, nd_type(node->nd_recv), line_node, 0,
true);
5545 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
5546 NO_CHECK(COMPILE(ret,
"defined/recv", node->nd_recv));
5550 ADD_INSN(ret, line_node, dup);
5552 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_METHOD),
5553 ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
5556 ADD_INSN(ret, line_node, putself);
5558 ADD_INSN(ret, line_node, dup);
5560 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_FUNC),
5561 ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
5567 ADD_INSN(ret, line_node, putnil);
5568 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_YIELD), 0,
5569 PUSH_VAL(DEFINED_YIELD));
5574 ADD_INSN(ret, line_node, putnil);
5575 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_REF),
5576 INT2FIX((node->nd_nth << 1) | (
type == NODE_BACK_REF)),
5577 PUSH_VAL(DEFINED_GVAR));
5582 ADD_INSN(ret, line_node, putnil);
5583 ADD_INSN3(ret, line_node, defined,
INT2FIX(DEFINED_ZSUPER), 0,
5584 PUSH_VAL(DEFINED_ZSUPER));
5590 case NODE_OP_ASGN_OR:
5591 case NODE_OP_ASGN_AND:
5599 expr_type = DEFINED_ASGN;
5603 assert(expr_type != DEFINED_NOT_DEFINED);
5606 VALUE str = rb_iseq_defined_string(expr_type);
5607 ADD_INSN1(ret, line_node, putobject, str);
5610 ADD_INSN1(ret, line_node, putobject,
Qtrue);
5617 NODE dummy_line_node = generate_dummy_line_node(0, -1);
5618 ADD_INSN(ret, &dummy_line_node, putnil);
5619 iseq_set_exception_local_table(iseq);
5627 defined_expr0(iseq, ret, node, lfinish, needstr,
false);
5629 int line = nd_line(node);
5630 LABEL *lstart = NEW_LABEL(line);
5631 LABEL *lend = NEW_LABEL(line);
5634 rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq, NULL);
5635 rescue = new_child_iseq_with_callback(iseq, ifunc,
5637 ISEQ_BODY(iseq)->location.label),
5638 iseq, ISEQ_TYPE_RESCUE, 0);
5639 lstart->rescued = LABEL_RESCUE_BEG;
5640 lend->rescued = LABEL_RESCUE_END;
5641 APPEND_LABEL(ret, lcur, lstart);
5642 ADD_LABEL(ret, lend);
5643 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
5650 const int line = nd_line(node);
5651 const NODE *line_node = node;
5652 if (!node->nd_head) {
5653 VALUE str = rb_iseq_defined_string(DEFINED_NIL);
5654 ADD_INSN1(ret, line_node, putobject, str);
5659 lfinish[0] = NEW_LABEL(line);
5662 defined_expr(iseq, ret, node->nd_head, lfinish, needstr);
5664 ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line_node, BIN(putnil), 0)->link);
5665 ADD_INSN(ret, line_node, swap);
5667 ADD_LABEL(ret, lfinish[2]);
5669 ADD_INSN(ret, line_node, pop);
5670 ADD_LABEL(ret, lfinish[1]);
5672 ADD_LABEL(ret, lfinish[0]);
5678make_name_for_block(
const rb_iseq_t *orig_iseq)
5683 if (ISEQ_BODY(orig_iseq)->parent_iseq != 0) {
5684 while (ISEQ_BODY(orig_iseq)->local_iseq != iseq) {
5685 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_BLOCK) {
5688 iseq = ISEQ_BODY(iseq)->parent_iseq;
5693 return rb_sprintf(
"block in %"PRIsVALUE, ISEQ_BODY(iseq)->location.label);
5696 return rb_sprintf(
"block (%d levels) in %"PRIsVALUE, level, ISEQ_BODY(iseq)->location.label);
5705 enl->ensure_node = node;
5706 enl->prev = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
5708 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl;
5718 while (erange->next != 0) {
5719 erange = erange->next;
5723 ne->end = erange->end;
5724 erange->end = lstart;
5730can_add_ensure_iseq(
const rb_iseq_t *iseq)
5733 if (ISEQ_COMPILE_DATA(iseq)->in_rescue && (e = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack) != NULL) {
5735 if (e->ensure_node)
return false;
5745 assert(can_add_ensure_iseq(iseq));
5748 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
5750 DECL_ANCHOR(ensure);
5752 INIT_ANCHOR(ensure);
5754 if (enlp->erange != NULL) {
5755 DECL_ANCHOR(ensure_part);
5756 LABEL *lstart = NEW_LABEL(0);
5757 LABEL *lend = NEW_LABEL(0);
5758 INIT_ANCHOR(ensure_part);
5760 add_ensure_range(iseq, enlp->erange, lstart, lend);
5762 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enlp->prev;
5763 ADD_LABEL(ensure_part, lstart);
5764 NO_CHECK(COMPILE_POPPED(ensure_part,
"ensure part", enlp->ensure_node));
5765 ADD_LABEL(ensure_part, lend);
5766 ADD_SEQ(ensure, ensure_part);
5775 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = prev_enlp;
5776 ADD_SEQ(ret, ensure);
5780check_keyword(
const NODE *node)
5784 if (nd_type_p(node, NODE_LIST)) {
5785 while (node->nd_next) {
5786 node = node->nd_next;
5788 node = node->nd_head;
5791 return keyword_node_p(node);
5799 switch (nd_type(argn)) {
5801 NO_CHECK(COMPILE(args,
"args (splat)", argn->nd_head));
5802 ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
5803 if (flag) *flag |= VM_CALL_ARGS_SPLAT;
5807 case NODE_ARGSPUSH: {
5808 int next_is_list = (nd_type_p(argn->nd_head, NODE_LIST));
5809 VALUE argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL);
5810 if (nd_type_p(argn->nd_body, NODE_LIST)) {
5812 int rest_len = compile_args(iseq, args, argn->nd_body, NULL, NULL);
5813 ADD_INSN1(args, argn, newarray,
INT2FIX(rest_len));
5816 NO_CHECK(COMPILE(args,
"args (cat: splat)", argn->nd_body));
5819 *flag |= VM_CALL_ARGS_SPLAT;
5822 if (check_keyword(argn->nd_body))
5823 *flag |= VM_CALL_KW_SPLAT;
5825 if (nd_type_p(argn, NODE_ARGSCAT)) {
5827 ADD_INSN1(args, argn, splatarray,
Qtrue);
5831 ADD_INSN1(args, argn, splatarray,
Qfalse);
5832 ADD_INSN(args, argn, concatarray);
5837 ADD_INSN1(args, argn, newarray,
INT2FIX(1));
5838 ADD_INSN(args, argn, concatarray);
5843 int len = compile_args(iseq, args, argn, keywords, flag);
5847 UNKNOWN_NODE(
"setup_arg", argn,
Qnil);
5859 if (argn && nd_type_p(argn, NODE_BLOCK_PASS)) {
5860 unsigned int dup_rest = 1;
5861 DECL_ANCHOR(arg_block);
5862 INIT_ANCHOR(arg_block);
5863 NO_CHECK(COMPILE(arg_block,
"block", argn->nd_body));
5865 *flag |= VM_CALL_ARGS_BLOCKARG;
5867 if (LIST_INSN_SIZE_ONE(arg_block)) {
5869 if (IS_INSN(elem)) {
5871 if (iobj->insn_id == BIN(getblockparam)) {
5872 iobj->insn_id = BIN(getblockparamproxy);
5877 ret = setup_args_core(iseq, args, argn->nd_head, dup_rest, flag, keywords);
5878 ADD_SEQ(args, arg_block);
5881 ret = setup_args_core(iseq, args, argn, 0, flag, keywords);
5889 const NODE *body = ptr;
5890 int line = nd_line(body);
5892 const rb_iseq_t *block = NEW_CHILD_ISEQ(body, make_name_for_block(ISEQ_BODY(iseq)->parent_iseq), ISEQ_TYPE_BLOCK, line);
5894 ADD_INSN1(ret, body, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5895 ADD_CALL_WITH_BLOCK(ret, body, id_core_set_postexe, argc, block);
5897 iseq_set_local_table(iseq, 0);
5905 int line = nd_line(node);
5906 const NODE *line_node = node;
5907 LABEL *fail_label = NEW_LABEL(line), *end_label = NEW_LABEL(line);
5909#if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0)
5910 ADD_INSN1(ret, line_node, getglobal,
ID2SYM(idBACKREF));
5914 ADD_INSN(ret, line_node, dup);
5915 ADD_INSNL(ret, line_node, branchunless, fail_label);
5917 for (vars = node; vars; vars = vars->nd_next) {
5919 if (vars->nd_next) {
5920 ADD_INSN(ret, line_node, dup);
5923 NO_CHECK(COMPILE_POPPED(ret,
"capture", vars->nd_head));
5925 cap = new_insn_send(iseq, line_node, idAREF,
INT2FIX(1),
5928#if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
5929 if (!vars->nd_next && vars == node) {
5934 ADD_INSNL(nom, line_node, jump, end_label);
5935 ADD_LABEL(nom, fail_label);
5937 ADD_INSN(nom, line_node, pop);
5938 ADD_INSN(nom, line_node, putnil);
5940 ADD_LABEL(nom, end_label);
5941 (nom->last->next = cap->link.next)->prev = nom->last;
5942 (cap->link.next = nom->anchor.next)->prev = &cap->link;
5947 ADD_INSNL(ret, line_node, jump, end_label);
5948 ADD_LABEL(ret, fail_label);
5949 ADD_INSN(ret, line_node, pop);
5950 for (vars = node; vars; vars = vars->nd_next) {
5952 NO_CHECK(COMPILE_POPPED(ret,
"capture", vars->nd_head));
5954 ((
INSN*)last)->insn_id = BIN(putnil);
5955 ((
INSN*)last)->operand_size = 0;
5957 ADD_LABEL(ret, end_label);
5961optimizable_range_item_p(
const NODE *n)
5963 if (!n)
return FALSE;
5964 switch (nd_type(n)) {
5978 const NODE *
const node_body =
type == NODE_IF ? node->nd_body : node->nd_else;
5979 const NODE *
const node_else =
type == NODE_IF ? node->nd_else : node->nd_body;
5981 const int line = nd_line(node);
5982 const NODE *line_node = node;
5983 DECL_ANCHOR(cond_seq);
5984 DECL_ANCHOR(then_seq);
5985 DECL_ANCHOR(else_seq);
5986 LABEL *then_label, *else_label, *end_label;
5989 VALUE catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
5990 long catch_table_size =
NIL_P(catch_table) ? 0 :
RARRAY_LEN(catch_table);
5992 INIT_ANCHOR(cond_seq);
5993 INIT_ANCHOR(then_seq);
5994 INIT_ANCHOR(else_seq);
5995 then_label = NEW_LABEL(line);
5996 else_label = NEW_LABEL(line);
5999 compile_branch_condition(iseq, cond_seq, node->nd_cond,
6000 then_label, else_label);
6002 ci_size = body->ci_size;
6003 CHECK(COMPILE_(then_seq,
"then", node_body, popped));
6004 catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
6005 if (!then_label->refcnt) {
6006 body->ci_size = ci_size;
6007 if (!
NIL_P(catch_table)) rb_ary_set_len(catch_table, catch_table_size);
6013 ci_size = body->ci_size;
6014 CHECK(COMPILE_(else_seq,
"else", node_else, popped));
6015 catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
6016 if (!else_label->refcnt) {
6017 body->ci_size = ci_size;
6018 if (!
NIL_P(catch_table)) rb_ary_set_len(catch_table, catch_table_size);
6024 ADD_SEQ(ret, cond_seq);
6026 if (then_label->refcnt && else_label->refcnt) {
6027 branches = decl_branch_base(iseq, node,
type == NODE_IF ?
"if" :
"unless");
6030 if (then_label->refcnt) {
6031 ADD_LABEL(ret, then_label);
6032 if (else_label->refcnt) {
6033 add_trace_branch_coverage(
6036 node_body ? node_body : node,
6038 type == NODE_IF ?
"then" :
"else",
6040 end_label = NEW_LABEL(line);
6041 ADD_INSNL(then_seq, line_node, jump, end_label);
6043 ADD_INSN(then_seq, line_node, pop);
6046 ADD_SEQ(ret, then_seq);
6049 if (else_label->refcnt) {
6050 ADD_LABEL(ret, else_label);
6051 if (then_label->refcnt) {
6052 add_trace_branch_coverage(
6055 node_else ? node_else : node,
6057 type == NODE_IF ?
"else" :
"then",
6060 ADD_SEQ(ret, else_seq);
6064 ADD_LABEL(ret, end_label);
6074 const NODE *node = orig_node;
6075 LABEL *endlabel, *elselabel;
6077 DECL_ANCHOR(body_seq);
6078 DECL_ANCHOR(cond_seq);
6079 int only_special_literals = 1;
6080 VALUE literals = rb_hash_new();
6082 enum node_type
type;
6083 const NODE *line_node;
6088 INIT_ANCHOR(body_seq);
6089 INIT_ANCHOR(cond_seq);
6091 RHASH_TBL_RAW(literals)->type = &cdhash_type;
6093 CHECK(COMPILE(head,
"case base", node->nd_head));
6095 branches = decl_branch_base(iseq, node,
"case");
6097 node = node->nd_body;
6098 EXPECT_NODE(
"NODE_CASE", node, NODE_WHEN, COMPILE_NG);
6099 type = nd_type(node);
6100 line = nd_line(node);
6103 endlabel = NEW_LABEL(line);
6104 elselabel = NEW_LABEL(line);
6108 while (
type == NODE_WHEN) {
6111 l1 = NEW_LABEL(line);
6112 ADD_LABEL(body_seq, l1);
6113 ADD_INSN(body_seq, line_node, pop);
6114 add_trace_branch_coverage(
6117 node->nd_body ? node->nd_body : node,
6121 CHECK(COMPILE_(body_seq,
"when body", node->nd_body, popped));
6122 ADD_INSNL(body_seq, line_node, jump, endlabel);
6124 vals = node->nd_head;
6126 switch (nd_type(vals)) {
6128 only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
6129 if (only_special_literals < 0)
return COMPILE_NG;
6134 only_special_literals = 0;
6135 CHECK(when_splat_vals(iseq, cond_seq, vals, l1, only_special_literals, literals));
6138 UNKNOWN_NODE(
"NODE_CASE", vals, COMPILE_NG);
6142 EXPECT_NODE_NONULL(
"NODE_CASE", node, NODE_LIST, COMPILE_NG);
6145 node = node->nd_next;
6149 type = nd_type(node);
6150 line = nd_line(node);
6155 ADD_LABEL(cond_seq, elselabel);
6156 ADD_INSN(cond_seq, line_node, pop);
6157 add_trace_branch_coverage(iseq, cond_seq, node, branch_id,
"else", branches);
6158 CHECK(COMPILE_(cond_seq,
"else", node, popped));
6159 ADD_INSNL(cond_seq, line_node, jump, endlabel);
6162 debugs(
"== else (implicit)\n");
6163 ADD_LABEL(cond_seq, elselabel);
6164 ADD_INSN(cond_seq, orig_node, pop);
6165 add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id,
"else", branches);
6167 ADD_INSN(cond_seq, orig_node, putnil);
6169 ADD_INSNL(cond_seq, orig_node, jump, endlabel);
6172 if (only_special_literals && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
6173 ADD_INSN(ret, orig_node, dup);
6174 ADD_INSN2(ret, orig_node, opt_case_dispatch, literals, elselabel);
6176 LABEL_REF(elselabel);
6179 ADD_SEQ(ret, cond_seq);
6180 ADD_SEQ(ret, body_seq);
6181 ADD_LABEL(ret, endlabel);
6190 const NODE *node = orig_node->nd_body;
6192 DECL_ANCHOR(body_seq);
6196 branches = decl_branch_base(iseq, orig_node,
"case");
6198 INIT_ANCHOR(body_seq);
6199 endlabel = NEW_LABEL(nd_line(node));
6201 while (node && nd_type_p(node, NODE_WHEN)) {
6202 const int line = nd_line(node);
6203 LABEL *l1 = NEW_LABEL(line);
6204 ADD_LABEL(body_seq, l1);
6205 add_trace_branch_coverage(
6208 node->nd_body ? node->nd_body : node,
6212 CHECK(COMPILE_(body_seq,
"when", node->nd_body, popped));
6213 ADD_INSNL(body_seq, node, jump, endlabel);
6215 vals = node->nd_head;
6217 EXPECT_NODE_NONULL(
"NODE_WHEN", node, NODE_LIST, COMPILE_NG);
6219 switch (nd_type(vals)) {
6223 val = vals->nd_head;
6224 lnext = NEW_LABEL(nd_line(val));
6225 debug_compile(
"== when2\n", (
void)0);
6226 CHECK(compile_branch_condition(iseq, ret, val, l1, lnext));
6227 ADD_LABEL(ret, lnext);
6228 vals = vals->nd_next;
6234 ADD_INSN(ret, vals, putnil);
6235 CHECK(COMPILE(ret,
"when2/cond splat", vals));
6236 ADD_INSN1(ret, vals, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY));
6237 ADD_INSNL(ret, vals, branchif, l1);
6240 UNKNOWN_NODE(
"NODE_WHEN", vals, COMPILE_NG);
6242 node = node->nd_next;
6245 add_trace_branch_coverage(
6248 node ? node : orig_node,
6252 CHECK(COMPILE_(ret,
"else", node, popped));
6253 ADD_INSNL(ret, orig_node, jump, endlabel);
6255 ADD_SEQ(ret, body_seq);
6256 ADD_LABEL(ret, endlabel);
6260static 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);
6262static 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);
6263static 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);
6264static int iseq_compile_pattern_set_general_errmsg(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
VALUE errmsg,
int base_index);
6265static 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);
6266static int iseq_compile_pattern_set_eqq_errmsg(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
int base_index);
6268#define CASE3_BI_OFFSET_DECONSTRUCTED_CACHE 0
6269#define CASE3_BI_OFFSET_ERROR_STRING 1
6270#define CASE3_BI_OFFSET_KEY_ERROR_P 2
6271#define CASE3_BI_OFFSET_KEY_ERROR_MATCHEE 3
6272#define CASE3_BI_OFFSET_KEY_ERROR_KEY 4
6275iseq_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)
6277 const int line = nd_line(node);
6278 const NODE *line_node = node;
6280 switch (nd_type(node)) {
6335 const NODE *args = apinfo->pre_args;
6336 const int pre_args_num = apinfo->pre_args ?
rb_long2int(apinfo->pre_args->nd_alen) : 0;
6337 const int post_args_num = apinfo->post_args ?
rb_long2int(apinfo->post_args->nd_alen) : 0;
6339 const int min_argc = pre_args_num + post_args_num;
6340 const int use_rest_num = apinfo->rest_arg && (NODE_NAMED_REST_P(apinfo->rest_arg) ||
6341 (!NODE_NAMED_REST_P(apinfo->rest_arg) && post_args_num > 0));
6343 LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
6345 match_failed = NEW_LABEL(line);
6346 type_error = NEW_LABEL(line);
6347 deconstruct = NEW_LABEL(line);
6348 deconstructed = NEW_LABEL(line);
6351 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
6352 ADD_INSN(ret, line_node, swap);
6358 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
6360 CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
6362 ADD_INSN(ret, line_node, dup);
6363 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6364 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
6365 ADD_SEND(ret, line_node, apinfo->rest_arg ? idGE : idEq,
INT2FIX(1));
6366 if (in_single_pattern) {
6367 CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node,
6368 apinfo->rest_arg ? rb_fstring_lit(
"%p length mismatch (given %p, expected %p+)") :
6369 rb_fstring_lit(
"%p length mismatch (given %p, expected %p)"),
6370 INT2FIX(min_argc), base_index + 1 ));
6372 ADD_INSNL(ret, line_node, branchunless, match_failed);
6374 for (i = 0; i < pre_args_num; i++) {
6375 ADD_INSN(ret, line_node, dup);
6376 ADD_INSN1(ret, line_node, putobject,
INT2FIX(i));
6377 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
6378 CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
6379 args = args->nd_next;
6382 if (apinfo->rest_arg) {
6383 if (NODE_NAMED_REST_P(apinfo->rest_arg)) {
6384 ADD_INSN(ret, line_node, dup);
6385 ADD_INSN1(ret, line_node, putobject,
INT2FIX(pre_args_num));
6386 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
6387 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6388 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
6389 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
6390 ADD_INSN1(ret, line_node, setn,
INT2FIX(4));
6391 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
6393 CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->rest_arg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
6396 if (post_args_num > 0) {
6397 ADD_INSN(ret, line_node, dup);
6398 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6399 ADD_INSN1(ret, line_node, putobject,
INT2FIX(min_argc));
6400 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
6401 ADD_INSN1(ret, line_node, setn,
INT2FIX(2));
6402 ADD_INSN(ret, line_node, pop);
6407 args = apinfo->post_args;
6408 for (i = 0; i < post_args_num; i++) {
6409 ADD_INSN(ret, line_node, dup);
6411 ADD_INSN1(ret, line_node, putobject,
INT2FIX(pre_args_num + i));
6412 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6413 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
6415 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
6416 CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
6417 args = args->nd_next;
6420 ADD_INSN(ret, line_node, pop);
6422 ADD_INSN(ret, line_node, pop);
6424 ADD_INSNL(ret, line_node, jump, matched);
6425 ADD_INSN(ret, line_node, putnil);
6427 ADD_INSN(ret, line_node, putnil);
6430 ADD_LABEL(ret, type_error);
6431 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6433 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct must return Array"));
6434 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
6435 ADD_INSN(ret, line_node, pop);
6437 ADD_LABEL(ret, match_failed);
6438 ADD_INSN(ret, line_node, pop);
6440 ADD_INSN(ret, line_node, pop);
6442 ADD_INSNL(ret, line_node, jump, unmatched);
6496 const NODE *args = fpinfo->args;
6497 const int args_num = fpinfo->args ?
rb_long2int(fpinfo->args->nd_alen) : 0;
6499 LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
6500 match_failed = NEW_LABEL(line);
6501 type_error = NEW_LABEL(line);
6502 deconstruct = NEW_LABEL(line);
6503 deconstructed = NEW_LABEL(line);
6505 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
6507 CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
6509 ADD_INSN(ret, line_node, dup);
6510 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6511 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
6512 ADD_SEND(ret, line_node, idGE,
INT2FIX(1));
6513 if (in_single_pattern) {
6514 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 ));
6516 ADD_INSNL(ret, line_node, branchunless, match_failed);
6519 LABEL *while_begin = NEW_LABEL(nd_line(node));
6520 LABEL *next_loop = NEW_LABEL(nd_line(node));
6521 LABEL *find_succeeded = NEW_LABEL(line);
6522 LABEL *find_failed = NEW_LABEL(nd_line(node));
6525 ADD_INSN(ret, line_node, dup);
6526 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
6528 ADD_INSN(ret, line_node, dup);
6529 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
6530 ADD_SEND(ret, line_node, idMINUS,
INT2FIX(1));
6532 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
6534 ADD_LABEL(ret, while_begin);
6536 ADD_INSN(ret, line_node, dup);
6537 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
6538 ADD_SEND(ret, line_node, idLE,
INT2FIX(1));
6539 ADD_INSNL(ret, line_node, branchunless, find_failed);
6541 for (j = 0; j < args_num; j++) {
6542 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6543 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
6545 ADD_INSN1(ret, line_node, putobject,
INT2FIX(j));
6546 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
6548 ADD_SEND(ret, line_node, idAREF,
INT2FIX(1));
6550 CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, next_loop, in_single_pattern, in_alt_pattern, base_index + 4 ,
false));
6551 args = args->nd_next;
6554 if (NODE_NAMED_REST_P(fpinfo->pre_rest_arg)) {
6555 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6556 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
6557 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
6558 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
6559 CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->pre_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 ,
false));
6561 if (NODE_NAMED_REST_P(fpinfo->post_rest_arg)) {
6562 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6563 ADD_INSN1(ret, line_node, topn,
INT2FIX(1));
6564 ADD_INSN1(ret, line_node, putobject,
INT2FIX(args_num));
6565 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
6566 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6567 ADD_SEND(ret, line_node, idAREF,
INT2FIX(2));
6568 CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->post_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 ,
false));
6570 ADD_INSNL(ret, line_node, jump, find_succeeded);
6572 ADD_LABEL(ret, next_loop);
6573 ADD_INSN1(ret, line_node, putobject,
INT2FIX(1));
6574 ADD_SEND(ret, line_node, idPLUS,
INT2FIX(1));
6575 ADD_INSNL(ret, line_node, jump, while_begin);
6577 ADD_LABEL(ret, find_failed);
6578 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(3));
6579 if (in_single_pattern) {
6580 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6581 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"%p does not match to find pattern"));
6582 ADD_INSN1(ret, line_node, topn,
INT2FIX(2));
6583 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(2));
6584 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
6586 ADD_INSN1(ret, line_node, putobject,
Qfalse);
6587 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
6589 ADD_INSN(ret, line_node, pop);
6590 ADD_INSN(ret, line_node, pop);
6592 ADD_INSNL(ret, line_node, jump, match_failed);
6593 ADD_INSN1(ret, line_node, dupn,
INT2FIX(3));
6595 ADD_LABEL(ret, find_succeeded);
6596 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(3));
6599 ADD_INSN(ret, line_node, pop);
6600 ADD_INSNL(ret, line_node, jump, matched);
6601 ADD_INSN(ret, line_node, putnil);
6603 ADD_LABEL(ret, type_error);
6604 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6606 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct must return Array"));
6607 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
6608 ADD_INSN(ret, line_node, pop);
6610 ADD_LABEL(ret, match_failed);
6611 ADD_INSN(ret, line_node, pop);
6612 ADD_INSNL(ret, line_node, jump, unmatched);
6676 LABEL *match_failed, *type_error;
6679 match_failed = NEW_LABEL(line);
6680 type_error = NEW_LABEL(line);
6682 if (node->nd_pkwargs && !node->nd_pkwrestarg) {
6683 const NODE *kw_args = node->nd_pkwargs->nd_head;
6684 keys = rb_ary_new_capa(kw_args ? kw_args->nd_alen/2 : 0);
6686 rb_ary_push(keys, kw_args->nd_head->nd_lit);
6687 kw_args = kw_args->nd_next->nd_next;
6691 CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
6693 ADD_INSN(ret, line_node, dup);
6694 ADD_INSN1(ret, line_node, putobject,
ID2SYM(rb_intern(
"deconstruct_keys")));
6695 ADD_SEND(ret, line_node, idRespond_to,
INT2FIX(1));
6696 if (in_single_pattern) {
6697 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p does not respond to #deconstruct_keys"), base_index + 1 ));
6699 ADD_INSNL(ret, line_node, branchunless, match_failed);
6702 ADD_INSN(ret, line_node, putnil);
6705 ADD_INSN1(ret, line_node, duparray, keys);
6708 ADD_SEND(ret, line_node, rb_intern(
"deconstruct_keys"),
INT2FIX(1));
6710 ADD_INSN(ret, line_node, dup);
6712 ADD_INSNL(ret, line_node, branchunless, type_error);
6714 if (node->nd_pkwrestarg) {
6715 ADD_SEND(ret, line_node, rb_intern(
"dup"),
INT2FIX(0));
6718 if (node->nd_pkwargs) {
6722 args = node->nd_pkwargs->nd_head;
6724 DECL_ANCHOR(match_values);
6725 INIT_ANCHOR(match_values);
6727 for (i = 0; i < keys_num; i++) {
6728 NODE *key_node = args->nd_head;
6729 NODE *value_node = args->nd_next->nd_head;
6732 if (!nd_type_p(key_node, NODE_LIT)) {
6733 UNKNOWN_NODE(
"NODE_IN", key_node, COMPILE_NG);
6735 key = key_node->nd_lit;
6737 ADD_INSN(ret, line_node, dup);
6738 ADD_INSN1(ret, line_node, putobject, key);
6739 ADD_SEND(ret, line_node, rb_intern(
"key?"),
INT2FIX(1));
6740 if (in_single_pattern) {
6741 LABEL *match_succeeded;
6742 match_succeeded = NEW_LABEL(line);
6744 ADD_INSN(ret, line_node, dup);
6745 ADD_INSNL(ret, line_node, branchif, match_succeeded);
6748 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 2 ));
6749 ADD_INSN1(ret, line_node, putobject,
Qtrue);
6750 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 3 ));
6751 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
6752 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4 ));
6753 ADD_INSN1(ret, line_node, putobject, key);
6754 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_KEY + 5 ));
6756 ADD_INSN1(ret, line_node, adjuststack,
INT2FIX(4));
6758 ADD_LABEL(ret, match_succeeded);
6760 ADD_INSNL(ret, line_node, branchunless, match_failed);
6762 ADD_INSN(match_values, line_node, dup);
6763 ADD_INSN1(match_values, line_node, putobject, key);
6764 ADD_SEND(match_values, line_node, node->nd_pkwrestarg ? rb_intern(
"delete") : idAREF,
INT2FIX(1));
6765 CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
6766 args = args->nd_next->nd_next;
6768 ADD_SEQ(ret, match_values);
6772 ADD_INSN(ret, line_node, dup);
6773 ADD_SEND(ret, line_node, idEmptyP,
INT2FIX(0));
6774 if (in_single_pattern) {
6775 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p is not empty"), base_index + 1 ));
6777 ADD_INSNL(ret, line_node, branchunless, match_failed);
6780 if (node->nd_pkwrestarg) {
6781 if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
6782 ADD_INSN(ret, line_node, dup);
6783 ADD_SEND(ret, line_node, idEmptyP,
INT2FIX(0));
6784 if (in_single_pattern) {
6785 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"rest of %p is not empty"), base_index + 1 ));
6787 ADD_INSNL(ret, line_node, branchunless, match_failed);
6790 ADD_INSN(ret, line_node, dup);
6791 CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_pkwrestarg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 ,
false));
6795 ADD_INSN(ret, line_node, pop);
6796 ADD_INSNL(ret, line_node, jump, matched);
6797 ADD_INSN(ret, line_node, putnil);
6799 ADD_LABEL(ret, type_error);
6800 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6802 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"deconstruct_keys must return Hash"));
6803 ADD_SEND(ret, line_node, id_core_raise,
INT2FIX(2));
6804 ADD_INSN(ret, line_node, pop);
6806 ADD_LABEL(ret, match_failed);
6807 ADD_INSN(ret, line_node, pop);
6808 ADD_INSNL(ret, line_node, jump, unmatched);
6835 CHECK(COMPILE(ret,
"case in literal", node));
6836 if (in_single_pattern) {
6837 ADD_INSN1(ret, line_node, dupn,
INT2FIX(2));
6839 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
6840 if (in_single_pattern) {
6841 CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 2 ));
6843 ADD_INSNL(ret, line_node, branchif, matched);
6844 ADD_INSNL(ret, line_node, jump, unmatched);
6848 ID id = node->nd_vid;
6849 int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
6851 if (in_alt_pattern) {
6853 if (name && strlen(name) > 0 && name[0] !=
'_') {
6854 COMPILE_ERROR(ERROR_ARGS
"illegal variable in alternative pattern (%"PRIsVALUE
")",
6860 ADD_SETLOCAL(ret, line_node, idx, get_lvar_level(iseq));
6861 ADD_INSNL(ret, line_node, jump, matched);
6866 ID id = node->nd_vid;
6868 idx = get_dyna_var_idx(iseq,
id, &lv, &ls);
6870 if (in_alt_pattern) {
6872 if (name && strlen(name) > 0 && name[0] !=
'_') {
6873 COMPILE_ERROR(ERROR_ARGS
"illegal variable in alternative pattern (%"PRIsVALUE
")",
6880 COMPILE_ERROR(ERROR_ARGS
"NODE_DASGN: unknown id (%"PRIsVALUE
")",
6884 ADD_SETLOCAL(ret, line_node, ls - idx, lv);
6885 ADD_INSNL(ret, line_node, jump, matched);
6890 LABEL *match_failed;
6891 match_failed = unmatched;
6892 CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_body, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
6893 CHECK(COMPILE(ret,
"case in if", node->nd_cond));
6894 if (in_single_pattern) {
6895 LABEL *match_succeeded;
6896 match_succeeded = NEW_LABEL(line);
6898 ADD_INSN(ret, line_node, dup);
6899 if (nd_type_p(node, NODE_IF)) {
6900 ADD_INSNL(ret, line_node, branchif, match_succeeded);
6903 ADD_INSNL(ret, line_node, branchunless, match_succeeded);
6906 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"guard clause does not return true"));
6907 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
6908 ADD_INSN1(ret, line_node, putobject,
Qfalse);
6909 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
6911 ADD_INSN(ret, line_node, pop);
6912 ADD_INSN(ret, line_node, pop);
6914 ADD_LABEL(ret, match_succeeded);
6916 if (nd_type_p(node, NODE_IF)) {
6917 ADD_INSNL(ret, line_node, branchunless, match_failed);
6920 ADD_INSNL(ret, line_node, branchif, match_failed);
6922 ADD_INSNL(ret, line_node, jump, matched);
6927 LABEL *match_failed;
6928 match_failed = NEW_LABEL(line);
6931 if (! (nd_type_p(n, NODE_LIST) && n->nd_alen == 2)) {
6932 COMPILE_ERROR(ERROR_ARGS
"unexpected node");
6936 ADD_INSN(ret, line_node, dup);
6937 CHECK(iseq_compile_pattern_match(iseq, ret, n->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 , use_deconstructed_cache));
6938 CHECK(iseq_compile_pattern_each(iseq, ret, n->nd_next->nd_head, matched, match_failed, in_single_pattern, in_alt_pattern, base_index,
false));
6939 ADD_INSN(ret, line_node, putnil);
6941 ADD_LABEL(ret, match_failed);
6942 ADD_INSN(ret, line_node, pop);
6943 ADD_INSNL(ret, line_node, jump, unmatched);
6947 LABEL *match_succeeded, *fin;
6948 match_succeeded = NEW_LABEL(line);
6949 fin = NEW_LABEL(line);
6951 ADD_INSN(ret, line_node, dup);
6952 CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_1st, match_succeeded, fin, in_single_pattern,
true, base_index + 1 , use_deconstructed_cache));
6953 ADD_LABEL(ret, match_succeeded);
6954 ADD_INSN(ret, line_node, pop);
6955 ADD_INSNL(ret, line_node, jump, matched);
6956 ADD_INSN(ret, line_node, putnil);
6957 ADD_LABEL(ret, fin);
6958 CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_2nd, matched, unmatched, in_single_pattern,
true, base_index, use_deconstructed_cache));
6962 UNKNOWN_NODE(
"NODE_IN", node, COMPILE_NG);
6968iseq_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)
6970 LABEL *fin = NEW_LABEL(nd_line(node));
6971 CHECK(iseq_compile_pattern_each(iseq, ret, node, fin, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
6972 ADD_LABEL(ret, fin);
6977iseq_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)
6979 const NODE *line_node = node;
6981 if (node->nd_pconst) {
6982 ADD_INSN(ret, line_node, dup);
6983 CHECK(COMPILE(ret,
"constant", node->nd_pconst));
6984 if (in_single_pattern) {
6985 ADD_INSN1(ret, line_node, dupn,
INT2FIX(2));
6987 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_CASE));
6988 if (in_single_pattern) {
6989 CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 3 ));
6991 ADD_INSNL(ret, line_node, branchunless, match_failed);
6998iseq_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)
7000 const NODE *line_node = node;
7004 if (use_deconstructed_cache) {
7006 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
7007 ADD_INSNL(ret, line_node, branchnil, deconstruct);
7010 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
7011 ADD_INSNL(ret, line_node, branchunless, match_failed);
7014 ADD_INSN(ret, line_node, pop);
7015 ADD_INSN1(ret, line_node, topn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE - 1 ));
7016 ADD_INSNL(ret, line_node, jump, deconstructed);
7019 ADD_INSNL(ret, line_node, jump, deconstruct);
7022 ADD_LABEL(ret, deconstruct);
7023 ADD_INSN(ret, line_node, dup);
7024 ADD_INSN1(ret, line_node, putobject,
ID2SYM(rb_intern(
"deconstruct")));
7025 ADD_SEND(ret, line_node, idRespond_to,
INT2FIX(1));
7028 if (use_deconstructed_cache) {
7029 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE + 1 ));
7032 if (in_single_pattern) {
7033 CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit(
"%p does not respond to #deconstruct"), base_index + 1 ));
7036 ADD_INSNL(ret, line_node, branchunless, match_failed);
7038 ADD_SEND(ret, line_node, rb_intern(
"deconstruct"),
INT2FIX(0));
7041 if (use_deconstructed_cache) {
7042 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
7045 ADD_INSN(ret, line_node, dup);
7047 ADD_INSNL(ret, line_node, branchunless, type_error);
7049 ADD_LABEL(ret, deconstructed);
7065 const int line = nd_line(node);
7066 const NODE *line_node = node;
7067 LABEL *match_succeeded = NEW_LABEL(line);
7069 ADD_INSN(ret, line_node, dup);
7070 ADD_INSNL(ret, line_node, branchif, match_succeeded);
7072 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7073 ADD_INSN1(ret, line_node, putobject, errmsg);
7074 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7075 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(2));
7076 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
7078 ADD_INSN1(ret, line_node, putobject,
Qfalse);
7079 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
7081 ADD_INSN(ret, line_node, pop);
7082 ADD_INSN(ret, line_node, pop);
7083 ADD_LABEL(ret, match_succeeded);
7099 const int line = nd_line(node);
7100 const NODE *line_node = node;
7101 LABEL *match_succeeded = NEW_LABEL(line);
7103 ADD_INSN(ret, line_node, dup);
7104 ADD_INSNL(ret, line_node, branchif, match_succeeded);
7106 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7107 ADD_INSN1(ret, line_node, putobject, errmsg);
7108 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7109 ADD_INSN(ret, line_node, dup);
7110 ADD_SEND(ret, line_node, idLength,
INT2FIX(0));
7111 ADD_INSN1(ret, line_node, putobject, pattern_length);
7112 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(4));
7113 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
7115 ADD_INSN1(ret, line_node, putobject,
Qfalse);
7116 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2));
7118 ADD_INSN(ret, line_node, pop);
7119 ADD_INSN(ret, line_node, pop);
7120 ADD_LABEL(ret, match_succeeded);
7126iseq_compile_pattern_set_eqq_errmsg(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
int base_index)
7136 const int line = nd_line(node);
7137 const NODE *line_node = node;
7138 LABEL *match_succeeded = NEW_LABEL(line);
7140 ADD_INSN(ret, line_node, dup);
7141 ADD_INSNL(ret, line_node, branchif, match_succeeded);
7143 ADD_INSN1(ret, line_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7144 ADD_INSN1(ret, line_node, putobject, rb_fstring_lit(
"%p === %p does not return true"));
7145 ADD_INSN1(ret, line_node, topn,
INT2FIX(3));
7146 ADD_INSN1(ret, line_node, topn,
INT2FIX(5));
7147 ADD_SEND(ret, line_node, id_core_sprintf,
INT2FIX(3));
7148 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 ));
7150 ADD_INSN1(ret, line_node, putobject,
Qfalse);
7151 ADD_INSN1(ret, line_node, setn,
INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 ));
7153 ADD_INSN(ret, line_node, pop);
7154 ADD_INSN(ret, line_node, pop);
7156 ADD_LABEL(ret, match_succeeded);
7157 ADD_INSN1(ret, line_node, setn,
INT2FIX(2));
7158 ADD_INSN(ret, line_node, pop);
7159 ADD_INSN(ret, line_node, pop);
7167 const NODE *pattern;
7168 const NODE *node = orig_node;
7169 LABEL *endlabel, *elselabel;
7171 DECL_ANCHOR(body_seq);
7172 DECL_ANCHOR(cond_seq);
7174 enum node_type
type;
7175 const NODE *line_node;
7178 bool single_pattern;
7181 INIT_ANCHOR(body_seq);
7182 INIT_ANCHOR(cond_seq);
7184 branches = decl_branch_base(iseq, node,
"case");
7186 node = node->nd_body;
7187 EXPECT_NODE(
"NODE_CASE3", node, NODE_IN, COMPILE_NG);
7188 type = nd_type(node);
7189 line = nd_line(node);
7191 single_pattern = !node->nd_next;
7193 endlabel = NEW_LABEL(line);
7194 elselabel = NEW_LABEL(line);
7196 if (single_pattern) {
7198 ADD_INSN(head, line_node, putnil);
7199 ADD_INSN(head, line_node, putnil);
7200 ADD_INSN1(head, line_node, putobject,
Qfalse);
7201 ADD_INSN(head, line_node, putnil);
7203 ADD_INSN(head, line_node, putnil);
7205 CHECK(COMPILE(head,
"case base", orig_node->nd_head));
7209 while (
type == NODE_IN) {
7213 ADD_INSN(body_seq, line_node, putnil);
7215 l1 = NEW_LABEL(line);
7216 ADD_LABEL(body_seq, l1);
7217 ADD_INSN1(body_seq, line_node, adjuststack,
INT2FIX(single_pattern ? 6 : 2));
7218 add_trace_branch_coverage(
7221 node->nd_body ? node->nd_body : node,
7225 CHECK(COMPILE_(body_seq,
"in body", node->nd_body, popped));
7226 ADD_INSNL(body_seq, line_node, jump, endlabel);
7228 pattern = node->nd_head;
7230 int pat_line = nd_line(pattern);
7231 LABEL *next_pat = NEW_LABEL(pat_line);
7232 ADD_INSN (cond_seq, pattern, dup);
7234 CHECK(iseq_compile_pattern_each(iseq, cond_seq, pattern, l1, next_pat, single_pattern,
false, 2,
true));
7235 ADD_LABEL(cond_seq, next_pat);
7236 LABEL_UNREMOVABLE(next_pat);
7239 COMPILE_ERROR(ERROR_ARGS
"unexpected node");
7243 node = node->nd_next;
7247 type = nd_type(node);
7248 line = nd_line(node);
7253 ADD_LABEL(cond_seq, elselabel);
7254 ADD_INSN(cond_seq, line_node, pop);
7255 ADD_INSN(cond_seq, line_node, pop);
7256 add_trace_branch_coverage(iseq, cond_seq, node, branch_id,
"else", branches);
7257 CHECK(COMPILE_(cond_seq,
"else", node, popped));
7258 ADD_INSNL(cond_seq, line_node, jump, endlabel);
7259 ADD_INSN(cond_seq, line_node, putnil);
7261 ADD_INSN(cond_seq, line_node, putnil);
7265 debugs(
"== else (implicit)\n");
7266 ADD_LABEL(cond_seq, elselabel);
7267 add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id,
"else", branches);
7268 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7270 if (single_pattern) {
7278 LABEL *key_error, *fin;
7281 key_error = NEW_LABEL(line);
7282 fin = NEW_LABEL(line);
7285 kw_arg->keyword_len = 2;
7286 kw_arg->keywords[0] =
ID2SYM(rb_intern(
"matchee"));
7287 kw_arg->keywords[1] =
ID2SYM(rb_intern(
"key"));
7289 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_P + 2));
7290 ADD_INSNL(cond_seq, orig_node, branchif, key_error);
7292 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7293 ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit(
"%p: %s"));
7294 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(4));
7295 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6));
7296 ADD_SEND(cond_seq, orig_node, id_core_sprintf,
INT2FIX(3));
7297 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(2));
7298 ADD_INSNL(cond_seq, orig_node, jump, fin);
7300 ADD_LABEL(cond_seq, key_error);
7302 ADD_INSN1(cond_seq, orig_node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
7303 ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit(
"%p: %s"));
7304 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(4));
7305 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6));
7306 ADD_SEND(cond_seq, orig_node, id_core_sprintf,
INT2FIX(3));
7307 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4));
7308 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_KEY + 5));
7309 ADD_SEND_R(cond_seq, orig_node, rb_intern(
"new"),
INT2FIX(1), NULL,
INT2FIX(VM_CALL_KWARG), kw_arg);
7310 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(1));
7312 ADD_LABEL(cond_seq, fin);
7316 ADD_INSN1(cond_seq, orig_node, topn,
INT2FIX(2));
7317 ADD_SEND(cond_seq, orig_node, id_core_raise,
INT2FIX(2));
7319 ADD_INSN1(cond_seq, orig_node, adjuststack,
INT2FIX(single_pattern ? 7 : 3));
7321 ADD_INSN(cond_seq, orig_node, putnil);
7323 ADD_INSNL(cond_seq, orig_node, jump, endlabel);
7324 ADD_INSN1(cond_seq, orig_node, dupn,
INT2FIX(single_pattern ? 5 : 1));
7326 ADD_INSN(cond_seq, line_node, putnil);
7330 ADD_SEQ(ret, cond_seq);
7331 ADD_SEQ(ret, body_seq);
7332 ADD_LABEL(ret, endlabel);
7336#undef CASE3_BI_OFFSET_DECONSTRUCTED_CACHE
7337#undef CASE3_BI_OFFSET_ERROR_STRING
7338#undef CASE3_BI_OFFSET_KEY_ERROR_P
7339#undef CASE3_BI_OFFSET_KEY_ERROR_MATCHEE
7340#undef CASE3_BI_OFFSET_KEY_ERROR_KEY
7345 const int line = (int)nd_line(node);
7346 const NODE *line_node = node;
7348 LABEL *prev_start_label = ISEQ_COMPILE_DATA(iseq)->start_label;
7349 LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label;
7350 LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label;
7351 int prev_loopval_popped = ISEQ_COMPILE_DATA(iseq)->loopval_popped;
7356 LABEL *next_label = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(line);
7357 LABEL *redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label = NEW_LABEL(line);
7358 LABEL *break_label = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(line);
7359 LABEL *end_label = NEW_LABEL(line);
7360 LABEL *adjust_label = NEW_LABEL(line);
7362 LABEL *next_catch_label = NEW_LABEL(line);
7363 LABEL *tmp_label = NULL;
7365 ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0;
7366 push_ensure_entry(iseq, &enl, NULL, NULL);
7368 if (node->nd_state == 1) {
7369 ADD_INSNL(ret, line_node, jump, next_label);
7372 tmp_label = NEW_LABEL(line);
7373 ADD_INSNL(ret, line_node, jump, tmp_label);
7375 ADD_LABEL(ret, adjust_label);
7376 ADD_INSN(ret, line_node, putnil);
7377 ADD_LABEL(ret, next_catch_label);
7378 ADD_INSN(ret, line_node, pop);
7379 ADD_INSNL(ret, line_node, jump, next_label);
7380 if (tmp_label) ADD_LABEL(ret, tmp_label);
7382 ADD_LABEL(ret, redo_label);
7383 branches = decl_branch_base(iseq, node,
type == NODE_WHILE ?
"while" :
"until");
7384 add_trace_branch_coverage(
7387 node->nd_body ? node->nd_body : node,
7391 CHECK(COMPILE_POPPED(ret,
"while body", node->nd_body));
7392 ADD_LABEL(ret, next_label);
7394 if (
type == NODE_WHILE) {
7395 compile_branch_condition(iseq, ret, node->nd_cond,
7396 redo_label, end_label);
7400 compile_branch_condition(iseq, ret, node->nd_cond,
7401 end_label, redo_label);
7404 ADD_LABEL(ret, end_label);
7405 ADD_ADJUST_RESTORE(ret, adjust_label);
7407 if (UNDEF_P(node->nd_state)) {
7409 COMPILE_ERROR(ERROR_ARGS
"unsupported: putundef");
7413 ADD_INSN(ret, line_node, putnil);
7416 ADD_LABEL(ret, break_label);
7419 ADD_INSN(ret, line_node, pop);
7422 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, NULL,
7424 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, NULL,
7426 ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, NULL,
7427 ISEQ_COMPILE_DATA(iseq)->redo_label);
7429 ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label;
7430 ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label;
7431 ISEQ_COMPILE_DATA(iseq)->redo_label = prev_redo_label;
7432 ISEQ_COMPILE_DATA(iseq)->loopval_popped = prev_loopval_popped;
7433 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->prev;
7440 const int line = nd_line(node);
7441 const NODE *line_node = node;
7442 const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(iseq)->current_block;
7443 LABEL *retry_label = NEW_LABEL(line);
7444 LABEL *retry_end_l = NEW_LABEL(line);
7447 ADD_LABEL(ret, retry_label);
7448 if (nd_type_p(node, NODE_FOR)) {
7449 CHECK(COMPILE(ret,
"iter caller (for)", node->nd_iter));
7451 ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
7452 NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
7453 ISEQ_TYPE_BLOCK, line);
7454 ADD_SEND_WITH_BLOCK(ret, line_node, idEach,
INT2FIX(0), child_iseq);
7457 ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
7458 NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
7459 ISEQ_TYPE_BLOCK, line);
7460 CHECK(COMPILE(ret,
"iter caller", node->nd_iter));
7474 iobj = IS_INSN(last_elem) ? (
INSN*) last_elem : (
INSN*) get_prev_insn((
INSN*) last_elem);
7475 while (INSN_OF(iobj) != BIN(send) && INSN_OF(iobj) != BIN(invokesuper)) {
7476 iobj = (
INSN*) get_prev_insn(iobj);
7478 ELEM_INSERT_NEXT(&iobj->link, (
LINK_ELEMENT*) retry_end_l);
7482 if (&iobj->link == LAST_ELEMENT(ret)) {
7488 ADD_INSN(ret, line_node, pop);
7491 ISEQ_COMPILE_DATA(iseq)->current_block = prevblock;
7493 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l);
7503 const NODE *line_node = node;
7504 const NODE *var = node->nd_var;
7505 LABEL *not_single = NEW_LABEL(nd_line(var));
7506 LABEL *not_ary = NEW_LABEL(nd_line(var));
7507 CHECK(COMPILE(ret,
"for var", var));
7508 ADD_INSN(ret, line_node, dup);
7509 ADD_CALL(ret, line_node, idLength,
INT2FIX(0));
7510 ADD_INSN1(ret, line_node, putobject,
INT2FIX(1));
7511 ADD_CALL(ret, line_node, idEq,
INT2FIX(1));
7512 ADD_INSNL(ret, line_node, branchunless, not_single);
7513 ADD_INSN(ret, line_node, dup);
7514 ADD_INSN1(ret, line_node, putobject,
INT2FIX(0));
7515 ADD_CALL(ret, line_node, idAREF,
INT2FIX(1));
7516 ADD_INSN1(ret, line_node, putobject,
rb_cArray);
7517 ADD_INSN(ret, line_node, swap);
7518 ADD_CALL(ret, line_node, rb_intern(
"try_convert"),
INT2FIX(1));
7519 ADD_INSN(ret, line_node, dup);
7520 ADD_INSNL(ret, line_node, branchunless, not_ary);
7521 ADD_INSN(ret, line_node, swap);
7522 ADD_LABEL(ret, not_ary);
7523 ADD_INSN(ret, line_node, pop);
7524 ADD_LABEL(ret, not_single);
7531 const NODE *line_node = node;
7532 unsigned long throw_flag = 0;
7534 if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
7536 LABEL *splabel = NEW_LABEL(0);
7537 ADD_LABEL(ret, splabel);
7538 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
7539 CHECK(COMPILE_(ret,
"break val (while/until)", node->nd_stts,
7540 ISEQ_COMPILE_DATA(iseq)->loopval_popped));
7541 add_ensure_iseq(ret, iseq, 0);
7542 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
7543 ADD_ADJUST_RESTORE(ret, splabel);
7546 ADD_INSN(ret, line_node, putnil);
7553 if (!ISEQ_COMPILE_DATA(ip)) {
7558 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
7559 throw_flag = VM_THROW_NO_ESCAPE_FLAG;
7561 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
7564 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
7565 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with break");
7569 ip = ISEQ_BODY(ip)->parent_iseq;
7574 CHECK(COMPILE(ret,
"break val (block)", node->nd_stts));
7575 ADD_INSN1(ret, line_node,
throw,
INT2FIX(throw_flag | TAG_BREAK));
7577 ADD_INSN(ret, line_node, pop);
7581 COMPILE_ERROR(ERROR_ARGS
"Invalid break");
7590 const NODE *line_node = node;
7591 unsigned long throw_flag = 0;
7593 if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
7594 LABEL *splabel = NEW_LABEL(0);
7595 debugs(
"next in while loop\n");
7596 ADD_LABEL(ret, splabel);
7597 CHECK(COMPILE(ret,
"next val/valid syntax?", node->nd_stts));
7598 add_ensure_iseq(ret, iseq, 0);
7599 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
7600 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
7601 ADD_ADJUST_RESTORE(ret, splabel);
7603 ADD_INSN(ret, line_node, putnil);
7606 else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) {
7607 LABEL *splabel = NEW_LABEL(0);
7608 debugs(
"next in block\n");
7609 ADD_LABEL(ret, splabel);
7610 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
7611 CHECK(COMPILE(ret,
"next val", node->nd_stts));
7612 add_ensure_iseq(ret, iseq, 0);
7613 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
7614 ADD_ADJUST_RESTORE(ret, splabel);
7615 splabel->unremovable = FALSE;
7618 ADD_INSN(ret, line_node, putnil);
7625 if (!ISEQ_COMPILE_DATA(ip)) {
7630 throw_flag = VM_THROW_NO_ESCAPE_FLAG;
7631 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
7635 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
7638 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
7639 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with next");
7643 ip = ISEQ_BODY(ip)->parent_iseq;
7646 CHECK(COMPILE(ret,
"next val", node->nd_stts));
7647 ADD_INSN1(ret, line_node,
throw,
INT2FIX(throw_flag | TAG_NEXT));
7650 ADD_INSN(ret, line_node, pop);
7654 COMPILE_ERROR(ERROR_ARGS
"Invalid next");
7664 const NODE *line_node = node;
7666 if (ISEQ_COMPILE_DATA(iseq)->redo_label && can_add_ensure_iseq(iseq)) {
7667 LABEL *splabel = NEW_LABEL(0);
7668 debugs(
"redo in while");
7669 ADD_LABEL(ret, splabel);
7670 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
7671 add_ensure_iseq(ret, iseq, 0);
7672 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
7673 ADD_ADJUST_RESTORE(ret, splabel);
7675 ADD_INSN(ret, line_node, putnil);
7678 else if (ISEQ_BODY(iseq)->
type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) {
7679 LABEL *splabel = NEW_LABEL(0);
7681 debugs(
"redo in block");
7682 ADD_LABEL(ret, splabel);
7683 add_ensure_iseq(ret, iseq, 0);
7684 ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
7685 ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
7686 ADD_ADJUST_RESTORE(ret, splabel);
7689 ADD_INSN(ret, line_node, putnil);
7696 if (!ISEQ_COMPILE_DATA(ip)) {
7701 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
7704 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_BLOCK) {
7707 else if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_EVAL) {
7708 COMPILE_ERROR(ERROR_ARGS
"Can't escape from eval with redo");
7712 ip = ISEQ_BODY(ip)->parent_iseq;
7715 ADD_INSN(ret, line_node, putnil);
7716 ADD_INSN1(ret, line_node,
throw,
INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO));
7719 ADD_INSN(ret, line_node, pop);
7723 COMPILE_ERROR(ERROR_ARGS
"Invalid redo");
7733 const NODE *line_node = node;
7735 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE) {
7736 ADD_INSN(ret, line_node, putnil);
7737 ADD_INSN1(ret, line_node,
throw,
INT2FIX(TAG_RETRY));
7740 ADD_INSN(ret, line_node, pop);
7744 COMPILE_ERROR(ERROR_ARGS
"Invalid retry");
7753 const int line = nd_line(node);
7754 const NODE *line_node = node;
7755 LABEL *lstart = NEW_LABEL(line);
7756 LABEL *lend = NEW_LABEL(line);
7757 LABEL *lcont = NEW_LABEL(line);
7758 const rb_iseq_t *rescue = NEW_CHILD_ISEQ(node->nd_resq,
7760 ISEQ_BODY(iseq)->location.label),
7761 ISEQ_TYPE_RESCUE, line);
7763 lstart->rescued = LABEL_RESCUE_BEG;
7764 lend->rescued = LABEL_RESCUE_END;
7765 ADD_LABEL(ret, lstart);
7767 bool prev_in_rescue = ISEQ_COMPILE_DATA(iseq)->in_rescue;
7768 ISEQ_COMPILE_DATA(iseq)->in_rescue =
true;
7770 CHECK(COMPILE(ret,
"rescue head", node->nd_head));
7772 ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue;
7774 ADD_LABEL(ret, lend);
7775 if (node->nd_else) {
7776 ADD_INSN(ret, line_node, pop);
7777 CHECK(COMPILE(ret,
"rescue else", node->nd_else));
7779 ADD_INSN(ret, line_node, nop);
7780 ADD_LABEL(ret, lcont);
7783 ADD_INSN(ret, line_node, pop);
7787 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont);
7788 ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, NULL, lstart);
7795 const int line = nd_line(node);
7796 const NODE *line_node = node;
7797 const NODE *resq = node;
7799 LABEL *label_miss, *label_hit;
7802 label_miss = NEW_LABEL(line);
7803 label_hit = NEW_LABEL(line);
7805 narg = resq->nd_args;
7807 switch (nd_type(narg)) {
7810 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
7811 CHECK(COMPILE(ret,
"rescue arg", narg->nd_head));
7812 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
7813 ADD_INSNL(ret, line_node, branchif, label_hit);
7814 narg = narg->nd_next;
7820 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
7821 CHECK(COMPILE(ret,
"rescue/cond splat", narg));
7822 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY));
7823 ADD_INSNL(ret, line_node, branchif, label_hit);
7826 UNKNOWN_NODE(
"NODE_RESBODY", narg, COMPILE_NG);
7830 ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
7832 ADD_INSN1(ret, line_node, checkmatch,
INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
7833 ADD_INSNL(ret, line_node, branchif, label_hit);
7835 ADD_INSNL(ret, line_node, jump, label_miss);
7836 ADD_LABEL(ret, label_hit);
7837 CHECK(COMPILE(ret,
"resbody body", resq->nd_body));
7838 if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
7839 ADD_INSN(ret, line_node, nop);
7841 ADD_INSN(ret, line_node, leave);
7842 ADD_LABEL(ret, label_miss);
7843 resq = resq->nd_head;
7851 const int line = nd_line(node);
7852 const NODE *line_node = node;
7854 const rb_iseq_t *ensure = NEW_CHILD_ISEQ(node->nd_ensr,
7856 ISEQ_TYPE_ENSURE, line);
7857 LABEL *lstart = NEW_LABEL(line);
7858 LABEL *lend = NEW_LABEL(line);
7859 LABEL *lcont = NEW_LABEL(line);
7867 CHECK(COMPILE_POPPED(ensr,
"ensure ensr", node->nd_ensr));
7869 last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave);
7874 push_ensure_entry(iseq, &enl, &er, node->nd_ensr);
7876 ADD_LABEL(ret, lstart);
7877 CHECK(COMPILE_(ret,
"ensure head", node->nd_head, (popped | last_leave)));
7878 ADD_LABEL(ret, lend);
7880 if (!popped && last_leave) ADD_INSN(ret, line_node, putnil);
7881 ADD_LABEL(ret, lcont);
7882 if (last_leave) ADD_INSN(ret, line_node, pop);
7884 erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange;
7885 if (lstart->link.next != &lend->link) {
7887 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end,
7889 erange = erange->next;
7893 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev;
7900 const NODE *line_node = node;
7903 enum rb_iseq_type
type = ISEQ_BODY(iseq)->type;
7905 enum rb_iseq_type t =
type;
7906 const NODE *retval = node->nd_stts;
7909 while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) {
7910 if (!(is = ISEQ_BODY(is)->parent_iseq))
break;
7911 t = ISEQ_BODY(is)->type;
7915 case ISEQ_TYPE_MAIN:
7917 rb_warn(
"argument of top-level return is ignored");
7921 type = ISEQ_TYPE_METHOD;
7928 if (
type == ISEQ_TYPE_METHOD) {
7929 splabel = NEW_LABEL(0);
7930 ADD_LABEL(ret, splabel);
7931 ADD_ADJUST(ret, line_node, 0);
7934 CHECK(COMPILE(ret,
"return nd_stts (return val)", retval));
7936 if (
type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
7937 add_ensure_iseq(ret, iseq, 1);
7939 ADD_INSN(ret, line_node, leave);
7940 ADD_ADJUST_RESTORE(ret, splabel);
7943 ADD_INSN(ret, line_node, putnil);
7947 ADD_INSN1(ret, line_node,
throw,
INT2FIX(TAG_RETURN));
7949 ADD_INSN(ret, line_node, pop);
7959 CHECK(COMPILE_(ret,
"nd_body", node, popped));
7961 if (!popped && !all_string_result_p(node)) {
7962 const NODE *line_node = node;
7963 const unsigned int flag = VM_CALL_FCALL;
7967 ADD_INSN(ret, line_node, dup);
7968 ADD_INSN1(ret, line_node, objtostring, new_callinfo(iseq, idTo_s, 0, flag, NULL, FALSE));
7969 ADD_INSN(ret, line_node, anytostring);
7977 int idx = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
7979 debugs(
"id: %s idx: %d\n",
rb_id2name(
id), idx);
7980 ADD_GETLOCAL(ret, line_node, idx, get_lvar_level(iseq));
7986 LABEL *else_label = NEW_LABEL(nd_line(line_node));
7989 br = decl_branch_base(iseq, node,
"&.");
7991 ADD_INSN(recv, line_node, dup);
7992 ADD_INSNL(recv, line_node, branchnil, else_label);
7993 add_trace_branch_coverage(iseq, recv, node, 0,
"then", br);
8001 if (!else_label)
return;
8002 end_label = NEW_LABEL(nd_line(line_node));
8003 ADD_INSNL(ret, line_node, jump, end_label);
8004 ADD_LABEL(ret, else_label);
8005 add_trace_branch_coverage(iseq, ret, node, 1,
"else", branches);
8006 ADD_LABEL(ret, end_label);
8015 if (node->nd_recv && nd_type_p(node->nd_recv, NODE_STR) &&
8016 (node->nd_mid == idFreeze || node->nd_mid == idUMinus) &&
8017 node->nd_args == NULL &&
8018 ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
8019 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
8020 VALUE str = rb_fstring(node->nd_recv->nd_lit);
8021 if (node->nd_mid == idUMinus) {
8022 ADD_INSN2(ret, line_node, opt_str_uminus, str,
8023 new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE));
8026 ADD_INSN2(ret, line_node, opt_str_freeze, str,
8027 new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE));
8031 ADD_INSN(ret, line_node, pop);
8038 if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args &&
8039 nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 1 &&
8040 nd_type_p(node->nd_args->nd_head, NODE_STR) &&
8041 ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
8042 !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
8043 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
8044 VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
8045 CHECK(COMPILE(ret,
"recv", node->nd_recv));
8046 ADD_INSN2(ret, line_node, opt_aref_with, str,
8047 new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE));
8050 ADD_INSN(ret, line_node, pop);
8058iseq_has_builtin_function_table(
const rb_iseq_t *iseq)
8060 return ISEQ_COMPILE_DATA(iseq)->builtin_function_table != NULL;
8064iseq_builtin_function_lookup(
const rb_iseq_t *iseq,
const char *name)
8067 const struct rb_builtin_function *table = ISEQ_COMPILE_DATA(iseq)->builtin_function_table;
8068 for (i=0; table[i].index != -1; i++) {
8069 if (strcmp(table[i].name, name) == 0) {
8077iseq_builtin_function_name(
const enum node_type
type,
const NODE *recv,
ID mid)
8080 static const char prefix[] =
"__builtin_";
8081 const size_t prefix_len =
sizeof(prefix) - 1;
8086 switch (nd_type(recv)) {
8088 if (recv->nd_mid == rb_intern(
"__builtin")) {
8093 if (recv->nd_vid == rb_intern(
"Primitive")) {
8103 if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) {
8104 return &name[prefix_len];
8113delegate_call_p(
const rb_iseq_t *iseq,
unsigned int argc,
const LINK_ANCHOR *args,
unsigned int *pstart_index)
8120 else if (argc <= ISEQ_BODY(iseq)->local_table_size) {
8121 unsigned int start=0;
8126 argc + start <= ISEQ_BODY(iseq)->local_table_size;
8130 for (
unsigned int i=start; i-start<argc; i++) {
8131 if (IS_INSN(elem) &&
8132 INSN_OF(elem) == BIN(getlocal)) {
8133 int local_index =
FIX2INT(OPERAND_AT(elem, 0));
8134 int local_level =
FIX2INT(OPERAND_AT(elem, 1));
8136 if (local_level == 0) {
8137 unsigned int index = ISEQ_BODY(iseq)->local_table_size - (local_index - VM_ENV_DATA_SIZE + 1);
8139 fprintf(stderr,
"lvar:%s (%d), id:%s (%d) local_index:%d, local_size:%d\n",
8140 rb_id2name(ISEQ_BODY(iseq)->local_table[i]), i,
8141 rb_id2name(ISEQ_BODY(iseq)->local_table[index]), index,
8142 local_index, (
int)ISEQ_BODY(iseq)->local_table_size);
8166 *pstart_index = start;
8177 if (!node)
goto no_arg;
8178 if (!nd_type_p(node, NODE_LIST))
goto bad_arg;
8179 if (node->nd_next)
goto too_many_arg;
8180 node = node->nd_head;
8181 if (!node)
goto no_arg;
8182 if (!nd_type_p(node, NODE_LIT))
goto bad_arg;
8183 VALUE name = node->nd_lit;
8184 if (!
SYMBOL_P(name))
goto non_symbol_arg;
8186 compile_lvar(iseq, ret, line_node,
SYM2ID(name));
8190 COMPILE_ERROR(ERROR_ARGS
"arg!: no argument");
8193 COMPILE_ERROR(ERROR_ARGS
"arg!: too many argument");
8196 COMPILE_ERROR(ERROR_ARGS
"non symbol argument to arg!: %s",
8197 rb_builtin_class_name(name));
8200 UNKNOWN_NODE(
"arg!", node, COMPILE_NG);
8206 const NODE *node = ISEQ_COMPILE_DATA(iseq)->root_node;
8207 if (nd_type(node) == NODE_IF && node->nd_cond == cond_node) {
8208 return node->nd_body;
8211 rb_bug(
"mandatory_node: can't find mandatory node");
8216compile_builtin_mandatory_only_method(
rb_iseq_t *iseq,
const NODE *node,
const NODE *line_node)
8220 .pre_args_num = ISEQ_BODY(iseq)->param.lead_num,
8223 rb_node_init(&args_node, NODE_ARGS, 0, 0, (
VALUE)&args);
8226 const int skip_local_size = ISEQ_BODY(iseq)->param.size - ISEQ_BODY(iseq)->param.lead_num;
8227 const int table_size = ISEQ_BODY(iseq)->local_table_size - skip_local_size;
8231 tbl->size = table_size;
8236 for (i=0; i<ISEQ_BODY(iseq)->param.lead_num; i++) {
8237 tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i];
8240 for (; i<table_size; i++) {
8241 tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i + skip_local_size];
8245 rb_node_init(&scope_node, NODE_SCOPE, (
VALUE)tbl, (
VALUE)mandatory_node(iseq, node), (
VALUE)&args_node);
8248 .root = &scope_node,
8249 .compile_option = 0,
8250 .script_lines = ISEQ_BODY(iseq)->variable.script_lines,
8253 int prev_inline_index = GET_VM()->builtin_inline_index;
8255 ISEQ_BODY(iseq)->mandatory_only_iseq =
8256 rb_iseq_new_with_opt(&ast, rb_iseq_base_label(iseq),
8257 rb_iseq_path(iseq), rb_iseq_realpath(iseq),
8258 nd_line(line_node), NULL, 0,
8259 ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option);
8261 GET_VM()->builtin_inline_index = prev_inline_index;
8270 NODE *args_node = node->nd_args;
8272 if (parent_block != NULL) {
8273 COMPILE_ERROR(iseq, nd_line(line_node),
"should not call builtins here.");
8277# define BUILTIN_INLINE_PREFIX "_bi"
8278 char inline_func[
DECIMAL_SIZE_OF_BITS(
sizeof(
int) * CHAR_BIT) +
sizeof(BUILTIN_INLINE_PREFIX)];
8279 bool cconst =
false;
8284 if (strcmp(
"cstmt!", builtin_func) == 0 ||
8285 strcmp(
"cexpr!", builtin_func) == 0) {
8288 else if (strcmp(
"cconst!", builtin_func) == 0) {
8291 else if (strcmp(
"cinit!", builtin_func) == 0) {
8293 GET_VM()->builtin_inline_index++;
8296 else if (strcmp(
"attr!", builtin_func) == 0) {
8298 ISEQ_BODY(iseq)->builtin_inline_p =
true;
8301 else if (strcmp(
"arg!", builtin_func) == 0) {
8302 return compile_builtin_arg(iseq, ret, args_node, line_node, popped);
8304 else if (strcmp(
"mandatory_only?", builtin_func) == 0) {
8306 rb_bug(
"mandatory_only? should be in if condition");
8308 else if (!LIST_INSN_SIZE_ZERO(ret)) {
8309 rb_bug(
"mandatory_only? should be put on top");
8312 ADD_INSN1(ret, line_node, putobject,
Qfalse);
8313 return compile_builtin_mandatory_only_method(iseq, node, line_node);
8316 rb_bug(
"can't find builtin function:%s", builtin_func);
8319 COMPILE_ERROR(ERROR_ARGS
"can't find builtin function:%s", builtin_func);
8323 if (GET_VM()->builtin_inline_index == INT_MAX) {
8324 rb_bug(
"builtin inline function index overflow:%s", builtin_func);
8326 int inline_index = GET_VM()->builtin_inline_index++;
8327 snprintf(inline_func,
sizeof(inline_func), BUILTIN_INLINE_PREFIX
"%d", inline_index);
8328 builtin_func = inline_func;
8334 typedef VALUE(*builtin_func0)(
void *,
VALUE);
8335 VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL,
Qnil);
8336 ADD_INSN1(ret, line_node, putobject, const_val);
8342 unsigned int flag = 0;
8344 VALUE argc = setup_args(iseq, args, args_node, &flag, &keywords);
8346 if (
FIX2INT(argc) != bf->argc) {
8347 COMPILE_ERROR(ERROR_ARGS
"argc is not match for builtin function:%s (expect %d but %d)",
8348 builtin_func, bf->argc,
FIX2INT(argc));
8352 unsigned int start_index;
8353 if (delegate_call_p(iseq,
FIX2INT(argc), args, &start_index)) {
8354 ADD_INSN2(ret, line_node, opt_invokebuiltin_delegate, bf,
INT2FIX(start_index));
8358 ADD_INSN1(ret, line_node, invokebuiltin, bf);
8361 if (popped) ADD_INSN(ret, line_node, pop);
8367compile_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)
8375 ID mid = node->nd_mid;
8377 unsigned int flag = 0;
8379 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
8380 LABEL *else_label = NULL;
8383 ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
8388 if (nd_type_p(node, NODE_VCALL)) {
8393 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
8395 if (mid == id_bitblt) {
8396 ADD_INSN(ret, line_node, bitblt);
8399 else if (mid == id_answer) {
8400 ADD_INSN(ret, line_node, answer);
8412 if (nd_type_p(node, NODE_FCALL) &&
8413 (mid == goto_id || mid == label_id)) {
8416 st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
8419 if (!labels_table) {
8420 labels_table = st_init_numtable();
8421 ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
8423 if (nd_type_p(node->nd_args->nd_head, NODE_LIT) &&
8424 SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
8426 label_name = node->nd_args->nd_head->nd_lit;
8427 if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
8428 label = NEW_LABEL(nd_line(line_node));
8429 label->position = nd_line(line_node);
8430 st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
8433 label = (
LABEL *)data;
8437 COMPILE_ERROR(ERROR_ARGS
"invalid goto/label format");
8441 if (mid == goto_id) {
8442 ADD_INSNL(ret, line_node, jump, label);
8445 ADD_LABEL(ret, label);
8452 const char *builtin_func;
8453 if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
8454 (builtin_func = iseq_builtin_function_name(
type, node->nd_recv, mid)) != NULL) {
8455 return compile_builtin_function_call(iseq, ret, node, line_node, popped, parent_block, args, builtin_func);
8459 if (!assume_receiver) {
8460 if (
type == NODE_CALL ||
type == NODE_OPCALL ||
type == NODE_QCALL) {
8463 if (mid == idCall &&
8464 nd_type_p(node->nd_recv, NODE_LVAR) &&
8465 iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) {
8466 ADD_INSN2(recv, node->nd_recv, getblockparamproxy,
INT2FIX(idx + VM_ENV_DATA_SIZE - 1),
INT2FIX(level));
8468 else if (private_recv_p(node)) {
8469 ADD_INSN(recv, node, putself);
8470 flag |= VM_CALL_FCALL;
8473 CHECK(COMPILE(recv,
"recv", node->nd_recv));
8476 if (
type == NODE_QCALL) {
8477 else_label = qcall_branch_start(iseq, recv, &branches, node, line_node);
8480 else if (
type == NODE_FCALL ||
type == NODE_VCALL) {
8481 ADD_CALL_RECEIVER(recv, line_node);
8486 if (
type != NODE_VCALL) {
8487 argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
8488 CHECK(!
NIL_P(argc));
8497 debugp_param(
"call args argc", argc);
8498 debugp_param(
"call method",
ID2SYM(mid));
8500 switch ((
int)
type) {
8502 flag |= VM_CALL_VCALL;
8505 flag |= VM_CALL_FCALL;
8508 ADD_SEND_R(ret, line_node, mid, argc, parent_block,
INT2FIX(flag), keywords);
8510 qcall_branch_end(iseq, ret, else_label, branches, node, line_node);
8512 ADD_INSN(ret, line_node, pop);
8520 const int line = nd_line(node);
8522 unsigned int flag = 0;
8524 ID id = node->nd_mid;
8551 ADD_INSN(ret, node, putnil);
8553 asgnflag = COMPILE_RECV(ret,
"NODE_OP_ASGN1 recv", node);
8554 CHECK(asgnflag != -1);
8555 switch (nd_type(node->nd_args->nd_head)) {
8559 case NODE_BLOCK_PASS:
8563 argc = setup_args(iseq, ret, node->nd_args->nd_head, &flag, NULL);
8564 CHECK(!
NIL_P(argc));
8566 ADD_INSN1(ret, node, dupn, FIXNUM_INC(argc, 1 + boff));
8568 ADD_SEND_WITH_FLAG(ret, node, idAREF, argc,
INT2FIX(flag));
8570 if (
id == idOROP ||
id == idANDOP) {
8579 LABEL *label = NEW_LABEL(line);
8580 LABEL *lfin = NEW_LABEL(line);
8582 ADD_INSN(ret, node, dup);
8584 ADD_INSNL(ret, node, branchif, label);
8587 ADD_INSNL(ret, node, branchunless, label);
8589 ADD_INSN(ret, node, pop);
8591 CHECK(COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
8593 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
8595 if (flag & VM_CALL_ARGS_SPLAT) {
8596 ADD_INSN1(ret, node, newarray,
INT2FIX(1));
8598 ADD_INSN1(ret, node, dupn,
INT2FIX(3));
8599 ADD_INSN(ret, node, swap);
8600 ADD_INSN(ret, node, pop);
8602 ADD_INSN(ret, node, concatarray);
8604 ADD_INSN1(ret, node, setn,
INT2FIX(3));
8605 ADD_INSN(ret, node, pop);
8606 ADD_INSN(ret, node, pop);
8608 ADD_SEND_WITH_FLAG(ret, node, idASET, argc,
INT2FIX(flag));
8612 ADD_INSN(ret, node, swap);
8613 ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1),
INT2FIX(flag));
8615 ADD_INSN(ret, node, pop);
8616 ADD_INSNL(ret, node, jump, lfin);
8617 ADD_LABEL(ret, label);
8619 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
8621 ADD_INSN1(ret, node, adjuststack, FIXNUM_INC(argc, 2+boff));
8622 ADD_LABEL(ret, lfin);
8625 CHECK(COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
8626 ADD_SEND(ret, node,
id,
INT2FIX(1));
8628 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
8630 if (flag & VM_CALL_ARGS_SPLAT) {
8631 ADD_INSN1(ret, node, newarray,
INT2FIX(1));
8633 ADD_INSN1(ret, node, dupn,
INT2FIX(3));
8634 ADD_INSN(ret, node, swap);
8635 ADD_INSN(ret, node, pop);
8637 ADD_INSN(ret, node, concatarray);
8639 ADD_INSN1(ret, node, setn,
INT2FIX(3));
8640 ADD_INSN(ret, node, pop);
8641 ADD_INSN(ret, node, pop);
8643 ADD_SEND_WITH_FLAG(ret, node, idASET, argc,
INT2FIX(flag));
8647 ADD_INSN(ret, node, swap);
8648 ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1),
INT2FIX(flag));
8650 ADD_INSN(ret, node, pop);
8658 const int line = nd_line(node);
8659 ID atype = node->nd_next->nd_mid;
8662 LABEL *lfin = NEW_LABEL(line);
8663 LABEL *lcfin = NEW_LABEL(line);
8718 asgnflag = COMPILE_RECV(ret,
"NODE_OP_ASGN2#recv", node);
8719 CHECK(asgnflag != -1);
8720 if (node->nd_next->nd_aid) {
8721 lskip = NEW_LABEL(line);
8722 ADD_INSN(ret, node, dup);
8723 ADD_INSNL(ret, node, branchnil, lskip);
8725 ADD_INSN(ret, node, dup);
8726 ADD_SEND_WITH_FLAG(ret, node, vid,
INT2FIX(0),
INT2FIX(asgnflag));
8728 if (atype == idOROP || atype == idANDOP) {
8730 ADD_INSN(ret, node, dup);
8732 if (atype == idOROP) {
8733 ADD_INSNL(ret, node, branchif, lcfin);
8736 ADD_INSNL(ret, node, branchunless, lcfin);
8739 ADD_INSN(ret, node, pop);
8741 CHECK(COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
8743 ADD_INSN(ret, node, swap);
8744 ADD_INSN1(ret, node, topn,
INT2FIX(1));
8746 ADD_SEND_WITH_FLAG(ret, node, aid,
INT2FIX(1),
INT2FIX(asgnflag));
8747 ADD_INSNL(ret, node, jump, lfin);
8749 ADD_LABEL(ret, lcfin);
8751 ADD_INSN(ret, node, swap);
8754 ADD_LABEL(ret, lfin);
8757 CHECK(COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
8758 ADD_SEND(ret, node, atype,
INT2FIX(1));
8760 ADD_INSN(ret, node, swap);
8761 ADD_INSN1(ret, node, topn,
INT2FIX(1));
8763 ADD_SEND_WITH_FLAG(ret, node, aid,
INT2FIX(1),
INT2FIX(asgnflag));
8765 if (lskip && popped) {
8766 ADD_LABEL(ret, lskip);
8768 ADD_INSN(ret, node, pop);
8769 if (lskip && !popped) {
8770 ADD_LABEL(ret, lskip);
8778 const int line = nd_line(node);
8783 switch (nd_type(node->nd_head)) {
8788 CHECK(COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
8791 COMPILE_ERROR(ERROR_ARGS
"%s: invalid node in NODE_OP_CDECL",
8792 ruby_node_name(nd_type(node->nd_head)));
8795 mid = node->nd_head->nd_mid;
8797 if (node->nd_aid == idOROP) {
8798 lassign = NEW_LABEL(line);
8799 ADD_INSN(ret, node, dup);
8800 ADD_INSN3(ret, node, defined,
INT2FIX(DEFINED_CONST_FROM),
8802 ADD_INSNL(ret, node, branchunless, lassign);
8804 ADD_INSN(ret, node, dup);
8805 ADD_INSN1(ret, node, putobject,
Qtrue);
8806 ADD_INSN1(ret, node, getconstant,
ID2SYM(mid));
8808 if (node->nd_aid == idOROP || node->nd_aid == idANDOP) {
8809 lfin = NEW_LABEL(line);
8810 if (!popped) ADD_INSN(ret, node, dup);
8811 if (node->nd_aid == idOROP)
8812 ADD_INSNL(ret, node, branchif, lfin);
8814 ADD_INSNL(ret, node, branchunless, lfin);
8816 if (!popped) ADD_INSN(ret, node, pop);
8817 if (lassign) ADD_LABEL(ret, lassign);
8818 CHECK(COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
8821 ADD_INSN1(ret, node, topn,
INT2FIX(1));
8823 ADD_INSN1(ret, node, dupn,
INT2FIX(2));
8824 ADD_INSN(ret, node, swap);
8826 ADD_INSN1(ret, node, setconstant,
ID2SYM(mid));
8827 ADD_LABEL(ret, lfin);
8828 if (!popped) ADD_INSN(ret, node, swap);
8829 ADD_INSN(ret, node, pop);
8832 CHECK(COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
8834 ADD_CALL(ret, node, node->nd_aid,
INT2FIX(1));
8836 ADD_INSN(ret, node, swap);
8838 ADD_INSN1(ret, node, topn,
INT2FIX(1));
8839 ADD_INSN(ret, node, swap);
8841 ADD_INSN1(ret, node, setconstant,
ID2SYM(mid));
8849 const int line = nd_line(node);
8850 LABEL *lfin = NEW_LABEL(line);
8853 if (
type == NODE_OP_ASGN_OR && !nd_type_p(node->nd_head, NODE_IVAR)) {
8857 defined_expr(iseq, ret, node->nd_head, lfinish,
Qfalse);
8858 lassign = lfinish[1];
8860 lassign = NEW_LABEL(line);
8862 ADD_INSNL(ret, node, branchunless, lassign);
8865 lassign = NEW_LABEL(line);
8868 CHECK(COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
8871 ADD_INSN(ret, node, dup);
8874 if (
type == NODE_OP_ASGN_AND) {
8875 ADD_INSNL(ret, node, branchunless, lfin);
8878 ADD_INSNL(ret, node, branchif, lfin);
8882 ADD_INSN(ret, node, pop);
8885 ADD_LABEL(ret, lassign);
8886 CHECK(COMPILE_(ret,
"NODE_OP_ASGN_AND/OR#nd_value", node->nd_value, popped));
8887 ADD_LABEL(ret, lfin);
8897 unsigned int flag = 0;
8899 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
8902 ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
8903 if (
type == NODE_SUPER) {
8904 VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
8905 CHECK(!
NIL_P(vargc));
8911 const rb_iseq_t *liseq = body->local_iseq;
8913 const struct rb_iseq_param_keyword *
const local_kwd = local_body->
param.keyword;
8914 int lvar_level = get_lvar_level(iseq);
8916 argc = local_body->
param.lead_num;
8919 for (i = 0; i < local_body->
param.lead_num; i++) {
8920 int idx = local_body->local_table_size - i;
8921 ADD_GETLOCAL(args, node, idx, lvar_level);
8924 if (local_body->
param.flags.has_opt) {
8927 for (j = 0; j < local_body->
param.opt_num; j++) {
8928 int idx = local_body->local_table_size - (i + j);
8929 ADD_GETLOCAL(args, node, idx, lvar_level);
8934 if (local_body->
param.flags.has_rest) {
8936 int idx = local_body->local_table_size - local_body->
param.rest_start;
8937 ADD_GETLOCAL(args, node, idx, lvar_level);
8938 ADD_INSN1(args, node, splatarray,
Qfalse);
8940 argc = local_body->
param.rest_start + 1;
8941 flag |= VM_CALL_ARGS_SPLAT;
8943 if (local_body->
param.flags.has_post) {
8945 int post_len = local_body->
param.post_num;
8946 int post_start = local_body->
param.post_start;
8948 if (local_body->
param.flags.has_rest) {
8950 for (j=0; j<post_len; j++) {
8951 int idx = local_body->local_table_size - (post_start + j);
8952 ADD_GETLOCAL(args, node, idx, lvar_level);
8954 ADD_INSN1(args, node, newarray,
INT2FIX(j));
8955 ADD_INSN (args, node, concatarray);
8960 for (j=0; j<post_len; j++) {
8961 int idx = local_body->local_table_size - (post_start + j);
8962 ADD_GETLOCAL(args, node, idx, lvar_level);
8964 argc = post_len + post_start;
8968 if (local_body->
param.flags.has_kw) {
8969 int local_size = local_body->local_table_size;
8972 ADD_INSN1(args, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
8974 if (local_body->
param.flags.has_kwrest) {
8975 int idx = local_body->local_table_size - local_kwd->rest_start;
8976 ADD_GETLOCAL(args, node, idx, lvar_level);
8977 if (local_kwd->num > 0) {
8978 ADD_SEND (args, node, rb_intern(
"dup"),
INT2FIX(0));
8979 flag |= VM_CALL_KW_SPLAT_MUT;
8983 ADD_INSN1(args, node, newhash,
INT2FIX(0));
8984 flag |= VM_CALL_KW_SPLAT_MUT;
8986 for (i = 0; i < local_kwd->num; ++i) {
8987 ID id = local_kwd->table[i];
8988 int idx = local_size - get_local_var_idx(liseq,
id);
8989 ADD_INSN1(args, node, putobject,
ID2SYM(
id));
8990 ADD_GETLOCAL(args, node, idx, lvar_level);
8992 ADD_SEND(args, node, id_core_hash_merge_ptr,
INT2FIX(i * 2 + 1));
8993 if (local_body->
param.flags.has_rest) {
8994 ADD_INSN1(args, node, newarray,
INT2FIX(1));
8995 ADD_INSN (args, node, concatarray);
8998 flag |= VM_CALL_KW_SPLAT;
9000 else if (local_body->
param.flags.has_kwrest) {
9001 int idx = local_body->local_table_size - local_kwd->rest_start;
9002 ADD_GETLOCAL(args, node, idx, lvar_level);
9004 if (local_body->
param.flags.has_rest) {
9005 ADD_INSN1(args, node, newarray,
INT2FIX(1));
9006 ADD_INSN (args, node, concatarray);
9011 flag |= VM_CALL_KW_SPLAT;
9015 flag |= VM_CALL_SUPER | VM_CALL_FCALL;
9016 if (
type == NODE_ZSUPER) flag |= VM_CALL_ZSUPER;
9017 ADD_INSN(ret, node, putself);
9019 ADD_INSN2(ret, node, invokesuper,
9020 new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL),
9024 ADD_INSN(ret, node, pop);
9034 unsigned int flag = 0;
9039 switch (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->
type) {
9041 case ISEQ_TYPE_MAIN:
9042 case ISEQ_TYPE_CLASS:
9043 COMPILE_ERROR(ERROR_ARGS
"Invalid yield");
9048 if (node->nd_head) {
9049 argc = setup_args(iseq, args, node->nd_head, &flag, &keywords);
9050 CHECK(!
NIL_P(argc));
9057 ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0,
FIX2INT(argc), flag, keywords, FALSE));
9060 ADD_INSN(ret, node, pop);
9065 for (; tmp_iseq != ISEQ_BODY(iseq)->local_iseq; level++ ) {
9066 tmp_iseq = ISEQ_BODY(tmp_iseq)->parent_iseq;
9068 if (level > 0) access_outer_variables(iseq, level, rb_intern(
"yield"),
true);
9081 switch ((
int)
type) {
9083 ADD_INSN1(recv, node, putobject, node->nd_lit);
9084 ADD_INSN2(val, node, getspecial,
INT2FIX(0),
9088 CHECK(COMPILE(recv,
"receiver", node->nd_recv));
9089 CHECK(COMPILE(val,
"value", node->nd_value));
9092 CHECK(COMPILE(recv,
"receiver", node->nd_value));
9093 CHECK(COMPILE(val,
"value", node->nd_recv));
9099 ADD_SEND(ret, node, idEqTilde,
INT2FIX(1));
9101 if (node->nd_args) {
9102 compile_named_capture_assign(iseq, ret, node->nd_args);
9106 ADD_INSN(ret, node, pop);
9117 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache &&
9118 (segments = collect_const_segments(iseq, node))) {
9119 ISEQ_BODY(iseq)->ic_size++;
9120 ADD_INSN1(ret, node, opt_getconstant_path, segments);
9130 CHECK(compile_const_prefix(iseq, node, pref, body));
9131 if (LIST_INSN_SIZE_ZERO(pref)) {
9132 ADD_INSN(ret, node, putnil);
9143 ADD_CALL_RECEIVER(ret, node);
9144 CHECK(COMPILE(ret,
"colon2#nd_head", node->nd_head));
9145 ADD_CALL(ret, node, node->nd_mid,
INT2FIX(1));
9148 ADD_INSN(ret, node, pop);
9156 debugi(
"colon3#nd_mid", node->nd_mid);
9159 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
9160 ISEQ_BODY(iseq)->ic_size++;
9162 ADD_INSN1(ret, node, opt_getconstant_path, segments);
9167 ADD_INSN1(ret, node, putobject,
Qtrue);
9168 ADD_INSN1(ret, node, getconstant,
ID2SYM(node->nd_mid));
9172 ADD_INSN(ret, node, pop);
9181 const NODE *b = node->nd_beg;
9182 const NODE *e = node->nd_end;
9184 if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
9186 VALUE bv = nd_type_p(b, NODE_LIT) ? b->nd_lit :
Qnil;
9187 VALUE ev = nd_type_p(e, NODE_LIT) ? e->nd_lit :
Qnil;
9189 ADD_INSN1(ret, node, putobject, val);
9194 CHECK(COMPILE_(ret,
"min", b, popped));
9195 CHECK(COMPILE_(ret,
"max", e, popped));
9197 ADD_INSN1(ret, node, newrange, flag);
9207 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_RESCUE) {
9208 ADD_GETLOCAL(ret, node, LVAR_ERRINFO, 0);
9214 if (ISEQ_BODY(ip)->
type == ISEQ_TYPE_RESCUE) {
9217 ip = ISEQ_BODY(ip)->parent_iseq;
9221 ADD_GETLOCAL(ret, node, LVAR_ERRINFO, level);
9224 ADD_INSN(ret, node, putnil);
9235 LABEL *end_label = NEW_LABEL(nd_line(node));
9236 const NODE *default_value = node->nd_body->nd_value;
9238 if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) {
9240 COMPILE_ERROR(ERROR_ARGS
"unreachable");
9243 else if (nd_type_p(default_value, NODE_LIT) ||
9244 nd_type_p(default_value, NODE_NIL) ||
9245 nd_type_p(default_value, NODE_TRUE) ||
9246 nd_type_p(default_value, NODE_FALSE)) {
9247 COMPILE_ERROR(ERROR_ARGS
"unreachable");
9255 int kw_bits_idx = body->local_table_size - body->param.keyword->bits_start;
9256 int keyword_idx = body->param.keyword->num;
9258 ADD_INSN2(ret, node, checkkeyword,
INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1),
INT2FIX(keyword_idx));
9259 ADD_INSNL(ret, node, branchif, end_label);
9260 CHECK(COMPILE_POPPED(ret,
"keyword default argument", node->nd_body));
9261 ADD_LABEL(ret, end_label);
9271 unsigned int flag = 0;
9272 ID mid = node->nd_mid;
9274 LABEL *else_label = NULL;
9280 if (mid == idASET && !private_recv_p(node) && node->nd_args &&
9281 nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 2 &&
9282 nd_type_p(node->nd_args->nd_head, NODE_STR) &&
9283 ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
9284 !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
9285 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
9287 VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
9288 CHECK(COMPILE(ret,
"recv", node->nd_recv));
9289 CHECK(COMPILE(ret,
"value", node->nd_args->nd_next->nd_head));
9291 ADD_INSN(ret, node, swap);
9292 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9294 ADD_INSN2(ret, node, opt_aset_with, str,
9295 new_callinfo(iseq, idASET, 2, 0, NULL, FALSE));
9297 ADD_INSN(ret, node, pop);
9303 argc = setup_args(iseq, args, node->nd_args, &flag, NULL);
9304 CHECK(!
NIL_P(argc));
9306 int asgnflag = COMPILE_RECV(recv,
"recv", node);
9307 CHECK(asgnflag != -1);
9308 flag |= (
unsigned int)asgnflag;
9310 debugp_param(
"argc", argc);
9311 debugp_param(
"nd_mid",
ID2SYM(mid));
9316 else_label = qcall_branch_start(iseq, recv, &branches, node, node);
9319 ADD_INSN(ret, node, putnil);
9323 if (flag & VM_CALL_ARGS_BLOCKARG) {
9324 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9325 if (flag & VM_CALL_ARGS_SPLAT) {
9326 ADD_INSN1(ret, node, putobject,
INT2FIX(-1));
9327 ADD_SEND_WITH_FLAG(ret, node, idAREF,
INT2FIX(1),
INT2FIX(asgnflag));
9329 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 3));
9330 ADD_INSN (ret, node, pop);
9332 else if (flag & VM_CALL_ARGS_SPLAT) {
9333 ADD_INSN(ret, node, dup);
9334 ADD_INSN1(ret, node, putobject,
INT2FIX(-1));
9335 ADD_SEND_WITH_FLAG(ret, node, idAREF,
INT2FIX(1),
INT2FIX(asgnflag));
9336 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2));
9337 ADD_INSN (ret, node, pop);
9340 ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 1));
9347 ADD_SEND_WITH_FLAG(ret, node, mid, argc,
INT2FIX(flag));
9348 qcall_branch_end(iseq, ret, else_label, branches, node, node);
9349 ADD_INSN(ret, node, pop);
9366 int lineno = ISEQ_COMPILE_DATA(iseq)->last_line;
9367 if (lineno == 0) lineno =
FIX2INT(rb_iseq_first_lineno(iseq));
9368 debugs(
"node: NODE_NIL(implicit)\n");
9369 NODE dummy_line_node = generate_dummy_line_node(lineno, -1);
9370 ADD_INSN(ret, &dummy_line_node, putnil);
9374 return iseq_compile_each0(iseq, ret, node, popped);
9380 const int line = (int)nd_line(node);
9381 const enum node_type
type = nd_type(node);
9384 if (ISEQ_COMPILE_DATA(iseq)->last_line == line) {
9388 if (node->flags & NODE_FL_NEWLINE) {
9390 ISEQ_COMPILE_DATA(iseq)->last_line = line;
9391 if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
9392 event |= RUBY_EVENT_COVERAGE_LINE;
9394 ADD_TRACE(ret, event);
9398 debug_node_start(node);
9400#define BEFORE_RETURN debug_node_end()
9404 CHECK(compile_block(iseq, ret, node, popped));
9408 CHECK(compile_if(iseq, ret, node, popped,
type));
9411 CHECK(compile_case(iseq, ret, node, popped));
9414 CHECK(compile_case2(iseq, ret, node, popped));
9417 CHECK(compile_case3(iseq, ret, node, popped));
9421 CHECK(compile_loop(iseq, ret, node, popped,
type));
9425 CHECK(compile_iter(iseq, ret, node, popped));
9427 case NODE_FOR_MASGN:
9428 CHECK(compile_for_masgn(iseq, ret, node, popped));
9431 CHECK(compile_break(iseq, ret, node, popped));
9434 CHECK(compile_next(iseq, ret, node, popped));
9437 CHECK(compile_redo(iseq, ret, node, popped));
9440 CHECK(compile_retry(iseq, ret, node, popped));
9443 CHECK(COMPILE_(ret,
"NODE_BEGIN", node->nd_body, popped));
9447 CHECK(compile_rescue(iseq, ret, node, popped));
9450 CHECK(compile_resbody(iseq, ret, node, popped));
9453 CHECK(compile_ensure(iseq, ret, node, popped));
9458 LABEL *end_label = NEW_LABEL(line);
9459 CHECK(COMPILE(ret,
"nd_1st", node->nd_1st));
9461 ADD_INSN(ret, node, dup);
9463 if (
type == NODE_AND) {
9464 ADD_INSNL(ret, node, branchunless, end_label);
9467 ADD_INSNL(ret, node, branchif, end_label);
9470 ADD_INSN(ret, node, pop);
9472 CHECK(COMPILE_(ret,
"nd_2nd", node->nd_2nd, popped));
9473 ADD_LABEL(ret, end_label);
9478 compile_massign(iseq, ret, node, popped);
9483 ID id = node->nd_vid;
9484 int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq,
id);
9486 debugs(
"lvar: %s idx: %d\n",
rb_id2name(
id), idx);
9487 CHECK(COMPILE(ret,
"rvalue", node->nd_value));
9490 ADD_INSN(ret, node, dup);
9492 ADD_SETLOCAL(ret, node, idx, get_lvar_level(iseq));
9497 ID id = node->nd_vid;
9498 CHECK(COMPILE(ret,
"dvalue", node->nd_value));
9499 debugi(
"dassn id", rb_id2str(
id) ?
id :
'*');
9502 ADD_INSN(ret, node, dup);
9505 idx = get_dyna_var_idx(iseq,
id, &lv, &ls);
9508 COMPILE_ERROR(ERROR_ARGS
"NODE_DASGN: unknown id (%"PRIsVALUE
")",
9512 ADD_SETLOCAL(ret, node, ls - idx, lv);
9516 CHECK(COMPILE(ret,
"lvalue", node->nd_value));
9519 ADD_INSN(ret, node, dup);
9521 ADD_INSN1(ret, node, setglobal,
ID2SYM(node->nd_entry));
9525 CHECK(COMPILE(ret,
"lvalue", node->nd_value));
9527 ADD_INSN(ret, node, dup);
9529 ADD_INSN2(ret, node, setinstancevariable,
9531 get_ivar_ic_value(iseq,node->nd_vid));
9536 CHECK(COMPILE(ret,
"lvalue", node->nd_value));
9539 ADD_INSN(ret, node, dup);
9542 ADD_INSN1(ret, node, putspecialobject,
9543 INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
9544 ADD_INSN1(ret, node, setconstant,
ID2SYM(node->nd_vid));
9547 compile_cpath(ret, iseq, node->nd_else);
9548 CHECK(COMPILE(ret,
"lvalue", node->nd_value));
9549 ADD_INSN(ret, node, swap);
9552 ADD_INSN1(ret, node, topn,
INT2FIX(1));
9553 ADD_INSN(ret, node, swap);
9556 ADD_INSN1(ret, node, setconstant,
ID2SYM(node->nd_else->nd_mid));
9561 CHECK(COMPILE(ret,
"cvasgn val", node->nd_value));
9563 ADD_INSN(ret, node, dup);
9565 ADD_INSN2(ret, node, setclassvariable,
9567 get_cvar_ic_value(iseq,node->nd_vid));
9571 CHECK(compile_op_asgn1(iseq, ret, node, popped));
9574 CHECK(compile_op_asgn2(iseq, ret, node, popped));
9577 CHECK(compile_op_cdecl(iseq, ret, node, popped));
9579 case NODE_OP_ASGN_AND:
9580 case NODE_OP_ASGN_OR:
9581 CHECK(compile_op_log(iseq, ret, node, popped,
type));
9585 if (compile_call_precheck_freeze(iseq, ret, node, node, popped) == TRUE) {
9591 if (compile_call(iseq, ret, node,
type, node, popped,
false) == COMPILE_NG) {
9597 CHECK(compile_super(iseq, ret, node, popped,
type));
9600 CHECK(compile_array(iseq, ret, node, popped) >= 0);
9605 ADD_INSN1(ret, node, newarray,
INT2FIX(0));
9610 const NODE *n = node;
9612 COMPILE_ERROR(ERROR_ARGS
"NODE_VALUES: must not be popped");
9615 CHECK(COMPILE(ret,
"values item", n->nd_head));
9618 ADD_INSN1(ret, node, newarray,
INT2FIX(node->nd_alen));
9622 CHECK(compile_hash(iseq, ret, node, FALSE, popped) >= 0);
9625 CHECK(compile_return(iseq, ret, node, popped));
9628 CHECK(compile_yield(iseq, ret, node, popped));
9632 compile_lvar(iseq, ret, node, node->nd_vid);
9638 debugi(
"nd_vid", node->nd_vid);
9640 idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
9642 COMPILE_ERROR(ERROR_ARGS
"unknown dvar (%"PRIsVALUE
")",
9643 rb_id2str(node->nd_vid));
9646 ADD_GETLOCAL(ret, node, ls - idx, lv);
9651 ADD_INSN1(ret, node, getglobal,
ID2SYM(node->nd_entry));
9653 ADD_INSN(ret, node, pop);
9658 debugi(
"nd_vid", node->nd_vid);
9660 ADD_INSN2(ret, node, getinstancevariable,
9662 get_ivar_ic_value(iseq,node->nd_vid));
9667 debugi(
"nd_vid", node->nd_vid);
9669 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
9671 VALUE segments = rb_ary_new_from_args(1,
ID2SYM(node->nd_vid));
9672 ADD_INSN1(ret, node, opt_getconstant_path, segments);
9676 ADD_INSN(ret, node, putnil);
9677 ADD_INSN1(ret, node, putobject,
Qtrue);
9678 ADD_INSN1(ret, node, getconstant,
ID2SYM(node->nd_vid));
9682 ADD_INSN(ret, node, pop);
9688 ADD_INSN2(ret, node, getclassvariable,
9690 get_cvar_ic_value(iseq,node->nd_vid));
9696 if (!node->nd_nth) {
9697 ADD_INSN(ret, node, putnil);
9700 ADD_INSN2(ret, node, getspecial,
INT2FIX(1) ,
9705 case NODE_BACK_REF:{
9707 ADD_INSN2(ret, node, getspecial,
INT2FIX(1) ,
9708 INT2FIX(0x01 | (node->nd_nth << 1)));
9715 CHECK(compile_match(iseq, ret, node, popped,
type));
9718 debugp_param(
"lit", node->nd_lit);
9720 ADD_INSN1(ret, node, putobject, node->nd_lit);
9726 debugp_param(
"nd_lit", node->nd_lit);
9728 VALUE lit = node->nd_lit;
9729 if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
9730 lit = rb_fstring(lit);
9731 ADD_INSN1(ret, node, putstring, lit);
9735 if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal ||
RTEST(
ruby_debug)) {
9736 VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq),
INT2FIX(line));
9742 lit = rb_fstring(lit);
9744 ADD_INSN1(ret, node, putobject, lit);
9751 compile_dstr(iseq, ret, node);
9754 ADD_INSN(ret, node, pop);
9759 ADD_CALL_RECEIVER(ret, node);
9760 VALUE str = rb_fstring(node->nd_lit);
9761 ADD_INSN1(ret, node, putobject, str);
9763 ADD_CALL(ret, node, idBackquote,
INT2FIX(1));
9766 ADD_INSN(ret, node, pop);
9771 ADD_CALL_RECEIVER(ret, node);
9772 compile_dstr(iseq, ret, node);
9773 ADD_CALL(ret, node, idBackquote,
INT2FIX(1));
9776 ADD_INSN(ret, node, pop);
9781 CHECK(compile_evstr(iseq, ret, node->nd_body, popped));
9784 compile_dregx(iseq, ret, node);
9787 ADD_INSN(ret, node, pop);
9792 int ic_index = body->ise_size++;
9794 block_iseq = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line);
9796 ADD_INSN2(ret, node, once, block_iseq,
INT2FIX(ic_index));
9800 ADD_INSN(ret, node, pop);
9806 CHECK(COMPILE(ret,
"argscat head", node->nd_head));
9807 ADD_INSN1(ret, node, splatarray,
Qfalse);
9808 ADD_INSN(ret, node, pop);
9809 CHECK(COMPILE(ret,
"argscat body", node->nd_body));
9810 ADD_INSN1(ret, node, splatarray,
Qfalse);
9811 ADD_INSN(ret, node, pop);
9814 CHECK(COMPILE(ret,
"argscat head", node->nd_head));
9815 CHECK(COMPILE(ret,
"argscat body", node->nd_body));
9816 ADD_INSN(ret, node, concatarray);
9820 case NODE_ARGSPUSH:{
9822 CHECK(COMPILE(ret,
"argspush head", node->nd_head));
9823 ADD_INSN1(ret, node, splatarray,
Qfalse);
9824 ADD_INSN(ret, node, pop);
9825 CHECK(COMPILE_(ret,
"argspush body", node->nd_body, popped));
9828 CHECK(COMPILE(ret,
"argspush head", node->nd_head));
9829 CHECK(compile_array_1(iseq, ret, node->nd_body));
9830 ADD_INSN(ret, node, concatarray);
9835 CHECK(COMPILE(ret,
"splat", node->nd_head));
9836 ADD_INSN1(ret, node, splatarray,
Qtrue);
9839 ADD_INSN(ret, node, pop);
9844 ID mid = node->nd_mid;
9845 const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn,
9847 ISEQ_TYPE_METHOD, line);
9849 debugp_param(
"defn/iseq", rb_iseqw_new(method_iseq));
9850 ADD_INSN2(ret, node, definemethod,
ID2SYM(mid), method_iseq);
9854 ADD_INSN1(ret, node, putobject,
ID2SYM(mid));
9860 ID mid = node->nd_mid;
9861 const rb_iseq_t * singleton_method_iseq = NEW_ISEQ(node->nd_defn,
9863 ISEQ_TYPE_METHOD, line);
9865 debugp_param(
"defs/iseq", rb_iseqw_new(singleton_method_iseq));
9866 CHECK(COMPILE(ret,
"defs: recv", node->nd_recv));
9867 ADD_INSN2(ret, node, definesmethod,
ID2SYM(mid), singleton_method_iseq);
9871 ADD_INSN1(ret, node, putobject,
ID2SYM(mid));
9876 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
9877 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_CBASE));
9878 CHECK(COMPILE(ret,
"alias arg1", node->nd_1st));
9879 CHECK(COMPILE(ret,
"alias arg2", node->nd_2nd));
9880 ADD_SEND(ret, node, id_core_set_method_alias,
INT2FIX(3));
9883 ADD_INSN(ret, node, pop);
9888 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
9889 ADD_INSN1(ret, node, putobject,
ID2SYM(node->nd_alias));
9890 ADD_INSN1(ret, node, putobject,
ID2SYM(node->nd_orig));
9891 ADD_SEND(ret, node, id_core_set_variable_alias,
INT2FIX(2));
9894 ADD_INSN(ret, node, pop);
9899 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
9900 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_CBASE));
9901 CHECK(COMPILE(ret,
"undef arg", node->nd_undef));
9902 ADD_SEND(ret, node, id_core_undef_method,
INT2FIX(2));
9905 ADD_INSN(ret, node, pop);
9910 const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(node->nd_body,
9912 ISEQ_TYPE_CLASS, line);
9913 const int flags = VM_DEFINECLASS_TYPE_CLASS |
9914 (node->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) |
9915 compile_cpath(ret, iseq, node->nd_cpath);
9917 CHECK(COMPILE(ret,
"super", node->nd_super));
9918 ADD_INSN3(ret, node, defineclass,
ID2SYM(node->nd_cpath->nd_mid), class_iseq,
INT2FIX(flags));
9922 ADD_INSN(ret, node, pop);
9927 const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(node->nd_body,
9929 ISEQ_TYPE_CLASS, line);
9930 const int flags = VM_DEFINECLASS_TYPE_MODULE |
9931 compile_cpath(ret, iseq, node->nd_cpath);
9933 ADD_INSN (ret, node, putnil);
9934 ADD_INSN3(ret, node, defineclass,
ID2SYM(node->nd_cpath->nd_mid), module_iseq,
INT2FIX(flags));
9938 ADD_INSN(ret, node, pop);
9944 const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_fstring_lit(
"singleton class"),
9945 ISEQ_TYPE_CLASS, line);
9947 CHECK(COMPILE(ret,
"sclass#recv", node->nd_recv));
9948 ADD_INSN (ret, node, putnil);
9949 CONST_ID(singletonclass,
"singletonclass");
9950 ADD_INSN3(ret, node, defineclass,
9951 ID2SYM(singletonclass), singleton_class,
9952 INT2FIX(VM_DEFINECLASS_TYPE_SINGLETON_CLASS));
9956 ADD_INSN(ret, node, pop);
9961 CHECK(compile_colon2(iseq, ret, node, popped));
9964 CHECK(compile_colon3(iseq, ret, node, popped));
9967 CHECK(compile_dots(iseq, ret, node, popped, FALSE));
9970 CHECK(compile_dots(iseq, ret, node, popped, TRUE));
9974 LABEL *lend = NEW_LABEL(line);
9975 LABEL *ltrue = NEW_LABEL(line);
9976 LABEL *lfalse = NEW_LABEL(line);
9977 CHECK(compile_flip_flop(iseq, ret, node,
type == NODE_FLIP2,
9979 ADD_LABEL(ret, ltrue);
9980 ADD_INSN1(ret, node, putobject,
Qtrue);
9981 ADD_INSNL(ret, node, jump, lend);
9982 ADD_LABEL(ret, lfalse);
9983 ADD_INSN1(ret, node, putobject,
Qfalse);
9984 ADD_LABEL(ret, lend);
9989 ADD_INSN(ret, node, putself);
9995 ADD_INSN(ret, node, putnil);
10001 ADD_INSN1(ret, node, putobject,
Qtrue);
10007 ADD_INSN1(ret, node, putobject,
Qfalse);
10012 CHECK(compile_errinfo(iseq, ret, node, popped));
10016 CHECK(compile_defined_expr(iseq, ret, node,
Qtrue));
10019 case NODE_POSTEXE:{
10023 int is_index = body->ise_size++;
10025 rb_iseq_new_with_callback_new_callback(build_postexe_iseq, node->nd_body);
10027 new_child_iseq_with_callback(iseq, ifunc,
10028 rb_fstring(make_name_for_block(iseq)), iseq, ISEQ_TYPE_BLOCK, line);
10030 ADD_INSN2(ret, node, once, once_iseq,
INT2FIX(is_index));
10034 ADD_INSN(ret, node, pop);
10039 CHECK(compile_kw_arg(iseq, ret, node, popped));
10042 compile_dstr(iseq, ret, node);
10044 ADD_INSN(ret, node, intern);
10047 ADD_INSN(ret, node, pop);
10051 case NODE_ATTRASGN:
10052 CHECK(compile_attrasgn(iseq, ret, node, popped));
10056 const rb_iseq_t *block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
10059 ADD_INSN1(ret, node, putspecialobject,
INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
10060 ADD_CALL_WITH_BLOCK(ret, node, idLambda, argc, block);
10064 ADD_INSN(ret, node, pop);
10069 UNKNOWN_NODE(
"iseq_compile_each", node, COMPILE_NG);
10084insn_data_length(
INSN *iobj)
10086 return insn_len(iobj->insn_id);
10090calc_sp_depth(
int depth,
INSN *insn)
10092 return comptime_insn_stack_increase(depth, insn->insn_id, insn->operands);
10096opobj_inspect(
VALUE obj)
10104 obj = rb_ary_dup(obj);
10116insn_data_to_s_detail(
INSN *iobj)
10120 if (iobj->operands) {
10121 const char *types = insn_op_types(iobj->insn_id);
10124 for (j = 0; types[j]; j++) {
10125 char type = types[j];
10149 VALUE v = OPERAND_AT(iobj, j);
10176 if (vm_ci_mid(ci))
rb_str_catf(str,
"%"PRIsVALUE, rb_id2str(vm_ci_mid(ci)));
10185 void *func = (
void *)OPERAND_AT(iobj, j);
10188 if (dladdr(func, &info) && info.dli_sname) {
10203 if (types[j + 1]) {
10214 dump_disasm_list_with_cursor(link, NULL, NULL);
10225 printf(
"-- raw disasm--------\n");
10228 if (curr) printf(curr == link ?
"*" :
" ");
10229 switch (link->type) {
10230 case ISEQ_ELEMENT_INSN:
10232 iobj = (
INSN *)link;
10233 str = insn_data_to_s_detail(iobj);
10234 printf(
" %04d %-65s(%4u)\n", pos,
StringValueCStr(str), iobj->insn_info.line_no);
10235 pos += insn_data_length(iobj);
10238 case ISEQ_ELEMENT_LABEL:
10240 lobj = (
LABEL *)link;
10241 printf(LABEL_FORMAT
" [sp: %d]%s\n", lobj->label_no, lobj->sp,
10242 dest == lobj ?
" <---" :
"");
10245 case ISEQ_ELEMENT_TRACE:
10248 printf(
" trace: %0x\n", trace->event);
10251 case ISEQ_ELEMENT_ADJUST:
10254 printf(
" adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1);
10263 printf(
"---------------------\n");
10268rb_insns_name(
int i)
10270 return insn_name(i);
10274rb_insns_name_array(
void)
10276 VALUE ary = rb_ary_new_capa(VM_INSTRUCTION_SIZE);
10278 for (i = 0; i < VM_INSTRUCTION_SIZE; i++) {
10279 rb_ary_push(ary, rb_fstring_cstr(insn_name(i)));
10289 obj = rb_to_symbol_type(obj);
10291 if (st_lookup(labels_table, obj, &tmp) == 0) {
10292 label = NEW_LABEL(0);
10293 st_insert(labels_table, obj, (st_data_t)label);
10296 label = (
LABEL *)tmp;
10303get_exception_sym2type(
VALUE sym)
10305 static VALUE symRescue, symEnsure, symRetry;
10306 static VALUE symBreak, symRedo, symNext;
10308 if (symRescue == 0) {
10309 symRescue =
ID2SYM(rb_intern_const(
"rescue"));
10310 symEnsure =
ID2SYM(rb_intern_const(
"ensure"));
10311 symRetry =
ID2SYM(rb_intern_const(
"retry"));
10312 symBreak =
ID2SYM(rb_intern_const(
"break"));
10313 symRedo =
ID2SYM(rb_intern_const(
"redo"));
10314 symNext =
ID2SYM(rb_intern_const(
"next"));
10317 if (sym == symRescue)
return CATCH_TYPE_RESCUE;
10318 if (sym == symEnsure)
return CATCH_TYPE_ENSURE;
10319 if (sym == symRetry)
return CATCH_TYPE_RETRY;
10320 if (sym == symBreak)
return CATCH_TYPE_BREAK;
10321 if (sym == symRedo)
return CATCH_TYPE_REDO;
10322 if (sym == symNext)
return CATCH_TYPE_NEXT;
10336 LABEL *lstart, *lend, *lcont;
10351 lstart = register_label(iseq, labels_table,
RARRAY_AREF(v, 2));
10352 lend = register_label(iseq, labels_table,
RARRAY_AREF(v, 3));
10353 lcont = register_label(iseq, labels_table,
RARRAY_AREF(v, 4));
10357 if (
type == CATCH_TYPE_RESCUE ||
10358 type == CATCH_TYPE_BREAK ||
10359 type == CATCH_TYPE_NEXT) {
10365 ADD_CATCH_ENTRY(
type, lstart, lend, eiseq, lcont);
10373insn_make_insn_table(
void)
10377 table = st_init_numtable_with_size(VM_INSTRUCTION_SIZE);
10379 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
10380 st_insert(table,
ID2SYM(rb_intern_const(insn_name(i))), i);
10392 if (RB_TYPE_P(op,
T_ARRAY)) {
10393 iseqw = rb_iseq_load(op, (
VALUE)iseq,
Qnil);
10395 else if (
CLASS_OF(op) == rb_cISeq) {
10402 loaded_iseq = rb_iseqw_to_iseq(iseqw);
10403 return loaded_iseq;
10411 unsigned int flag = 0;
10415 VALUE vmid = rb_hash_aref(op,
ID2SYM(rb_intern_const(
"mid")));
10416 VALUE vflag = rb_hash_aref(op,
ID2SYM(rb_intern_const(
"flag")));
10417 VALUE vorig_argc = rb_hash_aref(op,
ID2SYM(rb_intern_const(
"orig_argc")));
10418 VALUE vkw_arg = rb_hash_aref(op,
ID2SYM(rb_intern_const(
"kw_arg")));
10422 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
10424 if (!
NIL_P(vkw_arg)) {
10426 int len = RARRAY_LENINT(vkw_arg);
10427 size_t n = rb_callinfo_kwarg_bytes(len);
10430 kw_arg->keyword_len = len;
10431 for (i = 0; i < len; i++) {
10434 kw_arg->keywords[i] = kw;
10439 const struct rb_callinfo *ci = new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0);
10445event_name_to_flag(
VALUE sym)
10447#define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern_const(#ev))) return ev;
10467 int line_no = 0, node_id = -1, insn_idx = 0;
10468 int ret = COMPILE_OK;
10473 static struct st_table *insn_table;
10475 if (insn_table == 0) {
10476 insn_table = insn_make_insn_table();
10479 for (i=0; i<len; i++) {
10485 ADD_TRACE(anchor, event);
10488 LABEL *label = register_label(iseq, labels_table, obj);
10489 ADD_LABEL(anchor, label);
10495 else if (RB_TYPE_P(obj,
T_ARRAY)) {
10497 int argc = RARRAY_LENINT(obj) - 1;
10502 node_id =
NUM2INT(rb_ary_entry(node_ids, insn_idx++));
10506 if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
10508 COMPILE_ERROR(iseq, line_no,
10509 "unknown instruction: %+"PRIsVALUE, insn);
10514 if (argc != insn_len((
VALUE)insn_id)-1) {
10515 COMPILE_ERROR(iseq, line_no,
10516 "operand size mismatch");
10522 argv = compile_data_calloc2(iseq,
sizeof(
VALUE), argc);
10525 NODE dummy_line_node = generate_dummy_line_node(line_no, node_id);
10528 (
enum ruby_vminsn_type)insn_id, argc, argv));
10530 for (j=0; j<argc; j++) {
10531 VALUE op = rb_ary_entry(obj, j+1);
10532 switch (insn_op_type((
VALUE)insn_id, j)) {
10534 LABEL *label = register_label(iseq, labels_table, op);
10535 argv[j] = (
VALUE)label;
10550 VALUE v = (
VALUE)iseq_build_load_iseq(iseq, op);
10561 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->ise_size) {
10562 ISEQ_BODY(iseq)->ise_size =
NUM2INT(op) + 1;
10567 VALUE segments = rb_ary_new();
10568 op = rb_to_array_type(op);
10572 sym = rb_to_symbol_type(sym);
10573 rb_ary_push(segments, sym);
10577 argv[j] = segments;
10579 ISEQ_BODY(iseq)->ic_size++;
10584 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->ivc_size) {
10585 ISEQ_BODY(iseq)->ivc_size =
NUM2INT(op) + 1;
10590 if (
NUM2UINT(op) >= ISEQ_BODY(iseq)->icvarc_size) {
10591 ISEQ_BODY(iseq)->icvarc_size =
NUM2INT(op) + 1;
10595 argv[j] = iseq_build_callinfo_from_hash(iseq, op);
10598 argv[j] = rb_to_symbol_type(op);
10605 RHASH_TBL_RAW(map)->type = &cdhash_type;
10606 op = rb_to_array_type(op);
10611 register_label(iseq, labels_table, sym);
10612 rb_hash_aset(map, key, (
VALUE)label | 1);
10621#if SIZEOF_VALUE <= SIZEOF_LONG
10626 argv[j] = (
VALUE)funcptr;
10635 NODE dummy_line_node = generate_dummy_line_node(line_no, node_id);
10638 (
enum ruby_vminsn_type)insn_id, argc, NULL));
10646 validate_labels(iseq, labels_table);
10647 if (!ret)
return ret;
10648 return iseq_setup(iseq, anchor);
10651#define CHECK_ARRAY(v) rb_to_array_type(v)
10652#define CHECK_SYMBOL(v) rb_to_symbol_type(v)
10657 VALUE val = rb_hash_aref(param, sym);
10662 else if (!
NIL_P(val)) {
10669static const struct rb_iseq_param_keyword *
10673 int len = RARRAY_LENINT(keywords);
10675 VALUE key, sym, default_val;
10678 struct rb_iseq_param_keyword *keyword =
ZALLOC(
struct rb_iseq_param_keyword);
10680 ISEQ_BODY(iseq)->param.flags.has_kw = TRUE;
10682 keyword->num = len;
10683#define SYM(s) ID2SYM(rb_intern_const(#s))
10684 (void)int_param(&keyword->bits_start, params, SYM(kwbits));
10685 i = keyword->bits_start - keyword->num;
10686 ids = (
ID *)&ISEQ_BODY(iseq)->local_table[i];
10690 for (i = 0; i < len; i++) {
10694 goto default_values;
10697 keyword->required_num++;
10701 default_len = len - i;
10702 if (default_len == 0) {
10703 keyword->table = ids;
10706 else if (default_len < 0) {
10712 for (j = 0; i < len; i++, j++) {
10729 dvs[j] = default_val;
10732 keyword->table = ids;
10733 keyword->default_values = dvs;
10742 size_t size =
sizeof(
INSN);
10743 unsigned int pos = 0;
10746#ifdef STRICT_ALIGNMENT
10747 size_t padding = calc_padding((
void *)&storage->buff[pos], size);
10749 const size_t padding = 0;
10751 size_t offset = pos + size + padding;
10752 if (offset > storage->size || offset > storage->pos) {
10754 storage = storage->next;
10757#ifdef STRICT_ALIGNMENT
10758 pos += (int)padding;
10761 iobj = (
INSN *)&storage->buff[pos];
10763 if (iobj->operands) {
10765 const char *types = insn_op_types(iobj->insn_id);
10767 for (j = 0; types[j]; j++) {
10768 char type = types[j];
10776 VALUE op = OPERAND_AT(iobj, j);
10797#define SYM(s) ID2SYM(rb_intern_const(#s))
10799 unsigned int arg_size, local_size, stack_max;
10801 struct st_table *labels_table = st_init_numtable();
10803 VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt));
10804 VALUE keywords = rb_hash_aref(params, SYM(keyword));
10805 VALUE sym_arg_rest =
ID2SYM(rb_intern_const(
"#arg_rest"));
10806 DECL_ANCHOR(anchor);
10807 INIT_ANCHOR(anchor);
10809 len = RARRAY_LENINT(locals);
10810 ISEQ_BODY(iseq)->local_table_size = len;
10811 ISEQ_BODY(iseq)->local_table = tbl = len > 0 ? (
ID *)
ALLOC_N(
ID, ISEQ_BODY(iseq)->local_table_size) : NULL;
10813 for (i = 0; i < len; i++) {
10816 if (sym_arg_rest == lv) {
10824#define INT_PARAM(F) int_param(&ISEQ_BODY(iseq)->param.F, params, SYM(F))
10825 if (INT_PARAM(lead_num)) {
10826 ISEQ_BODY(iseq)->param.flags.has_lead = TRUE;
10828 if (INT_PARAM(post_num)) ISEQ_BODY(iseq)->param.flags.has_post = TRUE;
10829 if (INT_PARAM(post_start)) ISEQ_BODY(iseq)->param.flags.has_post = TRUE;
10830 if (INT_PARAM(rest_start)) ISEQ_BODY(iseq)->param.flags.has_rest = TRUE;
10831 if (INT_PARAM(block_start)) ISEQ_BODY(iseq)->param.flags.has_block = TRUE;
10834#define INT_PARAM(F) F = (int_param(&x, misc, SYM(F)) ? (unsigned int)x : 0)
10836 INT_PARAM(arg_size);
10837 INT_PARAM(local_size);
10838 INT_PARAM(stack_max);
10843#ifdef USE_ISEQ_NODE_ID
10844 node_ids = rb_hash_aref(misc,
ID2SYM(rb_intern(
"node_ids")));
10845 if (!RB_TYPE_P(node_ids,
T_ARRAY)) {
10850 if (RB_TYPE_P(arg_opt_labels,
T_ARRAY)) {
10851 len = RARRAY_LENINT(arg_opt_labels);
10852 ISEQ_BODY(iseq)->param.flags.has_opt = !!(len - 1 >= 0);
10854 if (ISEQ_BODY(iseq)->param.flags.has_opt) {
10857 for (i = 0; i < len; i++) {
10859 LABEL *label = register_label(iseq, labels_table, ent);
10860 opt_table[i] = (
VALUE)label;
10863 ISEQ_BODY(iseq)->param.opt_num = len - 1;
10864 ISEQ_BODY(iseq)->param.opt_table = opt_table;
10867 else if (!
NIL_P(arg_opt_labels)) {
10872 if (RB_TYPE_P(keywords,
T_ARRAY)) {
10873 ISEQ_BODY(iseq)->param.keyword = iseq_build_kw(iseq, params, keywords);
10875 else if (!
NIL_P(keywords)) {
10880 if (
Qtrue == rb_hash_aref(params, SYM(ambiguous_param0))) {
10881 ISEQ_BODY(iseq)->param.flags.ambiguous_param0 = TRUE;
10884 if (int_param(&i, params, SYM(kwrest))) {
10885 struct rb_iseq_param_keyword *keyword = (
struct rb_iseq_param_keyword *)ISEQ_BODY(iseq)->param.keyword;
10886 if (keyword == NULL) {
10887 ISEQ_BODY(iseq)->param.keyword = keyword =
ZALLOC(
struct rb_iseq_param_keyword);
10889 keyword->rest_start = i;
10890 ISEQ_BODY(iseq)->param.flags.has_kwrest = TRUE;
10893 iseq_calc_param_size(iseq);
10896 iseq_build_from_ary_exception(iseq, labels_table, exception);
10899 iseq_build_from_ary_body(iseq, anchor, body, node_ids, labels_wrapper);
10901 ISEQ_BODY(iseq)->param.size = arg_size;
10902 ISEQ_BODY(iseq)->local_table_size = local_size;
10903 ISEQ_BODY(iseq)->stack_max = stack_max;
10913 while (body->type == ISEQ_TYPE_BLOCK ||
10914 body->type == ISEQ_TYPE_RESCUE ||
10915 body->type == ISEQ_TYPE_ENSURE ||
10916 body->type == ISEQ_TYPE_EVAL ||
10917 body->type == ISEQ_TYPE_MAIN
10921 for (i = 0; i < body->local_table_size; i++) {
10922 if (body->local_table[i] ==
id) {
10926 iseq = body->parent_iseq;
10927 body = ISEQ_BODY(iseq);
10940 for (i=0; i<body->local_table_size; i++) {
10941 if (body->local_table[i] ==
id) {
10951#ifndef IBF_ISEQ_DEBUG
10952#define IBF_ISEQ_DEBUG 0
10955#ifndef IBF_ISEQ_ENABLE_LOCAL_BUFFER
10956#define IBF_ISEQ_ENABLE_LOCAL_BUFFER 0
10959typedef unsigned int ibf_offset_t;
10960#define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
10962#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
10964#define IBF_DEVEL_VERSION 4
10965#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
10967#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
10972 unsigned int major_version;
10973 unsigned int minor_version;
10975 unsigned int extra_size;
10977 unsigned int iseq_list_size;
10978 unsigned int global_object_list_size;
10979 ibf_offset_t iseq_list_offset;
10980 ibf_offset_t global_object_list_offset;
10999 unsigned int obj_list_size;
11000 ibf_offset_t obj_list_offset;
11019pinned_list_mark(
void *ptr)
11023 for (i = 0; i < list->size; i++) {
11024 if (list->buffer[i]) {
11025 rb_gc_mark(list->buffer[i]);
11031pinned_list_free(
void *ptr)
11034 xfree(list->buffer);
11039pinned_list_memsize(
const void *ptr)
11047 {pinned_list_mark, pinned_list_free, pinned_list_memsize,},
11048 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
11052pinned_list_fetch(
VALUE list,
long offset)
11058 if (offset >= ptr->size) {
11062 return ptr->buffer[offset];
11066pinned_list_store(
VALUE list,
long offset,
VALUE object)
11072 if (offset >= ptr->size) {
11080pinned_list_new(
long size)
11093ibf_dump_pos(
struct ibf_dump *dump)
11095 long pos = RSTRING_LEN(dump->current_buffer->str);
11096#if SIZEOF_LONG > SIZEOF_INT
11097 if (pos >= UINT_MAX) {
11101 return (
unsigned int)pos;
11105ibf_dump_align(
struct ibf_dump *dump,
size_t align)
11107 ibf_offset_t pos = ibf_dump_pos(dump);
11109 static const char padding[
sizeof(
VALUE)];
11110 size_t size = align - ((size_t)pos % align);
11111#if SIZEOF_LONG > SIZEOF_INT
11112 if (pos + size >= UINT_MAX) {
11116 for (; size >
sizeof(padding); size -=
sizeof(padding)) {
11117 rb_str_cat(dump->current_buffer->str, padding,
sizeof(padding));
11119 rb_str_cat(dump->current_buffer->str, padding, size);
11124ibf_dump_write(
struct ibf_dump *dump,
const void *buff,
unsigned long size)
11126 ibf_offset_t pos = ibf_dump_pos(dump);
11127 rb_str_cat(dump->current_buffer->str, (
const char *)buff, size);
11133ibf_dump_write_byte(
struct ibf_dump *dump,
unsigned char byte)
11135 return ibf_dump_write(dump, &
byte,
sizeof(
unsigned char));
11139ibf_dump_overwrite(
struct ibf_dump *dump,
void *buff,
unsigned int size,
long offset)
11141 VALUE str = dump->current_buffer->str;
11142 char *ptr = RSTRING_PTR(str);
11143 if ((
unsigned long)(size + offset) > (
unsigned long)RSTRING_LEN(str))
11144 rb_bug(
"ibf_dump_overwrite: overflow");
11145 memcpy(ptr + offset, buff, size);
11149ibf_load_ptr(
const struct ibf_load *load, ibf_offset_t *offset,
int size)
11151 ibf_offset_t beg = *offset;
11153 return load->current_buffer->buff + beg;
11157ibf_load_alloc(
const struct ibf_load *load, ibf_offset_t offset,
size_t x,
size_t y)
11159 void *buff = ruby_xmalloc2(x, y);
11160 size_t size = x * y;
11161 memcpy(buff, load->current_buffer->buff + offset, size);
11165#define IBF_W_ALIGN(type) (RUBY_ALIGNOF(type) > 1 ? ibf_dump_align(dump, RUBY_ALIGNOF(type)) : (void)0)
11167#define IBF_W(b, type, n) (IBF_W_ALIGN(type), (type *)(VALUE)IBF_WP(b, type, n))
11168#define IBF_WV(variable) ibf_dump_write(dump, &(variable), sizeof(variable))
11169#define IBF_WP(b, type, n) ibf_dump_write(dump, (b), sizeof(type) * (n))
11170#define IBF_R(val, type, n) (type *)ibf_load_alloc(load, IBF_OFFSET(val), sizeof(type), (n))
11171#define IBF_ZERO(variable) memset(&(variable), 0, sizeof(variable))
11174ibf_table_lookup(
struct st_table *table, st_data_t key)
11178 if (st_lookup(table, key, &val)) {
11187ibf_table_find_or_insert(
struct st_table *table, st_data_t key)
11189 int index = ibf_table_lookup(table, key);
11192 index = (int)table->num_entries;
11193 st_insert(table, key, (st_data_t)index);
11201static void ibf_dump_object_list(
struct ibf_dump *dump, ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size);
11207ibf_dump_object_table_new(
void)
11209 st_table *obj_table = st_init_numtable();
11210 st_insert(obj_table, (st_data_t)
Qnil, (st_data_t)0);
11218 return ibf_table_find_or_insert(dump->current_buffer->obj_table, (st_data_t)obj);
11227 return ibf_dump_object(dump,
rb_id2sym(
id));
11231ibf_load_id(
const struct ibf_load *load,
const ID id_index)
11233 if (id_index == 0) {
11236 VALUE sym = ibf_load_object(load, id_index);
11242static ibf_offset_t ibf_dump_iseq_each(
struct ibf_dump *dump,
const rb_iseq_t *iseq);
11247 if (iseq == NULL) {
11251 return ibf_table_find_or_insert(dump->iseq_table, (st_data_t)iseq);
11255static unsigned char
11256ibf_load_byte(
const struct ibf_load *load, ibf_offset_t *offset)
11259 return (
unsigned char)load->current_buffer->buff[(*offset)++];
11275 if (
sizeof(
VALUE) > 8 || CHAR_BIT != 8) {
11276 ibf_dump_write(dump, &x,
sizeof(
VALUE));
11280 enum { max_byte_length =
sizeof(
VALUE) + 1 };
11282 unsigned char bytes[max_byte_length];
11285 for (n = 0; n <
sizeof(
VALUE) && (x >> (7 - n)); n++, x >>= 8) {
11286 bytes[max_byte_length - 1 - n] = (
unsigned char)x;
11292 bytes[max_byte_length - 1 - n] = (
unsigned char)x;
11295 ibf_dump_write(dump, bytes + max_byte_length - n, n);
11299ibf_load_small_value(
const struct ibf_load *load, ibf_offset_t *offset)
11301 if (
sizeof(
VALUE) > 8 || CHAR_BIT != 8) {
11302 union {
char s[
sizeof(
VALUE)];
VALUE v; } x;
11304 memcpy(x.s, load->current_buffer->buff + *offset,
sizeof(
VALUE));
11305 *offset +=
sizeof(
VALUE);
11310 enum { max_byte_length =
sizeof(
VALUE) + 1 };
11312 const unsigned char *buffer = (
const unsigned char *)load->current_buffer->buff;
11313 const unsigned char c = buffer[*offset];
11317 c == 0 ? 9 : ntz_int32(c) + 1;
11320 if (*offset + n > load->current_buffer->size) {
11325 for (i = 1; i < n; i++) {
11327 x |= (
VALUE)buffer[*offset + i];
11341 ibf_dump_write_small_value(dump, (
VALUE)bf->index);
11343 size_t len = strlen(bf->name);
11344 ibf_dump_write_small_value(dump, (
VALUE)len);
11345 ibf_dump_write(dump, bf->name, len);
11349ibf_load_builtin(
const struct ibf_load *load, ibf_offset_t *offset)
11351 int i = (int)ibf_load_small_value(load, offset);
11352 int len = (int)ibf_load_small_value(load, offset);
11353 const char *name = (
char *)ibf_load_ptr(load, offset, len);
11356 fprintf(stderr,
"%.*s!!\n", len, name);
11361 if (strncmp(table[i].name, name, len) != 0) {
11362 rb_raise(
rb_eArgError,
"builtin function index (%d) mismatch (expect %s but %s)", i, name, table[i].name);
11373 const int iseq_size = body->iseq_size;
11375 const VALUE *orig_code = rb_iseq_original_iseq(iseq);
11377 ibf_offset_t offset = ibf_dump_pos(dump);
11379 for (code_index=0; code_index<iseq_size;) {
11380 const VALUE insn = orig_code[code_index++];
11381 const char *types = insn_op_types(insn);
11386 ibf_dump_write_small_value(dump, insn);
11389 for (op_index=0; types[op_index]; op_index++, code_index++) {
11390 VALUE op = orig_code[code_index];
11393 switch (types[op_index]) {
11396 wv = ibf_dump_object(dump, op);
11404 VALUE arr = idlist_to_array(ic->segments);
11405 wv = ibf_dump_object(dump, arr);
11413 wv = is - ISEQ_IS_ENTRY_START(body, types[op_index]);
11421 wv = ibf_dump_id(dump, (
ID)op);
11433 ibf_dump_write_small_value(dump, wv);
11436 assert(insn_len(insn) == op_index+1);
11443ibf_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)
11446 unsigned int code_index;
11447 ibf_offset_t reading_pos = bytecode_offset;
11451 struct rb_call_data *cd_entries = load_body->call_data;
11454 iseq_bits_t * mark_offset_bits;
11456 iseq_bits_t tmp[1] = {0};
11458 if (ISEQ_MBITS_BUFLEN(iseq_size) == 1) {
11459 mark_offset_bits = tmp;
11462 mark_offset_bits =
ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(iseq_size));
11464 bool needs_bitmap =
false;
11466 for (code_index=0; code_index<iseq_size;) {
11468 const VALUE insn = code[code_index] = ibf_load_small_value(load, &reading_pos);
11469 const char *types = insn_op_types(insn);
11475 for (op_index=0; types[op_index]; op_index++, code_index++) {
11476 const char operand_type = types[op_index];
11477 switch (operand_type) {
11480 VALUE op = ibf_load_small_value(load, &reading_pos);
11481 VALUE v = ibf_load_object(load, op);
11482 code[code_index] = v;
11485 ISEQ_MBITS_SET(mark_offset_bits, code_index);
11486 needs_bitmap =
true;
11492 VALUE op = ibf_load_small_value(load, &reading_pos);
11493 VALUE v = ibf_load_object(load, op);
11494 v = rb_hash_dup(v);
11495 RHASH_TBL_RAW(v)->type = &cdhash_type;
11497 freeze_hide_obj(v);
11502 pinned_list_store(load->current_buffer->obj_list, (
long)op, v);
11504 code[code_index] = v;
11505 ISEQ_MBITS_SET(mark_offset_bits, code_index);
11507 needs_bitmap =
true;
11512 VALUE op = (
VALUE)ibf_load_small_value(load, &reading_pos);
11514 code[code_index] = v;
11517 ISEQ_MBITS_SET(mark_offset_bits, code_index);
11518 needs_bitmap =
true;
11524 VALUE op = ibf_load_small_value(load, &reading_pos);
11525 VALUE arr = ibf_load_object(load, op);
11527 IC ic = &ISEQ_IS_IC_ENTRY(load_body, ic_index++);
11528 ic->segments = array_to_idlist(arr);
11530 code[code_index] = (
VALUE)ic;
11537 unsigned int op = (
unsigned int)ibf_load_small_value(load, &reading_pos);
11539 ISE ic = ISEQ_IS_ENTRY_START(load_body, operand_type) + op;
11540 code[code_index] = (
VALUE)ic;
11542 if (operand_type == TS_IVC) {
11545 if (insn == BIN(setinstancevariable)) {
11546 ID iv_name = (
ID)code[code_index - 1];
11547 cache->iv_set_name = iv_name;
11550 cache->iv_set_name = 0;
11553 vm_ic_attr_index_initialize(cache, INVALID_SHAPE_ID);
11560 code[code_index] = (
VALUE)cd_entries++;
11565 VALUE op = ibf_load_small_value(load, &reading_pos);
11566 code[code_index] = ibf_load_id(load, (
ID)(
VALUE)op);
11573 code[code_index] = (
VALUE)ibf_load_builtin(load, &reading_pos);
11576 code[code_index] = ibf_load_small_value(load, &reading_pos);
11580 if (insn_len(insn) != op_index+1) {
11585 load_body->iseq_encoded = code;
11586 load_body->iseq_size = code_index;
11588 if (ISEQ_MBITS_BUFLEN(load_body->iseq_size) == 1) {
11589 load_body->mark_bits.single = mark_offset_bits[0];
11592 if (needs_bitmap) {
11593 load_body->mark_bits.list = mark_offset_bits;
11596 load_body->mark_bits.list = 0;
11597 ruby_xfree(mark_offset_bits);
11601 assert(code_index == iseq_size);
11602 assert(reading_pos == bytecode_offset + bytecode_size);
11609 int opt_num = ISEQ_BODY(iseq)->param.opt_num;
11612 IBF_W_ALIGN(
VALUE);
11613 return ibf_dump_write(dump, ISEQ_BODY(iseq)->param.opt_table,
sizeof(
VALUE) * (opt_num + 1));
11616 return ibf_dump_pos(dump);
11621ibf_load_param_opt_table(
const struct ibf_load *load, ibf_offset_t opt_table_offset,
int opt_num)
11625 MEMCPY(table, load->current_buffer->buff + opt_table_offset,
VALUE, opt_num+1);
11636 const struct rb_iseq_param_keyword *kw = ISEQ_BODY(iseq)->param.keyword;
11639 struct rb_iseq_param_keyword dump_kw = *kw;
11640 int dv_num = kw->num - kw->required_num;
11645 for (i=0; i<kw->num; i++) ids[i] = (
ID)ibf_dump_id(dump, kw->table[i]);
11646 for (i=0; i<dv_num; i++) dvs[i] = (
VALUE)ibf_dump_object(dump, kw->default_values[i]);
11648 dump_kw.table = IBF_W(ids,
ID, kw->num);
11649 dump_kw.default_values = IBF_W(dvs,
VALUE, dv_num);
11650 IBF_W_ALIGN(
struct rb_iseq_param_keyword);
11651 return ibf_dump_write(dump, &dump_kw,
sizeof(
struct rb_iseq_param_keyword) * 1);
11658static const struct rb_iseq_param_keyword *
11659ibf_load_param_keyword(
const struct ibf_load *load, ibf_offset_t param_keyword_offset)
11661 if (param_keyword_offset) {
11662 struct rb_iseq_param_keyword *kw = IBF_R(param_keyword_offset,
struct rb_iseq_param_keyword, 1);
11663 ID *ids = IBF_R(kw->table,
ID, kw->num);
11664 int dv_num = kw->num - kw->required_num;
11665 VALUE *dvs = IBF_R(kw->default_values,
VALUE, dv_num);
11668 for (i=0; i<kw->num; i++) {
11669 ids[i] = ibf_load_id(load, ids[i]);
11671 for (i=0; i<dv_num; i++) {
11672 dvs[i] = ibf_load_object(load, dvs[i]);
11676 kw->default_values = dvs;
11687 ibf_offset_t offset = ibf_dump_pos(dump);
11691 for (i = 0; i < ISEQ_BODY(iseq)->insns_info.size; i++) {
11692 ibf_dump_write_small_value(dump, entries[i].line_no);
11693#ifdef USE_ISEQ_NODE_ID
11694 ibf_dump_write_small_value(dump, entries[i].node_id);
11696 ibf_dump_write_small_value(dump, entries[i].events);
11703ibf_load_insns_info_body(
const struct ibf_load *load, ibf_offset_t body_offset,
unsigned int size)
11705 ibf_offset_t reading_pos = body_offset;
11709 for (i = 0; i < size; i++) {
11710 entries[i].line_no = (int)ibf_load_small_value(load, &reading_pos);
11711#ifdef USE_ISEQ_NODE_ID
11712 entries[i].node_id = (int)ibf_load_small_value(load, &reading_pos);
11714 entries[i].events = (
rb_event_flag_t)ibf_load_small_value(load, &reading_pos);
11721ibf_dump_insns_info_positions(
struct ibf_dump *dump,
const unsigned int *positions,
unsigned int size)
11723 ibf_offset_t offset = ibf_dump_pos(dump);
11725 unsigned int last = 0;
11727 for (i = 0; i < size; i++) {
11728 ibf_dump_write_small_value(dump, positions[i] - last);
11729 last = positions[i];
11735static unsigned int *
11736ibf_load_insns_info_positions(
const struct ibf_load *load, ibf_offset_t positions_offset,
unsigned int size)
11738 ibf_offset_t reading_pos = positions_offset;
11739 unsigned int *positions =
ALLOC_N(
unsigned int, size);
11741 unsigned int last = 0;
11743 for (i = 0; i < size; i++) {
11744 positions[i] = last + (
unsigned int)ibf_load_small_value(load, &reading_pos);
11745 last = positions[i];
11755 const int size = body->local_table_size;
11759 for (i=0; i<size; i++) {
11760 table[i] = ibf_dump_id(dump, body->local_table[i]);
11764 return ibf_dump_write(dump, table,
sizeof(
ID) * size);
11768ibf_load_local_table(
const struct ibf_load *load, ibf_offset_t local_table_offset,
int size)
11771 ID *table = IBF_R(local_table_offset,
ID, size);
11774 for (i=0; i<size; i++) {
11775 table[i] = ibf_load_id(load, table[i]);
11790 int *iseq_indices =
ALLOCA_N(
int, table->size);
11793 for (i=0; i<table->size; i++) {
11794 iseq_indices[i] = ibf_dump_iseq(dump, table->entries[i].iseq);
11797 const ibf_offset_t offset = ibf_dump_pos(dump);
11799 for (i=0; i<table->size; i++) {
11800 ibf_dump_write_small_value(dump, iseq_indices[i]);
11801 ibf_dump_write_small_value(dump, table->entries[i].type);
11802 ibf_dump_write_small_value(dump, table->entries[i].start);
11803 ibf_dump_write_small_value(dump, table->entries[i].end);
11804 ibf_dump_write_small_value(dump, table->entries[i].cont);
11805 ibf_dump_write_small_value(dump, table->entries[i].sp);
11810 return ibf_dump_pos(dump);
11815ibf_load_catch_table(
const struct ibf_load *load, ibf_offset_t catch_table_offset,
unsigned int size)
11818 struct iseq_catch_table *table = ruby_xmalloc(iseq_catch_table_bytes(size));
11819 table->size = size;
11821 ibf_offset_t reading_pos = catch_table_offset;
11824 for (i=0; i<table->size; i++) {
11825 int iseq_index = (int)ibf_load_small_value(load, &reading_pos);
11826 table->entries[i].type = (
enum rb_catch_type)ibf_load_small_value(load, &reading_pos);
11827 table->entries[i].start = (
unsigned int)ibf_load_small_value(load, &reading_pos);
11828 table->entries[i].end = (
unsigned int)ibf_load_small_value(load, &reading_pos);
11829 table->entries[i].cont = (
unsigned int)ibf_load_small_value(load, &reading_pos);
11830 table->entries[i].sp = (
unsigned int)ibf_load_small_value(load, &reading_pos);
11832 table->entries[i].iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)iseq_index);
11845 const unsigned int ci_size = body->ci_size;
11848 ibf_offset_t offset = ibf_dump_pos(dump);
11852 for (i = 0; i < ci_size; i++) {
11855 ibf_dump_write_small_value(dump, ibf_dump_id(dump, vm_ci_mid(ci)));
11856 ibf_dump_write_small_value(dump, vm_ci_flag(ci));
11857 ibf_dump_write_small_value(dump, vm_ci_argc(ci));
11861 int len = kwarg->keyword_len;
11862 ibf_dump_write_small_value(dump, len);
11863 for (
int j=0; j<len; j++) {
11864 VALUE keyword = ibf_dump_object(dump, kwarg->keywords[j]);
11865 ibf_dump_write_small_value(dump, keyword);
11869 ibf_dump_write_small_value(dump, 0);
11874 ibf_dump_write_small_value(dump, (
VALUE)-1);
11881static enum rb_id_table_iterator_result
11882dump_outer_variable(
ID id,
VALUE val,
void *dump)
11884 ibf_dump_write_small_value(dump, ibf_dump_id(dump,
id));
11885 ibf_dump_write_small_value(dump, val);
11887 return ID_TABLE_CONTINUE;
11893 struct rb_id_table * ovs = ISEQ_BODY(iseq)->outer_variables;
11895 ibf_offset_t offset = ibf_dump_pos(dump);
11898 ibf_dump_write_small_value(dump, (
VALUE)rb_id_table_size(ovs));
11899 rb_id_table_foreach(ovs, dump_outer_variable, (
void *)dump);
11902 ibf_dump_write_small_value(dump, (
VALUE)0);
11910ibf_load_ci_entries(
const struct ibf_load *load,
11911 ibf_offset_t ci_entries_offset,
11912 unsigned int ci_size,
11915 ibf_offset_t reading_pos = ci_entries_offset;
11922 for (i = 0; i < ci_size; i++) {
11923 VALUE mid_index = ibf_load_small_value(load, &reading_pos);
11924 if (mid_index != (
VALUE)-1) {
11925 ID mid = ibf_load_id(load, mid_index);
11926 unsigned int flag = (
unsigned int)ibf_load_small_value(load, &reading_pos);
11927 unsigned int argc = (
unsigned int)ibf_load_small_value(load, &reading_pos);
11930 int kwlen = (int)ibf_load_small_value(load, &reading_pos);
11933 kwarg->keyword_len = kwlen;
11934 for (
int j=0; j<kwlen; j++) {
11935 VALUE keyword = ibf_load_small_value(load, &reading_pos);
11936 kwarg->keywords[j] = ibf_load_object(load, keyword);
11940 cds[i].ci = vm_ci_new(mid, flag, argc, kwarg);
11942 cds[i].cc = vm_cc_empty();
11953ibf_load_outer_variables(
const struct ibf_load * load, ibf_offset_t outer_variables_offset)
11955 ibf_offset_t reading_pos = outer_variables_offset;
11959 size_t table_size = (size_t)ibf_load_small_value(load, &reading_pos);
11961 if (table_size > 0) {
11962 tbl = rb_id_table_create(table_size);
11965 for (
size_t i = 0; i < table_size; i++) {
11966 ID key = ibf_load_id(load, (
ID)ibf_load_small_value(load, &reading_pos));
11967 VALUE value = ibf_load_small_value(load, &reading_pos);
11968 if (!key) key = rb_make_temporary_id(i);
11969 rb_id_table_insert(tbl, key, value);
11978 assert(dump->current_buffer == &dump->global_buffer);
11980 unsigned int *positions;
11984 const VALUE location_pathobj_index = ibf_dump_object(dump, body->location.pathobj);
11985 const VALUE location_base_label_index = ibf_dump_object(dump, body->location.base_label);
11986 const VALUE location_label_index = ibf_dump_object(dump, body->location.label);
11988#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
11989 ibf_offset_t iseq_start = ibf_dump_pos(dump);
11994 buffer.obj_table = ibf_dump_object_table_new();
11995 dump->current_buffer = &buffer;
11998 const ibf_offset_t bytecode_offset = ibf_dump_code(dump, iseq);
11999 const ibf_offset_t bytecode_size = ibf_dump_pos(dump) - bytecode_offset;
12000 const ibf_offset_t param_opt_table_offset = ibf_dump_param_opt_table(dump, iseq);
12001 const ibf_offset_t param_keyword_offset = ibf_dump_param_keyword(dump, iseq);
12002 const ibf_offset_t insns_info_body_offset = ibf_dump_insns_info_body(dump, iseq);
12004 positions = rb_iseq_insns_info_decode_positions(ISEQ_BODY(iseq));
12005 const ibf_offset_t insns_info_positions_offset = ibf_dump_insns_info_positions(dump, positions, body->insns_info.size);
12006 ruby_xfree(positions);
12008 const ibf_offset_t local_table_offset = ibf_dump_local_table(dump, iseq);
12009 const unsigned int catch_table_size = body->catch_table ? body->catch_table->size : 0;
12010 const ibf_offset_t catch_table_offset = ibf_dump_catch_table(dump, iseq);
12011 const int parent_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->parent_iseq);
12012 const int local_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->local_iseq);
12013 const int mandatory_only_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->mandatory_only_iseq);
12014 const ibf_offset_t ci_entries_offset = ibf_dump_ci_entries(dump, iseq);
12015 const ibf_offset_t outer_variables_offset = ibf_dump_outer_variables(dump, iseq);
12017#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12018 ibf_offset_t local_obj_list_offset;
12019 unsigned int local_obj_list_size;
12021 ibf_dump_object_list(dump, &local_obj_list_offset, &local_obj_list_size);
12024 ibf_offset_t body_offset = ibf_dump_pos(dump);
12027 unsigned int param_flags =
12028 (body->param.flags.has_lead << 0) |
12029 (body->param.flags.has_opt << 1) |
12030 (body->param.flags.has_rest << 2) |
12031 (body->param.flags.has_post << 3) |
12032 (body->param.flags.has_kw << 4) |
12033 (body->param.flags.has_kwrest << 5) |
12034 (body->param.flags.has_block << 6) |
12035 (body->param.flags.ambiguous_param0 << 7) |
12036 (body->param.flags.accepts_no_kwarg << 8) |
12037 (body->param.flags.ruby2_keywords << 9);
12039#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12040# define IBF_BODY_OFFSET(x) (x)
12042# define IBF_BODY_OFFSET(x) (body_offset - (x))
12045 ibf_dump_write_small_value(dump, body->type);
12046 ibf_dump_write_small_value(dump, body->iseq_size);
12047 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(bytecode_offset));
12048 ibf_dump_write_small_value(dump, bytecode_size);
12049 ibf_dump_write_small_value(dump, param_flags);
12050 ibf_dump_write_small_value(dump, body->param.size);
12051 ibf_dump_write_small_value(dump, body->param.lead_num);
12052 ibf_dump_write_small_value(dump, body->param.opt_num);
12053 ibf_dump_write_small_value(dump, body->param.rest_start);
12054 ibf_dump_write_small_value(dump, body->param.post_start);
12055 ibf_dump_write_small_value(dump, body->param.post_num);
12056 ibf_dump_write_small_value(dump, body->param.block_start);
12057 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(param_opt_table_offset));
12058 ibf_dump_write_small_value(dump, param_keyword_offset);
12059 ibf_dump_write_small_value(dump, location_pathobj_index);
12060 ibf_dump_write_small_value(dump, location_base_label_index);
12061 ibf_dump_write_small_value(dump, location_label_index);
12062 ibf_dump_write_small_value(dump, body->location.first_lineno);
12063 ibf_dump_write_small_value(dump, body->location.node_id);
12064 ibf_dump_write_small_value(dump, body->location.code_location.beg_pos.lineno);
12065 ibf_dump_write_small_value(dump, body->location.code_location.beg_pos.column);
12066 ibf_dump_write_small_value(dump, body->location.code_location.end_pos.lineno);
12067 ibf_dump_write_small_value(dump, body->location.code_location.end_pos.column);
12068 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(insns_info_body_offset));
12069 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(insns_info_positions_offset));
12070 ibf_dump_write_small_value(dump, body->insns_info.size);
12071 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(local_table_offset));
12072 ibf_dump_write_small_value(dump, catch_table_size);
12073 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(catch_table_offset));
12074 ibf_dump_write_small_value(dump, parent_iseq_index);
12075 ibf_dump_write_small_value(dump, local_iseq_index);
12076 ibf_dump_write_small_value(dump, mandatory_only_iseq_index);
12077 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(ci_entries_offset));
12078 ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(outer_variables_offset));
12079 ibf_dump_write_small_value(dump, body->variable.flip_count);
12080 ibf_dump_write_small_value(dump, body->local_table_size);
12081 ibf_dump_write_small_value(dump, body->ivc_size);
12082 ibf_dump_write_small_value(dump, body->icvarc_size);
12083 ibf_dump_write_small_value(dump, body->ise_size);
12084 ibf_dump_write_small_value(dump, body->ic_size);
12085 ibf_dump_write_small_value(dump, body->ci_size);
12086 ibf_dump_write_small_value(dump, body->stack_max);
12087 ibf_dump_write_small_value(dump, body->catch_except_p);
12088 ibf_dump_write_small_value(dump, body->builtin_inline_p);
12090#undef IBF_BODY_OFFSET
12092#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12093 ibf_offset_t iseq_length_bytes = ibf_dump_pos(dump);
12095 dump->current_buffer = saved_buffer;
12096 ibf_dump_write(dump, RSTRING_PTR(buffer.str), iseq_length_bytes);
12098 ibf_offset_t offset = ibf_dump_pos(dump);
12099 ibf_dump_write_small_value(dump, iseq_start);
12100 ibf_dump_write_small_value(dump, iseq_length_bytes);
12101 ibf_dump_write_small_value(dump, body_offset);
12103 ibf_dump_write_small_value(dump, local_obj_list_offset);
12104 ibf_dump_write_small_value(dump, local_obj_list_size);
12106 st_free_table(buffer.obj_table);
12110 return body_offset;
12115ibf_load_location_str(
const struct ibf_load *load,
VALUE str_index)
12117 VALUE str = ibf_load_object(load, str_index);
12119 str = rb_fstring(str);
12129 ibf_offset_t reading_pos = offset;
12131#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12133 load->current_buffer = &load->global_buffer;
12135 const ibf_offset_t iseq_start = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12136 const ibf_offset_t iseq_length_bytes = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12137 const ibf_offset_t body_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12140 buffer.buff = load->global_buffer.buff + iseq_start;
12141 buffer.size = iseq_length_bytes;
12142 buffer.obj_list_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12143 buffer.obj_list_size = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12144 buffer.obj_list = pinned_list_new(buffer.obj_list_size);
12146 load->current_buffer = &buffer;
12147 reading_pos = body_offset;
12150#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12151# define IBF_BODY_OFFSET(x) (x)
12153# define IBF_BODY_OFFSET(x) (offset - (x))
12156 const unsigned int type = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12157 const unsigned int iseq_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12158 const ibf_offset_t bytecode_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12159 const ibf_offset_t bytecode_size = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12160 const unsigned int param_flags = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12161 const unsigned int param_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12162 const int param_lead_num = (int)ibf_load_small_value(load, &reading_pos);
12163 const int param_opt_num = (int)ibf_load_small_value(load, &reading_pos);
12164 const int param_rest_start = (int)ibf_load_small_value(load, &reading_pos);
12165 const int param_post_start = (int)ibf_load_small_value(load, &reading_pos);
12166 const int param_post_num = (int)ibf_load_small_value(load, &reading_pos);
12167 const int param_block_start = (int)ibf_load_small_value(load, &reading_pos);
12168 const ibf_offset_t param_opt_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12169 const ibf_offset_t param_keyword_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
12170 const VALUE location_pathobj_index = ibf_load_small_value(load, &reading_pos);
12171 const VALUE location_base_label_index = ibf_load_small_value(load, &reading_pos);
12172 const VALUE location_label_index = ibf_load_small_value(load, &reading_pos);
12173 const int location_first_lineno = (int)ibf_load_small_value(load, &reading_pos);
12174 const int location_node_id = (int)ibf_load_small_value(load, &reading_pos);
12175 const int location_code_location_beg_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
12176 const int location_code_location_beg_pos_column = (int)ibf_load_small_value(load, &reading_pos);
12177 const int location_code_location_end_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
12178 const int location_code_location_end_pos_column = (int)ibf_load_small_value(load, &reading_pos);
12179 const ibf_offset_t insns_info_body_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12180 const ibf_offset_t insns_info_positions_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12181 const unsigned int insns_info_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12182 const ibf_offset_t local_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12183 const unsigned int catch_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12184 const ibf_offset_t catch_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12185 const int parent_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
12186 const int local_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
12187 const int mandatory_only_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
12188 const ibf_offset_t ci_entries_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12189 const ibf_offset_t outer_variables_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
12190 const rb_snum_t variable_flip_count = (rb_snum_t)ibf_load_small_value(load, &reading_pos);
12191 const unsigned int local_table_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12193 const unsigned int ivc_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12194 const unsigned int icvarc_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12195 const unsigned int ise_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12196 const unsigned int ic_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12198 const unsigned int ci_size = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12199 const unsigned int stack_max = (
unsigned int)ibf_load_small_value(load, &reading_pos);
12200 const char catch_except_p = (char)ibf_load_small_value(load, &reading_pos);
12201 const bool builtin_inline_p = (bool)ibf_load_small_value(load, &reading_pos);
12204 VALUE path = ibf_load_object(load, location_pathobj_index);
12209 realpath = path = rb_fstring(path);
12211 else if (RB_TYPE_P(path,
T_ARRAY)) {
12212 VALUE pathobj = path;
12218 if (!
NIL_P(realpath)) {
12219 if (!RB_TYPE_P(realpath,
T_STRING)) {
12221 "(%x), path=%+"PRIsVALUE,
12222 realpath,
TYPE(realpath), path);
12224 realpath = rb_fstring(realpath);
12230 rb_iseq_pathobj_set(iseq, path, realpath);
12235 VALUE dummy_frame = rb_vm_push_frame_fname(ec, path);
12237#undef IBF_BODY_OFFSET
12239 load_body->type =
type;
12240 load_body->stack_max = stack_max;
12241 load_body->
param.flags.has_lead = (param_flags >> 0) & 1;
12242 load_body->
param.flags.has_opt = (param_flags >> 1) & 1;
12243 load_body->
param.flags.has_rest = (param_flags >> 2) & 1;
12244 load_body->
param.flags.has_post = (param_flags >> 3) & 1;
12245 load_body->
param.flags.has_kw = FALSE;
12246 load_body->
param.flags.has_kwrest = (param_flags >> 5) & 1;
12247 load_body->
param.flags.has_block = (param_flags >> 6) & 1;
12248 load_body->
param.flags.ambiguous_param0 = (param_flags >> 7) & 1;
12249 load_body->
param.flags.accepts_no_kwarg = (param_flags >> 8) & 1;
12250 load_body->
param.flags.ruby2_keywords = (param_flags >> 9) & 1;
12251 load_body->
param.size = param_size;
12252 load_body->
param.lead_num = param_lead_num;
12253 load_body->
param.opt_num = param_opt_num;
12254 load_body->
param.rest_start = param_rest_start;
12255 load_body->
param.post_start = param_post_start;
12256 load_body->
param.post_num = param_post_num;
12257 load_body->
param.block_start = param_block_start;
12258 load_body->local_table_size = local_table_size;
12259 load_body->ci_size = ci_size;
12260 load_body->insns_info.size = insns_info_size;
12262 ISEQ_COVERAGE_SET(iseq,
Qnil);
12263 ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
12264 load_body->variable.flip_count = variable_flip_count;
12265 load_body->variable.script_lines =
Qnil;
12267 load_body->location.first_lineno = location_first_lineno;
12268 load_body->location.node_id = location_node_id;
12269 load_body->location.code_location.beg_pos.lineno = location_code_location_beg_pos_lineno;
12270 load_body->location.code_location.beg_pos.column = location_code_location_beg_pos_column;
12271 load_body->location.code_location.end_pos.lineno = location_code_location_end_pos_lineno;
12272 load_body->location.code_location.end_pos.column = location_code_location_end_pos_column;
12273 load_body->catch_except_p = catch_except_p;
12274 load_body->builtin_inline_p = builtin_inline_p;
12276 load_body->ivc_size = ivc_size;
12277 load_body->icvarc_size = icvarc_size;
12278 load_body->ise_size = ise_size;
12279 load_body->ic_size = ic_size;
12281 ibf_load_ci_entries(load, ci_entries_offset, ci_size, &load_body->call_data);
12282 load_body->outer_variables = ibf_load_outer_variables(load, outer_variables_offset);
12283 load_body->
param.opt_table = ibf_load_param_opt_table(load, param_opt_table_offset, param_opt_num);
12284 load_body->
param.keyword = ibf_load_param_keyword(load, param_keyword_offset);
12285 load_body->
param.flags.has_kw = (param_flags >> 4) & 1;
12286 load_body->insns_info.body = ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size);
12287 load_body->insns_info.positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size);
12288 load_body->local_table = ibf_load_local_table(load, local_table_offset, local_table_size);
12289 load_body->catch_table = ibf_load_catch_table(load, catch_table_offset, catch_table_size);
12290 load_body->parent_iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)parent_iseq_index);
12291 load_body->local_iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)local_iseq_index);
12292 load_body->mandatory_only_iseq = ibf_load_iseq(load, (
const rb_iseq_t *)(
VALUE)mandatory_only_iseq_index);
12294 ibf_load_code(load, iseq, bytecode_offset, bytecode_size, iseq_size);
12295#if VM_INSN_INFO_TABLE_IMPL == 2
12296 rb_iseq_insns_info_encode_positions(iseq);
12299 rb_iseq_translate_threaded_code(iseq);
12301#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12302 load->current_buffer = &load->global_buffer;
12305 RB_OBJ_WRITE(iseq, &load_body->location.base_label, ibf_load_location_str(load, location_base_label_index));
12306 RB_OBJ_WRITE(iseq, &load_body->location.label, ibf_load_location_str(load, location_label_index));
12308#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
12309 load->current_buffer = saved_buffer;
12311 verify_call_cache(iseq);
12314 rb_vm_pop_frame_no_int(ec);
12324ibf_dump_iseq_list_i(st_data_t key, st_data_t val, st_data_t ptr)
12329 ibf_offset_t offset = ibf_dump_iseq_each(args->dump, iseq);
12330 rb_ary_push(args->offset_list,
UINT2NUM(offset));
12332 return ST_CONTINUE;
12338 VALUE offset_list = rb_ary_hidden_new(dump->iseq_table->num_entries);
12342 args.offset_list = offset_list;
12344 st_foreach(dump->iseq_table, ibf_dump_iseq_list_i, (st_data_t)&args);
12347 st_index_t size = dump->iseq_table->num_entries;
12348 ibf_offset_t *offsets =
ALLOCA_N(ibf_offset_t, size);
12350 for (i = 0; i < size; i++) {
12354 ibf_dump_align(dump,
sizeof(ibf_offset_t));
12355 header->iseq_list_offset = ibf_dump_write(dump, offsets,
sizeof(ibf_offset_t) * size);
12356 header->iseq_list_size = (
unsigned int)size;
12359#define IBF_OBJECT_INTERNAL FL_PROMOTED0
12368 unsigned int type: 5;
12369 unsigned int special_const: 1;
12370 unsigned int frozen: 1;
12371 unsigned int internal: 1;
12374enum ibf_object_class_index {
12375 IBF_OBJECT_CLASS_OBJECT,
12376 IBF_OBJECT_CLASS_ARRAY,
12377 IBF_OBJECT_CLASS_STANDARD_ERROR,
12378 IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR,
12379 IBF_OBJECT_CLASS_TYPE_ERROR,
12380 IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR,
12390 long keyval[FLEX_ARY_LEN];
12403 BDIGIT digits[FLEX_ARY_LEN];
12406enum ibf_object_data_type {
12407 IBF_OBJECT_DATA_ENCODING,
12418#define IBF_ALIGNED_OFFSET(align, offset) \
12419 ((((offset) - 1) / (align) + 1) * (align))
12420#define IBF_OBJBODY(type, offset) (const type *)\
12421 ibf_load_check_offset(load, IBF_ALIGNED_OFFSET(RUBY_ALIGNOF(type), offset))
12424ibf_load_check_offset(
const struct ibf_load *load,
size_t offset)
12426 if (offset >= load->current_buffer->size) {
12429 return load->current_buffer->buff + offset;
12432NORETURN(
static void ibf_dump_object_unsupported(
struct ibf_dump *dump,
VALUE obj));
12435ibf_dump_object_unsupported(
struct ibf_dump *dump,
VALUE obj)
12438 rb_raw_obj_info(buff,
sizeof(buff), obj);
12454 enum ibf_object_class_index cindex;
12455 if (obj == rb_cObject) {
12456 cindex = IBF_OBJECT_CLASS_OBJECT;
12459 cindex = IBF_OBJECT_CLASS_ARRAY;
12462 cindex = IBF_OBJECT_CLASS_STANDARD_ERROR;
12465 cindex = IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR;
12468 cindex = IBF_OBJECT_CLASS_TYPE_ERROR;
12471 cindex = IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR;
12474 rb_obj_info_dump(obj);
12476 rb_bug(
"unsupported class");
12478 ibf_dump_write_small_value(dump, (
VALUE)cindex);
12484 enum ibf_object_class_index cindex = (
enum ibf_object_class_index)ibf_load_small_value(load, &offset);
12487 case IBF_OBJECT_CLASS_OBJECT:
12489 case IBF_OBJECT_CLASS_ARRAY:
12491 case IBF_OBJECT_CLASS_STANDARD_ERROR:
12493 case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR:
12495 case IBF_OBJECT_CLASS_TYPE_ERROR:
12497 case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR:
12509 (void)IBF_W(&dbl,
double, 1);
12515 const double *dblp = IBF_OBJBODY(
double, offset);
12522 long encindex = (long)rb_enc_get_index(obj);
12523 long len = RSTRING_LEN(obj);
12524 const char *ptr = RSTRING_PTR(obj);
12526 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
12527 rb_encoding *enc = rb_enc_from_index((
int)encindex);
12528 const char *enc_name = rb_enc_name(enc);
12529 encindex = RUBY_ENCINDEX_BUILTIN_MAX + ibf_dump_object(dump,
rb_str_new2(enc_name));
12532 ibf_dump_write_small_value(dump, encindex);
12533 ibf_dump_write_small_value(dump, len);
12534 IBF_WP(ptr,
char, len);
12540 ibf_offset_t reading_pos = offset;
12542 int encindex = (int)ibf_load_small_value(load, &reading_pos);
12543 const long len = (long)ibf_load_small_value(load, &reading_pos);
12544 const char *ptr = load->current_buffer->buff + reading_pos;
12546 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
12547 VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX);
12548 encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str));
12552 if (header->frozen && !header->internal) {
12556 str = rb_enc_str_new(ptr, len, rb_enc_from_index(encindex));
12559 if (header->frozen) str = rb_fstring(str);
12567 VALUE srcstr = RREGEXP_SRC(obj);
12570 regexp.srcstr = (long)ibf_dump_object(dump, srcstr);
12572 ibf_dump_write_byte(dump, (
unsigned char)regexp.option);
12573 ibf_dump_write_small_value(dump, regexp.srcstr);
12580 regexp.option = ibf_load_byte(load, &offset);
12581 regexp.srcstr = ibf_load_small_value(load, &offset);
12583 VALUE srcstr = ibf_load_object(load, regexp.srcstr);
12584 VALUE reg = rb_reg_compile(srcstr, (
int)regexp.option, NULL, 0);
12596 ibf_dump_write_small_value(dump, len);
12597 for (i=0; i<len; i++) {
12598 long index = (long)ibf_dump_object(dump,
RARRAY_AREF(obj, i));
12599 ibf_dump_write_small_value(dump, index);
12606 ibf_offset_t reading_pos = offset;
12608 const long len = (long)ibf_load_small_value(load, &reading_pos);
12610 VALUE ary = header->internal ? rb_ary_hidden_new(len) : rb_ary_new_capa(len);
12613 for (i=0; i<len; i++) {
12614 const VALUE index = ibf_load_small_value(load, &reading_pos);
12615 rb_ary_push(ary, ibf_load_object(load, index));
12624ibf_dump_object_hash_i(st_data_t key, st_data_t val, st_data_t ptr)
12628 VALUE key_index = ibf_dump_object(dump, (
VALUE)key);
12629 VALUE val_index = ibf_dump_object(dump, (
VALUE)val);
12631 ibf_dump_write_small_value(dump, key_index);
12632 ibf_dump_write_small_value(dump, val_index);
12633 return ST_CONTINUE;
12640 ibf_dump_write_small_value(dump, (
VALUE)len);
12642 if (len > 0) rb_hash_foreach(obj, ibf_dump_object_hash_i, (
VALUE)dump);
12648 long len = (long)ibf_load_small_value(load, &offset);
12649 VALUE obj = rb_hash_new_with_size(len);
12652 for (i = 0; i < len; i++) {
12653 VALUE key_index = ibf_load_small_value(load, &offset);
12654 VALUE val_index = ibf_load_small_value(load, &offset);
12656 VALUE key = ibf_load_object(load, key_index);
12657 VALUE val = ibf_load_object(load, val_index);
12658 rb_hash_aset(obj, key, val);
12660 rb_hash_rehash(obj);
12676 range.class_index = 0;
12679 range.beg = (long)ibf_dump_object(dump, beg);
12680 range.end = (long)ibf_dump_object(dump, end);
12695 VALUE beg = ibf_load_object(load, range->beg);
12696 VALUE end = ibf_load_object(load, range->end);
12706 ssize_t len = BIGNUM_LEN(obj);
12707 ssize_t slen = BIGNUM_SIGN(obj) > 0 ? len : len * -1;
12708 BDIGIT *d = BIGNUM_DIGITS(obj);
12710 (void)IBF_W(&slen, ssize_t, 1);
12711 IBF_WP(d, BDIGIT, len);
12718 int sign = bignum->slen > 0;
12719 ssize_t len = sign > 0 ? bignum->slen : -1 * bignum->slen;
12720 VALUE obj = rb_integer_unpack(bignum->digits, len * 2, 2, 0,
12730 if (rb_data_is_encoding(obj)) {
12732 const char *name = rb_enc_name(enc);
12733 long len = strlen(name) + 1;
12735 data[0] = IBF_OBJECT_DATA_ENCODING;
12737 (void)IBF_W(data,
long, 2);
12738 IBF_WP(name,
char, len);
12741 ibf_dump_object_unsupported(dump, obj);
12748 const long *body = IBF_OBJBODY(
long, offset);
12749 const enum ibf_object_data_type
type = (
enum ibf_object_data_type)body[0];
12751 const char *data = (
const char *)&body[2];
12754 case IBF_OBJECT_DATA_ENCODING:
12756 VALUE encobj = rb_enc_from_encoding(rb_enc_find(data));
12761 return ibf_load_object_unsupported(load, header, offset);
12765ibf_dump_object_complex_rational(
struct ibf_dump *dump,
VALUE obj)
12768 data[0] = (long)ibf_dump_object(dump, RCOMPLEX(obj)->real);
12769 data[1] = (long)ibf_dump_object(dump, RCOMPLEX(obj)->imag);
12771 (void)IBF_W(data,
long, 2);
12775ibf_load_object_complex_rational(
const struct ibf_load *load,
const struct ibf_object_header *header, ibf_offset_t offset)
12778 VALUE a = ibf_load_object(load, nums->a);
12779 VALUE b = ibf_load_object(load, nums->b);
12791 ibf_dump_object_string(dump,
rb_sym2str(obj));
12797 ibf_offset_t reading_pos = offset;
12799 int encindex = (int)ibf_load_small_value(load, &reading_pos);
12800 const long len = (long)ibf_load_small_value(load, &reading_pos);
12801 const char *ptr = load->current_buffer->buff + reading_pos;
12803 if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
12804 VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX);
12805 encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str));
12808 ID id =
rb_intern3(ptr, len, rb_enc_from_index(encindex));
12812typedef void (*ibf_dump_object_function)(
struct ibf_dump *dump,
VALUE obj);
12813static ibf_dump_object_function dump_object_functions[
RUBY_T_MASK+1] = {
12814 ibf_dump_object_unsupported,
12815 ibf_dump_object_unsupported,
12816 ibf_dump_object_class,
12817 ibf_dump_object_unsupported,
12818 ibf_dump_object_float,
12819 ibf_dump_object_string,
12820 ibf_dump_object_regexp,
12821 ibf_dump_object_array,
12822 ibf_dump_object_hash,
12823 ibf_dump_object_struct,
12824 ibf_dump_object_bignum,
12825 ibf_dump_object_unsupported,
12826 ibf_dump_object_data,
12827 ibf_dump_object_unsupported,
12828 ibf_dump_object_complex_rational,
12829 ibf_dump_object_complex_rational,
12830 ibf_dump_object_unsupported,
12831 ibf_dump_object_unsupported,
12832 ibf_dump_object_unsupported,
12833 ibf_dump_object_unsupported,
12834 ibf_dump_object_symbol,
12835 ibf_dump_object_unsupported,
12836 ibf_dump_object_unsupported,
12837 ibf_dump_object_unsupported,
12838 ibf_dump_object_unsupported,
12839 ibf_dump_object_unsupported,
12840 ibf_dump_object_unsupported,
12841 ibf_dump_object_unsupported,
12842 ibf_dump_object_unsupported,
12843 ibf_dump_object_unsupported,
12844 ibf_dump_object_unsupported,
12845 ibf_dump_object_unsupported,
12851 unsigned char byte =
12852 (header.type << 0) |
12853 (header.special_const << 5) |
12854 (header.frozen << 6) |
12855 (header.internal << 7);
12861ibf_load_object_object_header(const struct
ibf_load *load, ibf_offset_t *offset)
12863 unsigned char byte = ibf_load_byte(load, offset);
12866 header.type = (
byte >> 0) & 0x1f;
12867 header.special_const = (
byte >> 5) & 0x01;
12868 header.frozen = (
byte >> 6) & 0x01;
12869 header.internal = (
byte >> 7) & 0x01;
12878 ibf_offset_t current_offset;
12879 IBF_ZERO(obj_header);
12880 obj_header.type =
TYPE(obj);
12882 IBF_W_ALIGN(ibf_offset_t);
12883 current_offset = ibf_dump_pos(dump);
12887 RB_FLOAT_TYPE_P(obj))) {
12888 obj_header.special_const = TRUE;
12889 obj_header.frozen = TRUE;
12890 obj_header.internal = TRUE;
12891 ibf_dump_object_object_header(dump, obj_header);
12892 ibf_dump_write_small_value(dump, obj);
12895 obj_header.internal =
SPECIAL_CONST_P(obj) ? FALSE : (RBASIC_CLASS(obj) == 0) ? TRUE : FALSE;
12896 obj_header.special_const = FALSE;
12898 ibf_dump_object_object_header(dump, obj_header);
12899 (*dump_object_functions[obj_header.type])(dump, obj);
12902 return current_offset;
12906static ibf_load_object_function load_object_functions[
RUBY_T_MASK+1] = {
12907 ibf_load_object_unsupported,
12908 ibf_load_object_unsupported,
12909 ibf_load_object_class,
12910 ibf_load_object_unsupported,
12911 ibf_load_object_float,
12912 ibf_load_object_string,
12913 ibf_load_object_regexp,
12914 ibf_load_object_array,
12915 ibf_load_object_hash,
12916 ibf_load_object_struct,
12917 ibf_load_object_bignum,
12918 ibf_load_object_unsupported,
12919 ibf_load_object_data,
12920 ibf_load_object_unsupported,
12921 ibf_load_object_complex_rational,
12922 ibf_load_object_complex_rational,
12923 ibf_load_object_unsupported,
12924 ibf_load_object_unsupported,
12925 ibf_load_object_unsupported,
12926 ibf_load_object_unsupported,
12927 ibf_load_object_symbol,
12928 ibf_load_object_unsupported,
12929 ibf_load_object_unsupported,
12930 ibf_load_object_unsupported,
12931 ibf_load_object_unsupported,
12932 ibf_load_object_unsupported,
12933 ibf_load_object_unsupported,
12934 ibf_load_object_unsupported,
12935 ibf_load_object_unsupported,
12936 ibf_load_object_unsupported,
12937 ibf_load_object_unsupported,
12938 ibf_load_object_unsupported,
12942ibf_load_object(
const struct ibf_load *load,
VALUE object_index)
12944 if (object_index == 0) {
12948 VALUE obj = pinned_list_fetch(load->current_buffer->obj_list, (
long)object_index);
12950 ibf_offset_t *offsets = (ibf_offset_t *)(load->current_buffer->obj_list_offset + load->current_buffer->buff);
12951 ibf_offset_t offset = offsets[object_index];
12952 const struct ibf_object_header header = ibf_load_object_object_header(load, &offset);
12955 fprintf(stderr,
"ibf_load_object: list=%#x offsets=%p offset=%#x\n",
12956 load->current_buffer->obj_list_offset, (
void *)offsets, offset);
12957 fprintf(stderr,
"ibf_load_object: type=%#x special=%d frozen=%d internal=%d\n",
12958 header.type, header.special_const, header.frozen, header.internal);
12960 if (offset >= load->current_buffer->size) {
12964 if (header.special_const) {
12965 ibf_offset_t reading_pos = offset;
12967 obj = ibf_load_small_value(load, &reading_pos);
12970 obj = (*load_object_functions[header.type])(load, &header, offset);
12973 pinned_list_store(load->current_buffer->obj_list, (
long)object_index, obj);
12976 fprintf(stderr,
"ibf_load_object: index=%#"PRIxVALUE
" obj=%#"PRIxVALUE
"\n",
12977 object_index, obj);
12990ibf_dump_object_list_i(st_data_t key, st_data_t val, st_data_t ptr)
12995 ibf_offset_t offset = ibf_dump_object_object(args->dump, obj);
12996 rb_ary_push(args->offset_list,
UINT2NUM(offset));
12998 return ST_CONTINUE;
13002ibf_dump_object_list(
struct ibf_dump *dump, ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size)
13004 st_table *obj_table = dump->current_buffer->obj_table;
13005 VALUE offset_list = rb_ary_hidden_new(obj_table->num_entries);
13009 args.offset_list = offset_list;
13011 st_foreach(obj_table, ibf_dump_object_list_i, (st_data_t)&args);
13013 IBF_W_ALIGN(ibf_offset_t);
13014 *obj_list_offset = ibf_dump_pos(dump);
13016 st_index_t size = obj_table->num_entries;
13019 for (i=0; i<size; i++) {
13024 *obj_list_size = (
unsigned int)size;
13028ibf_dump_mark(
void *ptr)
13031 rb_gc_mark(dump->global_buffer.str);
13033 rb_mark_set(dump->global_buffer.obj_table);
13034 rb_mark_set(dump->iseq_table);
13038ibf_dump_free(
void *ptr)
13041 if (dump->global_buffer.obj_table) {
13042 st_free_table(dump->global_buffer.obj_table);
13043 dump->global_buffer.obj_table = 0;
13045 if (dump->iseq_table) {
13046 st_free_table(dump->iseq_table);
13047 dump->iseq_table = 0;
13053ibf_dump_memsize(
const void *ptr)
13056 size_t size =
sizeof(*dump);
13057 if (dump->iseq_table) size += st_memsize(dump->iseq_table);
13058 if (dump->global_buffer.obj_table) size += st_memsize(dump->global_buffer.obj_table);
13064 {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
13065 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
13071 dump->global_buffer.obj_table = NULL;
13072 dump->iseq_table = NULL;
13075 dump->global_buffer.obj_table = ibf_dump_object_table_new();
13076 dump->iseq_table = st_init_numtable();
13078 dump->current_buffer = &dump->global_buffer;
13089 if (ISEQ_BODY(iseq)->parent_iseq != NULL ||
13090 ISEQ_BODY(iseq)->local_iseq != iseq) {
13093 if (
RTEST(ISEQ_COVERAGE(iseq))) {
13098 ibf_dump_setup(dump, dump_obj);
13100 ibf_dump_write(dump, &header,
sizeof(header));
13101 ibf_dump_write(dump, RUBY_PLATFORM, strlen(RUBY_PLATFORM) + 1);
13102 ibf_dump_iseq(dump, iseq);
13104 header.magic[0] =
'Y';
13105 header.magic[1] =
'A';
13106 header.magic[2] =
'R';
13107 header.magic[3] =
'B';
13108 header.major_version = IBF_MAJOR_VERSION;
13109 header.minor_version = IBF_MINOR_VERSION;
13110 ibf_dump_iseq_list(dump, &header);
13111 ibf_dump_object_list(dump, &header.global_object_list_offset, &header.global_object_list_size);
13112 header.size = ibf_dump_pos(dump);
13115 VALUE opt_str = opt;
13117 header.extra_size = RSTRING_LENINT(opt_str);
13118 ibf_dump_write(dump, ptr, header.extra_size);
13121 header.extra_size = 0;
13124 ibf_dump_overwrite(dump, &header,
sizeof(header), 0);
13126 str = dump->global_buffer.str;
13127 ibf_dump_free(dump);
13133static const ibf_offset_t *
13134ibf_iseq_list(
const struct ibf_load *load)
13136 return (
const ibf_offset_t *)(load->global_buffer.buff + load->header->iseq_list_offset);
13140rb_ibf_load_iseq_complete(
rb_iseq_t *iseq)
13144 ibf_offset_t offset = ibf_iseq_list(load)[iseq->aux.loader.index];
13147 fprintf(stderr,
"rb_ibf_load_iseq_complete: index=%#x offset=%#x size=%#x\n",
13148 iseq->aux.loader.index, offset,
13149 load->header->size);
13151 ibf_load_iseq_each(load, iseq, offset);
13152 ISEQ_COMPILE_DATA_CLEAR(iseq);
13154 rb_iseq_init_trace(iseq);
13155 load->iseq = prev_src_iseq;
13162 rb_ibf_load_iseq_complete((
rb_iseq_t *)iseq);
13170 int iseq_index = (int)(
VALUE)index_iseq;
13173 fprintf(stderr,
"ibf_load_iseq: index_iseq=%p iseq_list=%p\n",
13174 (
void *)index_iseq, (
void *)load->iseq_list);
13176 if (iseq_index == -1) {
13180 VALUE iseqv = pinned_list_fetch(load->iseq_list, iseq_index);
13183 fprintf(stderr,
"ibf_load_iseq: iseqv=%p\n", (
void *)iseqv);
13191 fprintf(stderr,
"ibf_load_iseq: new iseq=%p\n", (
void *)iseq);
13194 iseq->aux.loader.obj = load->loader_obj;
13195 iseq->aux.loader.index = iseq_index;
13197 fprintf(stderr,
"ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n",
13198 (
void *)iseq, (
void *)load->loader_obj, iseq_index);
13200 pinned_list_store(load->iseq_list, iseq_index, (
VALUE)iseq);
13204 fprintf(stderr,
"ibf_load_iseq: loading iseq=%p\n", (
void *)iseq);
13206 rb_ibf_load_iseq_complete(iseq);
13208 if (GET_VM()->builtin_function_table) {
13209 rb_ibf_load_iseq_complete(iseq);
13214 fprintf(stderr,
"ibf_load_iseq: iseq=%p loaded %p\n",
13215 (
void *)iseq, (
void *)load->iseq);
13223ibf_load_setup_bytes(
struct ibf_load *load,
VALUE loader_obj,
const char *bytes,
size_t size)
13225 load->loader_obj = loader_obj;
13226 load->global_buffer.buff = bytes;
13227 load->header = (
struct ibf_header *)load->global_buffer.buff;
13228 load->global_buffer.size = load->header->size;
13229 load->global_buffer.obj_list_offset = load->header->global_object_list_offset;
13230 load->global_buffer.obj_list_size = load->header->global_object_list_size;
13231 RB_OBJ_WRITE(loader_obj, &load->iseq_list, pinned_list_new(load->header->iseq_list_size));
13232 RB_OBJ_WRITE(loader_obj, &load->global_buffer.obj_list, pinned_list_new(load->global_buffer.obj_list_size));
13235 load->current_buffer = &load->global_buffer;
13237 if (size < load->header->size) {
13240 if (strncmp(load->header->magic,
"YARB", 4) != 0) {
13243 if (load->header->major_version != IBF_MAJOR_VERSION ||
13244 load->header->minor_version != IBF_MINOR_VERSION) {
13246 load->header->major_version, load->header->minor_version, IBF_MAJOR_VERSION, IBF_MINOR_VERSION);
13248 if (strcmp(load->global_buffer.buff +
sizeof(
struct ibf_header), RUBY_PLATFORM) != 0) {
13251 if (load->header->iseq_list_offset %
RUBY_ALIGNOF(ibf_offset_t)) {
13253 load->header->iseq_list_offset);
13255 if (load->global_buffer.obj_list_offset %
RUBY_ALIGNOF(ibf_offset_t)) {
13257 load->global_buffer.obj_list_offset);
13264 if (RSTRING_LENINT(str) < (
int)
sizeof(
struct ibf_header)) {
13269 str =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
13272 ibf_load_setup_bytes(load, loader_obj,
StringValuePtr(str), RSTRING_LEN(str));
13277ibf_loader_mark(
void *ptr)
13280 rb_gc_mark(load->str);
13281 rb_gc_mark(load->iseq_list);
13282 rb_gc_mark(load->global_buffer.obj_list);
13286ibf_loader_free(
void *ptr)
13293ibf_loader_memsize(
const void *ptr)
13300 {ibf_loader_mark, ibf_loader_free, ibf_loader_memsize,},
13301 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
13305rb_iseq_ibf_load(
VALUE str)
13311 ibf_load_setup(load, loader_obj, str);
13312 iseq = ibf_load_iseq(load, 0);
13319rb_iseq_ibf_load_bytes(
const char *bytes,
size_t size)
13325 ibf_load_setup_bytes(load, loader_obj, bytes, size);
13326 iseq = ibf_load_iseq(load, 0);
13333rb_iseq_ibf_load_extra_data(
VALUE str)
13339 ibf_load_setup(load, loader_obj, str);
13340 extra_str =
rb_str_new(load->global_buffer.buff + load->header->size, load->header->extra_size);
#define RUBY_ASSERT(expr)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_ALIGNOF
Wraps (or simulates) alignof.
#define RUBY_EVENT_END
Encountered an end of a class clause.
#define RUBY_EVENT_C_CALL
A method, written in C, is called.
#define RUBY_EVENT_B_RETURN
Encountered a next statement.
#define RUBY_EVENT_CLASS
Encountered a new class.
#define RUBY_EVENT_NONE
No events.
#define RUBY_EVENT_LINE
Encountered a new line.
#define RUBY_EVENT_RETURN
Encountered a return statement.
#define RUBY_EVENT_C_RETURN
Return from a method, written in C.
#define RUBY_EVENT_B_CALL
Encountered an yield statement.
uint32_t rb_event_flag_t
Represents event(s).
#define RUBY_EVENT_CALL
A method, written in Ruby, is called.
#define rb_str_new2
Old name of rb_str_new_cstr.
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
#define TYPE(_)
Old name of rb_type.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define NUM2LL
Old name of RB_NUM2LL.
#define REALLOC_N
Old name of RB_REALLOC_N.
#define ALLOCV
Old name of RB_ALLOCV.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define T_STRING
Old name of RUBY_T_STRING.
#define xfree
Old name of ruby_xfree.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define T_NIL
Old name of RUBY_T_NIL.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define T_FLOAT
Old name of RUBY_T_FLOAT.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SYM2ID
Old name of RB_SYM2ID.
#define FIX2UINT
Old name of RB_FIX2UINT.
#define ZALLOC
Old name of RB_ZALLOC.
#define CLASS_OF
Old name of rb_class_of.
#define FIXABLE
Old name of RB_FIXABLE.
#define xmalloc
Old name of ruby_xmalloc.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2INT
Old name of RB_FIX2INT.
#define NUM2UINT
Old name of RB_NUM2UINT.
#define ZALLOC_N
Old name of RB_ZALLOC_N.
#define ASSUME
Old name of RBIMPL_ASSUME.
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
#define T_HASH
Old name of RUBY_T_HASH.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define FL_SET
Old name of RB_FL_SET.
#define Qtrue
Old name of RUBY_Qtrue.
#define NUM2INT
Old name of RB_NUM2INT.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
#define DBL2NUM
Old name of rb_float_new.
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
#define FL_TEST
Old name of RB_FL_TEST.
#define FL_FREEZE
Old name of RUBY_FL_FREEZE.
#define xcalloc
Old name of ruby_xcalloc.
#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.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
VALUE rb_eNotImpError
NotImplementedError exception.
void rb_bug(const char *fmt,...)
Interpreter panic switch.
VALUE rb_eStandardError
StandardError exception.
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
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 always regardless of runtime -W flag.
VALUE rb_eNoMatchingPatternKeyError
NoMatchingPatternKeyError exception.
VALUE rb_eArgError
ArgumentError exception.
VALUE rb_eIndexError
IndexError exception.
VALUE rb_eSyntaxError
SyntaxError exception.
VALUE rb_cArray
Array class.
VALUE rb_cObject
Documented in include/ruby/internal/globals.h.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_cNumeric
Numeric class.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_cRange
Range class.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it returns a "f"string.
ID rb_intern3(const char *name, long len, rb_encoding *enc)
Identical to rb_intern2(), except it additionally takes an encoding.
Defines RBIMPL_HAS_BUILTIN.
#define INTEGER_PACK_LITTLE_ENDIAN
Little endian combination.
#define INTEGER_PACK_NEGATIVE
Interprets the input as a signed negative number (unpack only).
int rb_is_const_id(ID id)
Classifies the given ID, then sees if it is a constant.
ID rb_id_attrset(ID id)
Calculates an ID of attribute writer.
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_tmp_new(long len)
Allocates a "temporary" string.
int rb_str_hash_cmp(VALUE str1, VALUE str2)
Compares two strings.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
st_index_t rb_str_hash(VALUE str)
Calculates a hash value of a string.
VALUE rb_str_cat(VALUE dst, const char *src, long srclen)
Destructively appends the passed contents to the string.
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
VALUE rb_str_freeze(VALUE str)
This is the implementation of String#freeze.
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
VALUE rb_id2sym(ID id)
Allocates an instance of rb_cSymbol that has the given id.
VALUE rb_sym2str(VALUE id)
Identical to rb_id2str(), except it takes an instance of rb_cSymbol rather than an ID.
ID rb_sym2id(VALUE obj)
Converts an instance of rb_cSymbol into an ID.
const char * rb_id2name(ID id)
Retrieves the name mapped to the given id.
#define DECIMAL_SIZE_OF_BITS(n)
an approximation of ceil(n * log10(2)), up to 65536 at least
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
#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.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RBIMPL_ATTR_NORETURN()
Wraps (or simulates) [[noreturn]]
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_CONST_PTR_TRANSIENT
Just another name of rb_array_const_ptr_transient.
#define RARRAY_AREF(a, i)
#define Data_Wrap_Struct(klass, mark, free, sval)
Converts sval, a pointer to your struct, into a Ruby object.
#define DATA_PTR(obj)
Convenient getter macro.
#define RHASH_SIZE(h)
Queries the size of the hash.
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
#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_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
void rb_p(VALUE obj)
Inspects an object.
#define RTEST
This is an old name of RB_TEST.
Internal header for Complex.
Internal header for Rational.
struct rb_iseq_constant_body::@132 param
parameter information
uintptr_t VALUE
Type that represents a Ruby object.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
@ RUBY_T_MASK
Bitmask of ruby_value_type.