27#include "internal/error.h"
33#include "internal/symbol.h"
35#include "internal/variable.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))
145#define compile_debug CPDEBUG
147#define compile_debug ISEQ_COMPILE_DATA(iseq)->option->debug_level
152#define compile_debug_print_indent(level) \
153 ruby_debug_print_indent((level), compile_debug, gl_node_level * 2)
155#define debugp(header, value) (void) \
156 (compile_debug_print_indent(1) && \
157 ruby_debug_print_value(1, compile_debug, (header), (value)))
159#define debugi(header, id) (void) \
160 (compile_debug_print_indent(1) && \
161 ruby_debug_print_id(1, compile_debug, (header), (id)))
163#define debugp_param(header, value) (void) \
164 (compile_debug_print_indent(1) && \
165 ruby_debug_print_value(1, compile_debug, (header), (value)))
167#define debugp_verbose(header, value) (void) \
168 (compile_debug_print_indent(2) && \
169 ruby_debug_print_value(2, compile_debug, (header), (value)))
171#define debugp_verbose_node(header, value) (void) \
172 (compile_debug_print_indent(10) && \
173 ruby_debug_print_value(10, compile_debug, (header), (value)))
175#define debug_node_start(node) ((void) \
176 (compile_debug_print_indent(1) && \
177 (ruby_debug_print_node(1, CPDEBUG, "", (const NODE *)(node)), gl_node_level)), \
180#define debug_node_end() gl_node_level --
184#define debugi(header, id) ((void)0)
185#define debugp(header, value) ((void)0)
186#define debugp_verbose(header, value) ((void)0)
187#define debugp_verbose_node(header, value) ((void)0)
188#define debugp_param(header, value) ((void)0)
189#define debug_node_start(node) ((void)0)
190#define debug_node_end() ((void)0)
193#if CPDEBUG > 1 || CPDEBUG < 0
195#define printf ruby_debug_printf
196#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
197#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v))
199#define debugs if(0)printf
200#define debug_compile(msg, v) (v)
203#define LVAR_ERRINFO (1)
206#define NEW_LABEL(l) new_label_body(iseq, (l))
207#define LABEL_FORMAT "<L%03d>"
209#define NEW_ISEQ(node, name, type, line_no) \
210 new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no))
212#define NEW_CHILD_ISEQ(node, name, type, line_no) \
213 new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no))
216#define ADD_SEQ(seq1, seq2) \
217 APPEND_LIST((seq1), (seq2))
220#define ADD_INSN(seq, line, insn) \
221 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
224#define INSERT_BEFORE_INSN(next, line, insn) \
225 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
228#define INSERT_AFTER_INSN(prev, line, insn) \
229 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
232#define ADD_INSN1(seq, line, insn, op1) \
233 ADD_ELEM((seq), (LINK_ELEMENT *) \
234 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
237#define INSERT_BEFORE_INSN1(next, line, insn, op1) \
238 ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) \
239 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
242#define INSERT_AFTER_INSN1(prev, line, insn, op1) \
243 ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) \
244 new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
246#define LABEL_REF(label) ((label)->refcnt++)
249#define ADD_INSNL(seq, line, insn, label) (ADD_INSN1(seq, line, insn, label), LABEL_REF(label))
251#define ADD_INSN2(seq, line, insn, op1, op2) \
252 ADD_ELEM((seq), (LINK_ELEMENT *) \
253 new_insn_body(iseq, (line), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
255#define ADD_INSN3(seq, line, insn, op1, op2, op3) \
256 ADD_ELEM((seq), (LINK_ELEMENT *) \
257 new_insn_body(iseq, (line), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
260#define ADD_SEND(seq, line, id, argc) \
261 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL)
263#define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag) \
264 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)(flag), NULL)
266#define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block) \
267 ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(0), NULL)
269#define ADD_CALL_RECEIVER(seq, line) \
270 ADD_INSN((seq), (line), putself)
272#define ADD_CALL(seq, line, id, argc) \
273 ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
275#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \
276 ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
278#define ADD_SEND_R(seq, line, id, argc, block, flag, keywords) \
279 ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
281#define ADD_TRACE(seq, event) \
282 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), 0))
283#define ADD_TRACE_WITH_DATA(seq, event, data) \
284 ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), (data)))
286static void iseq_add_getlocal(
rb_iseq_t *iseq,
LINK_ANCHOR *
const seq,
int line,
int idx,
int level);
287static void iseq_add_setlocal(
rb_iseq_t *iseq,
LINK_ANCHOR *
const seq,
int line,
int idx,
int level);
289#define ADD_GETLOCAL(seq, line, idx, level) iseq_add_getlocal(iseq, (seq), (line), (idx), (level))
290#define ADD_SETLOCAL(seq, line, idx, level) iseq_add_setlocal(iseq, (seq), (line), (idx), (level))
293#define ADD_LABEL(seq, label) \
294 ADD_ELEM((seq), (LINK_ELEMENT *) (label))
296#define APPEND_LABEL(seq, before, label) \
297 APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label))
299#define ADD_ADJUST(seq, line, label) \
300 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), (line)))
302#define ADD_ADJUST_RESTORE(seq, label) \
303 ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1))
305#define LABEL_UNREMOVABLE(label) \
306 ((label) ? (LABEL_REF(label), (label)->unremovable=1) : 0)
307#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \
308 VALUE _e = rb_ary_new3(5, (type), \
309 (VALUE)(ls) | 1, (VALUE)(le) | 1, \
310 (VALUE)(iseqv), (VALUE)(lc) | 1); \
311 LABEL_UNREMOVABLE(ls); \
314 if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) \
315 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, rb_ary_tmp_new(3)); \
316 rb_ary_push(ISEQ_COMPILE_DATA(iseq)->catch_table_ary, freeze_hide_obj(_e)); \
320#define COMPILE(anchor, desc, node) \
321 (debug_compile("== " desc "\n", \
322 iseq_compile_each(iseq, (anchor), (node), 0)))
325#define COMPILE_POPPED(anchor, desc, node) \
326 (debug_compile("== " desc "\n", \
327 iseq_compile_each(iseq, (anchor), (node), 1)))
330#define COMPILE_(anchor, desc, node, popped) \
331 (debug_compile("== " desc "\n", \
332 iseq_compile_each(iseq, (anchor), (node), (popped))))
334#define COMPILE_RECV(anchor, desc, node) \
335 (private_recv_p(node) ? \
336 (ADD_INSN(anchor, nd_line(node), putself), VM_CALL_FCALL) : \
337 COMPILE(anchor, desc, node->nd_recv) ? 0 : -1)
339#define OPERAND_AT(insn, idx) \
340 (((INSN*)(insn))->operands[(idx)])
342#define INSN_OF(insn) \
343 (((INSN*)(insn))->insn_id)
345#define IS_INSN(link) ((link)->type == ISEQ_ELEMENT_INSN)
346#define IS_LABEL(link) ((link)->type == ISEQ_ELEMENT_LABEL)
347#define IS_ADJUST(link) ((link)->type == ISEQ_ELEMENT_ADJUST)
348#define IS_TRACE(link) ((link)->type == ISEQ_ELEMENT_TRACE)
349#define IS_INSN_ID(iobj, insn) (INSN_OF(iobj) == BIN(insn))
350#define IS_NEXT_INSN_ID(link, insn) \
351 ((link)->next && IS_INSN((link)->next) && IS_INSN_ID((link)->next, insn))
355NORETURN(
static void append_compile_error(
const rb_iseq_t *iseq,
int line,
const char *fmt, ...));
359append_compile_error(
const rb_iseq_t *iseq,
int line,
const char *fmt, ...)
361 VALUE err_info = ISEQ_COMPILE_DATA(iseq)->err_info;
369 if (
NIL_P(err_info)) {
373 else if (!err_info) {
384compile_bug(
rb_iseq_t *iseq,
int line,
const char *fmt, ...)
394#define COMPILE_ERROR append_compile_error
396#define ERROR_ARGS_AT(n) iseq, nd_line(n),
397#define ERROR_ARGS ERROR_ARGS_AT(node)
399#define EXPECT_NODE(prefix, node, ndtype, errval) \
401 const NODE *error_node = (node); \
402 enum node_type error_type = nd_type(error_node); \
403 if (error_type != (ndtype)) { \
404 COMPILE_ERROR(ERROR_ARGS_AT(error_node) \
405 prefix ": " #ndtype " is expected, but %s", \
406 ruby_node_name(error_type)); \
411#define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval) \
413 COMPILE_ERROR(ERROR_ARGS_AT(parent) \
414 prefix ": must be " #ndtype ", but 0"); \
418#define UNKNOWN_NODE(prefix, node, errval) \
420 const NODE *error_node = (node); \
421 COMPILE_ERROR(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \
422 ruby_node_name(nd_type(error_node))); \
429#define CHECK(sub) if (!(sub)) {BEFORE_RETURN;return COMPILE_NG;}
430#define NO_CHECK(sub) (void)(sub)
435#define DECL_ANCHOR(name) \
436 LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},}}
437#define INIT_ANCHOR(name) \
438 (name->last = &name->anchor)
441freeze_hide_obj(
VALUE obj)
444 RBASIC_CLEAR_CLASS(obj);
448#include "optinsn.inc"
449#if OPT_INSTRUCTIONS_UNIFICATION
450#include "optunifs.inc"
455#define ISEQ_ARG iseq,
456#define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
459#define ISEQ_ARG_DECLARE
463#define gl_node_level ISEQ_COMPILE_DATA(iseq)->node_level
469static int insn_data_length(
INSN *iobj);
470static int calc_sp_depth(
int depth,
INSN *iobj);
472static INSN *new_insn_body(
rb_iseq_t *iseq,
int line_no,
enum ruby_vminsn_type insn_id,
int argc, ...);
484static int iseq_set_local_table(
rb_iseq_t *iseq,
const ID *tbl);
485static int iseq_set_exception_local_table(
rb_iseq_t *iseq);
490static int iseq_set_exception_table(
rb_iseq_t *iseq);
491static int iseq_set_optargs_table(
rb_iseq_t *iseq);
494static int compile_hash(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *node,
int method_call_keywords,
int popped);
512 if (plist != list->
prev) {
519 if (anchor->
last != plist && anchor->
last != 0) {
524 rb_bug(
"list verify error: %08x (%s)", flag, info);
529#define verify_list(info, anchor) verify_list(iseq, (info), (anchor))
540 while (i < iseq->body->iseq_size) {
541 VALUE insn = original[i];
542 const char *
types = insn_op_types(insn);
544 for (
int j=0;
types[j]; j++) {
545 if (
types[j] == TS_CALLDATA) {
551 rb_bug(
"call cache is not initialized by vm_cc_empty()");
558 for (
unsigned int i=0; i<iseq->
body->
ci_size; i++) {
564 rb_bug(
"call cache is not initialized by vm_cc_empty()");
576 elem->
prev = anchor->last;
577 anchor->last->
next = elem;
579 verify_list(
"add", anchor);
592 if (before == anchor->last) anchor->last = elem;
593 verify_list(
"add", anchor);
596#define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem))
597#define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem))
601branch_coverage_valid_p(
rb_iseq_t *iseq,
int first_line)
605 if (first_line <= 0)
return 0;
615 if (!branch_coverage_valid_p(iseq, first_lineno))
return Qundef;
630 if (
NIL_P(branch_base)) {
655 if (!branch_coverage_valid_p(iseq, first_lineno))
return;
690#define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line)
720 (*ifunc->
func)(iseq, ret, ifunc->
data);
722 ADD_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, leave);
724 CHECK(iseq_setup_insn(iseq, ret));
725 return iseq_setup(iseq, ret);
740 iseq_set_local_table(iseq, 0);
745 iseq_set_local_table(iseq, node->nd_tbl);
746 iseq_set_arguments(iseq, ret, node->nd_args);
749 case ISEQ_TYPE_BLOCK:
751 LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label =
NEW_LABEL(0);
770 case ISEQ_TYPE_CLASS:
775 ISEQ_COMPILE_DATA(iseq)->last_line =
nd_line(node);
778 case ISEQ_TYPE_METHOD:
783 ISEQ_COMPILE_DATA(iseq)->last_line =
nd_line(node);
794#define INVALID_ISEQ_TYPE(type) \
795 ISEQ_TYPE_##type: m = #type; goto invalid_iseq_type
803#undef INVALID_ISEQ_TYPE
804 case ISEQ_TYPE_RESCUE:
805 iseq_set_exception_local_table(iseq);
808 case ISEQ_TYPE_ENSURE:
809 iseq_set_exception_local_table(iseq);
812 case ISEQ_TYPE_PLAIN:
824 if (iseq->
body->
type == ISEQ_TYPE_RESCUE || iseq->
body->
type == ISEQ_TYPE_ENSURE) {
829 ADD_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, leave);
833 if (ISEQ_COMPILE_DATA(iseq)->labels_table) {
834 st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
835 ISEQ_COMPILE_DATA(iseq)->labels_table = 0;
836 validate_labels(iseq, labels_table);
839 CHECK(iseq_setup_insn(iseq, ret));
840 return iseq_setup(iseq, ret);
844rb_iseq_translate_threaded_code(
rb_iseq_t *iseq)
846#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
853 int len = insn_len(insn);
854 encoded[i] = (
VALUE)table[insn];
865 VALUE *original_code;
867 if (ISEQ_ORIGINAL_ISEQ(iseq))
return ISEQ_ORIGINAL_ISEQ(iseq);
868 original_code = ISEQ_ORIGINAL_ISEQ_ALLOC(iseq, iseq->
body->
iseq_size);
871#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
876 const void *addr = (
const void *)original_code[i];
879 original_code[i] = insn;
884 return original_code;
897#if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__)
898 #define STRICT_ALIGNMENT
904#if defined(__OpenBSD__)
905 #include <sys/endian.h>
906 #ifdef __STRICT_ALIGNMENT
907 #define STRICT_ALIGNMENT
911#ifdef STRICT_ALIGNMENT
912 #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE
913 #define ALIGNMENT_SIZE SIZEOF_LONG_LONG
915 #define ALIGNMENT_SIZE SIZEOF_VALUE
917 #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1))
918 #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX
921 #define PADDING_SIZE_MAX 0
924#ifdef STRICT_ALIGNMENT
927calc_padding(
void *
ptr,
size_t size)
932 mis = (size_t)
ptr & ALIGNMENT_SIZE_MASK;
934 padding = ALIGNMENT_SIZE - mis;
940#if ALIGNMENT_SIZE > SIZEOF_VALUE
955#ifdef STRICT_ALIGNMENT
956 size_t padding = calc_padding((
void *)&storage->
buff[storage->
pos],
size);
958 const size_t padding = 0;
962 if (storage->
pos +
size + padding > storage->
size) {
963 unsigned int alloc_size = storage->
size;
971 storage = *arena = storage->
next;
974 storage->
size = alloc_size;
975#ifdef STRICT_ALIGNMENT
976 padding = calc_padding((
void *)&storage->
buff[storage->
pos],
size);
980#ifdef STRICT_ALIGNMENT
981 storage->
pos += (
int)padding;
993 return compile_data_alloc_with_arena(arena,
size);
997compile_data_alloc2(
rb_iseq_t *iseq,
size_t x,
size_t y)
1000 return compile_data_alloc(iseq,
size);
1004compile_data_calloc2(
rb_iseq_t *iseq,
size_t x,
size_t y)
1007 void *p = compile_data_alloc(iseq,
size);
1016 return (
INSN *)compile_data_alloc_with_arena(arena,
sizeof(
INSN));
1020compile_data_alloc_label(
rb_iseq_t *iseq)
1022 return (
LABEL *)compile_data_alloc(iseq,
sizeof(
LABEL));
1026compile_data_alloc_adjust(
rb_iseq_t *iseq)
1028 return (
ADJUST *)compile_data_alloc(iseq,
sizeof(
ADJUST));
1032compile_data_alloc_trace(
rb_iseq_t *iseq)
1034 return (
TRACE *)compile_data_alloc(iseq,
sizeof(
TRACE));
1044 elem2->
prev = elem1;
1045 elem1->
next = elem2;
1058 elem2->
next = elem1;
1059 elem1->
prev = elem2;
1099 return anchor->
last;
1106 anchor->last = anchor->last->
prev;
1107 anchor->last->
next = 0;
1108 verify_list(
"pop", anchor);
1112#define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor))
1119 switch (elem->
type) {
1120 case ISEQ_ELEMENT_INSN:
1121 case ISEQ_ELEMENT_ADJUST:
1131LIST_INSN_SIZE_ONE(
const LINK_ANCHOR *
const anchor)
1133 LINK_ELEMENT *first_insn = ELEM_FIRST_INSN(FIRST_ELEMENT(anchor));
1134 if (first_insn !=
NULL &&
1135 ELEM_FIRST_INSN(first_insn->
next) ==
NULL) {
1144LIST_INSN_SIZE_ZERO(
const LINK_ANCHOR *
const anchor)
1146 if (ELEM_FIRST_INSN(FIRST_ELEMENT(anchor)) ==
NULL) {
1167 anc1->last = anc2->
last;
1169 verify_list(
"append", anc1);
1172#define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
1181 printf(
"anch: %p, frst: %p, last: %p\n", &anchor->anchor,
1182 anchor->anchor.next, anchor->last);
1184 printf(
"curr: %p, next: %p, prev: %p, type: %d\n", list, list->
next,
1190 dump_disasm_list_with_cursor(anchor->anchor.next, cur, 0);
1191 verify_list(
"debug list", anchor);
1194#define debug_list(anc, cur) debug_list(iseq, (anc), (cur))
1197#define debug_list(anc, cur) ((void)0)
1203 TRACE *trace = compile_data_alloc_trace(iseq);
1205 trace->
link.
type = ISEQ_ELEMENT_TRACE;
1207 trace->
event = event;
1214new_label_body(
rb_iseq_t *iseq,
long line)
1216 LABEL *labelobj = compile_data_alloc_label(iseq);
1218 labelobj->
link.
type = ISEQ_ELEMENT_LABEL;
1221 labelobj->
label_no = ISEQ_COMPILE_DATA(iseq)->label_no++;
1234 ADJUST *adjust = compile_data_alloc_adjust(iseq);
1235 adjust->
link.
type = ISEQ_ELEMENT_ADJUST;
1237 adjust->
label = label;
1244new_insn_core(
rb_iseq_t *iseq,
int line_no,
1247 INSN *iobj = compile_data_alloc_insn(iseq);
1251 iobj->
link.
type = ISEQ_ELEMENT_INSN;
1263new_insn_body(
rb_iseq_t *iseq,
int line_no,
enum ruby_vminsn_type insn_id,
int argc, ...)
1265 VALUE *operands = 0;
1270 operands = compile_data_alloc2(iseq,
sizeof(
VALUE),
argc);
1271 for (i = 0; i <
argc; i++) {
1277 return new_insn_core(iseq, line_no, insn_id,
argc, operands);
1286 kw_arg ==
NULL && !has_blockiseq) {
1305 VALUE *operands = compile_data_calloc2(iseq,
sizeof(
VALUE), 2);
1308 operands[1] = (
VALUE)blockiseq;
1312 INSN *insn = new_insn_core(iseq, line_no, BIN(send), 2, operands);
1329 debugs(
"[new_child_iseq]> ---------------------------------------\n");
1330 int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
1334 isolated_depth ? isolated_depth + 1 : 0,
1335 type, ISEQ_COMPILE_DATA(iseq)->option);
1336 debugs(
"[new_child_iseq]< ---------------------------------------\n");
1346 debugs(
"[new_child_iseq_with_callback]> ---------------------------------------\n");
1349 INT2FIX(line_no), parent,
type, ISEQ_COMPILE_DATA(iseq)->option);
1350 debugs(
"[new_child_iseq_with_callback]< ---------------------------------------\n");
1376 const struct iseq_catch_table *ct = body->
catch_table;
1381 while (pos < body->iseq_size) {
1382#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
1387 if (insn == BIN(
throw)) {
1388 set_catch_except_p(body);
1391 pos += insn_len(insn);
1397 for (i = 0; i < ct->size; i++) {
1412 VALUE catch_table_ary = ISEQ_COMPILE_DATA(
iseq)->catch_table_ary;
1413 if (
NIL_P(catch_table_ary))
return;
1414 unsigned int i, tlen = (
unsigned int)
RARRAY_LEN(catch_table_ary);
1416 for (i = 0; i < tlen; i++) {
1423 INSN *nop = new_insn_core(
iseq, 0, BIN(nop), 0, 0);
1424 ELEM_INSERT_NEXT(
end, &nop->
link);
1434 if (
RTEST(ISEQ_COMPILE_DATA(
iseq)->err_info))
1440 dump_disasm_list(FIRST_ELEMENT(anchor));
1442 debugs(
"[compile step 3.1 (iseq_optimize)]\n");
1443 iseq_optimize(
iseq, anchor);
1446 dump_disasm_list(FIRST_ELEMENT(anchor));
1448 if (ISEQ_COMPILE_DATA(
iseq)->option->instructions_unification) {
1449 debugs(
"[compile step 3.2 (iseq_insns_unification)]\n");
1450 iseq_insns_unification(
iseq, anchor);
1452 dump_disasm_list(FIRST_ELEMENT(anchor));
1455 if (ISEQ_COMPILE_DATA(
iseq)->option->stack_caching) {
1456 debugs(
"[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
1457 iseq_set_sequence_stackcaching(
iseq, anchor);
1459 dump_disasm_list(FIRST_ELEMENT(anchor));
1462 debugs(
"[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n");
1463 iseq_insert_nop_between_end_and_cont(
iseq);
1465 dump_disasm_list(FIRST_ELEMENT(anchor));
1473 if (
RTEST(ISEQ_COMPILE_DATA(
iseq)->err_info))
1476 debugs(
"[compile step 4.1 (iseq_set_sequence)]\n");
1479 dump_disasm_list(FIRST_ELEMENT(anchor));
1481 debugs(
"[compile step 4.2 (iseq_set_exception_table)]\n");
1484 debugs(
"[compile step 4.3 (set_optargs_table)] \n");
1487 debugs(
"[compile step 5 (iseq_translate_threaded_code)] \n");
1490 debugs(
"[compile step 6 (update_catch_except_flags)] \n");
1491 update_catch_except_flags(
iseq->
body);
1493#if VM_INSN_INFO_TABLE_IMPL == 2
1495 debugs(
"[compile step 7 (rb_iseq_insns_info_encode_positions)] \n");
1504 verify_call_cache(
iseq);
1505 debugs(
"[compile step: finish]\n");
1549 "get_local_var_idx: %d", idx);
1558 int lv = 0, idx = -1;
1562 idx = get_dyna_var_idx_at_raw(
iseq,
id);
1572 "get_dyna_var_idx: -1");
1581iseq_local_block_param_p(
const rb_iseq_t *
iseq,
unsigned int idx,
unsigned int level)
1600iseq_block_param_id_p(
const rb_iseq_t *iseq,
ID id,
int *pidx,
int *plevel)
1603 int idx = get_dyna_var_idx(iseq,
id, &level, &ls);
1604 if (iseq_local_block_param_p(iseq, ls - idx, level)) {
1617 int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
1619 if (isolated_depth && level >= isolated_depth) {
1628 for (
int i=0; i<level; i++) {
1637 if (
write && !val) {
1650iseq_lvar_id(
const rb_iseq_t *iseq,
int idx,
int level)
1652 for (
int i=0; i<level; i++) {
1664 if (iseq_local_block_param_p(iseq, idx, level)) {
1670 if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level),
Qfalse);
1676 if (iseq_local_block_param_p(iseq, idx, level)) {
1682 if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level),
Qtrue);
1731 struct rb_iseq_param_keyword *keyword;
1734 int kw = 0, rkw = 0, di = 0, i;
1741 node = node->nd_next;
1744 keyword->bits_start = arg_size++;
1748 const NODE *val_node = node->nd_body->nd_value;
1757 dv = val_node->nd_lit;
1773 keyword->num = ++di;
1777 node = node->nd_next;
1783 keyword->rest_start = arg_size++;
1786 keyword->required_num = rkw;
1787 keyword->table = &body->
local_table[keyword->bits_start - keyword->num];
1792 for (i = 0; i <
RARRAY_LEN(default_values); i++) {
1794 if (dv == complex_mark) dv =
Qundef;
1801 keyword->default_values = dvs;
1809 debugs(
"iseq_set_arguments: %s\n", node_args ?
"" :
"0");
1845 node = node->nd_next;
1857 for (j = 0; j < i+1; j++) {
1886 arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size);
1889 struct rb_iseq_param_keyword *keyword =
ZALLOC_N(
struct rb_iseq_param_keyword, 1);
1890 keyword->rest_start = arg_size++;
1903 iseq_calc_param_size(iseq);
1913 if (body->
type == ISEQ_TYPE_BLOCK) {
1932iseq_set_local_table(
rb_iseq_t *iseq,
const ID *tbl)
1969 else if (tlit != tval) {
1992 return cdhash_cmp(rat1->
num, rat2->
num) || cdhash_cmp(rat1->
den, rat2->
den);
1997 return cdhash_cmp(comp1->
real, comp2->
real) || cdhash_cmp(comp1->
imag, comp2->
imag);
2051 struct rb_id_table *tbl = ISEQ_COMPILE_DATA(iseq)->ivar_cache_table;
2059 ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
2066#define BADINSN_DUMP(anchor, list, dest) \
2067 dump_disasm_list_with_cursor(FIRST_ELEMENT(anchor), list, dest)
2069#define BADINSN_ERROR \
2070 (xfree(generated_iseq), \
2071 xfree(insns_info), \
2072 BADINSN_DUMP(anchor, list, NULL), \
2078 int stack_max = 0, sp = 0, line = 0;
2081 for (list = FIRST_ELEMENT(anchor); list; list = list->
next) {
2082 if (list->
type == ISEQ_ELEMENT_LABEL) {
2088 for (list = FIRST_ELEMENT(anchor); list; list = list->
next) {
2089 switch (list->
type) {
2090 case ISEQ_ELEMENT_INSN:
2098 sp = calc_sp_depth(sp, iobj);
2102 "argument stack underflow (%d)", sp);
2105 if (sp > stack_max) {
2113 types = insn_op_types(insn);
2114 len = insn_len(insn);
2121 "operand size miss! (%d for %d)",
2126 for (j = 0;
types[j]; j++) {
2127 if (
types[j] == TS_OFFSET) {
2136 if (lobj->
sp == -1) {
2138 }
else if (lobj->
sp != sp) {
2139 debugs(
"%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n",
2147 case ISEQ_ELEMENT_LABEL:
2150 if (lobj->
sp == -1) {
2154 if (lobj->
sp != sp) {
2155 debugs(
"%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n",
2163 case ISEQ_ELEMENT_TRACE:
2168 case ISEQ_ELEMENT_ADJUST:
2174 if (adjust->
line_no != -1 && orig_sp - sp < 0) {
2177 "iseq_set_sequence: adjust bug %d < %d",
2194 int insns_info_index,
int code_index,
const INSN *iobj)
2196 if (insns_info_index == 0 ||
2201 positions[insns_info_index] = code_index;
2209 int insns_info_index,
int code_index,
const ADJUST *adjust)
2211 if (insns_info_index > 0 ||
2212 insns_info[insns_info_index-1].line_no != adjust->
line_no) {
2214 insns_info[insns_info_index].
events = 0;
2215 positions[insns_info_index] = code_index;
2230 unsigned int *positions;
2232 VALUE *generated_iseq;
2236 int insn_num, code_index, insns_info_index, sp = 0;
2237 int stack_max = fix_sp_depth(iseq, anchor);
2242 insn_num = code_index = 0;
2243 for (list = FIRST_ELEMENT(anchor); list; list = list->
next) {
2244 switch (list->
type) {
2245 case ISEQ_ELEMENT_INSN:
2249 sp = calc_sp_depth(sp, iobj);
2267 code_index += insn_data_length(iobj);
2272 case ISEQ_ELEMENT_LABEL:
2276 if (lobj->
sp != sp) {
2277 debugs(
"%s: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n",
2284 case ISEQ_ELEMENT_TRACE:
2287 events |= trace->
event;
2291 case ISEQ_ELEMENT_ADJUST:
2297 if (orig_sp - sp > 0) {
2298 if (orig_sp - sp > 1) code_index++;
2312 positions =
ALLOC_N(
unsigned int, insn_num);
2315 ISEQ_COMPILE_DATA(iseq)->ci_index = 0;
2317 list = FIRST_ELEMENT(anchor);
2318 insns_info_index = code_index = sp = 0;
2321 switch (list->
type) {
2322 case ISEQ_ELEMENT_INSN:
2330 sp = calc_sp_depth(sp, iobj);
2334 generated_iseq[code_index] = insn;
2335 types = insn_op_types(insn);
2336 len = insn_len(insn);
2338 for (j = 0;
types[j]; j++) {
2346 generated_iseq[code_index + 1 + j] = lobj->
position - (code_index +
len);
2354 data.pos = code_index;
2359 freeze_hide_obj(
map);
2360 generated_iseq[code_index + 1 + j] =
map;
2367 generated_iseq[code_index + 1 + j] =
FIX2INT(operands[j]);
2372 VALUE v = operands[j];
2373 generated_iseq[code_index + 1 + j] = v;
2385 unsigned int ic_index =
FIX2UINT(operands[j]);
2390 "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
2393 generated_iseq[code_index + 1 + j] = (
VALUE)ic;
2401 assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size);
2404 generated_iseq[code_index + 1 + j] = (
VALUE)cd;
2408 generated_iseq[code_index + 1 + j] =
SYM2ID(operands[j]);
2411 generated_iseq[code_index + 1 + j] = operands[j];
2414 generated_iseq[code_index + 1 + j] = operands[j];
2418 "unknown operand type: %c",
type);
2422 if (add_insn_info(insns_info, positions, insns_info_index, code_index, iobj)) insns_info_index++;
2426 case ISEQ_ELEMENT_LABEL:
2429 if (lobj->
sp != sp) {
2430 debugs(
"%s: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n",
2437 case ISEQ_ELEMENT_ADJUST:
2442 if (adjust->
label) {
2450 const int diff = orig_sp - sp;
2452 if (add_adjust_info(insns_info, positions, insns_info_index, code_index, adjust)) insns_info_index++;
2455 generated_iseq[code_index++] = BIN(adjuststack);
2456 generated_iseq[code_index++] = orig_sp - sp;
2458 else if (diff == 1) {
2459 generated_iseq[code_index++] = BIN(pop);
2461 else if (diff < 0) {
2463 xfree(generated_iseq);
2468 "iseq_set_sequence: adjust bug to %d %d < %d",
2469 label_no, orig_sp, sp);
2492 REALLOC_N(positions,
unsigned int, insns_info_index);
2500label_get_position(
LABEL *lobj)
2506label_get_sp(
LABEL *lobj)
2512iseq_set_exception_table(
rb_iseq_t *iseq)
2515 unsigned int tlen, i;
2524 struct iseq_catch_table *table =
xmalloc(iseq_catch_table_bytes(tlen));
2527 for (i = 0; i < table->size; i++) {
2530 entry->
type = (
enum catch_type)(
ptr[0] & 0xffff);
2532 entry->
end = label_get_position((
LABEL *)(
ptr[2] & ~1));
2539 entry->
cont = label_get_position(lobj);
2540 entry->
sp = label_get_sp(lobj);
2543 if (entry->
type == CATCH_TYPE_RESCUE ||
2544 entry->
type == CATCH_TYPE_BREAK ||
2545 entry->
type == CATCH_TYPE_NEXT) {
2554 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0);
2577 opt_table[i] = label_get_position((
LABEL *)opt_table[i]);
2584get_destination_insn(
INSN *iobj)
2592 switch (list->
type) {
2593 case ISEQ_ELEMENT_INSN:
2594 case ISEQ_ELEMENT_ADJUST:
2596 case ISEQ_ELEMENT_LABEL:
2599 case ISEQ_ELEMENT_TRACE:
2602 events |= trace->
event;
2618get_next_insn(
INSN *iobj)
2632get_prev_insn(
INSN *iobj)
2646unref_destination(
INSN *iobj,
int pos)
2654replace_destination(
INSN *dobj,
INSN *nobj)
2666find_destination(
INSN *i)
2669 for (pos = 0; pos <
len; ++pos) {
2670 if (insn_op_types(i->
insn_id)[pos] == TS_OFFSET) {
2681 int *unref_counts = 0, nlabels = ISEQ_COMPILE_DATA(iseq)->label_no;
2684 unref_counts =
ALLOCA_N(
int, nlabels);
2685 MEMZERO(unref_counts,
int, nlabels);
2694 else if ((lab = find_destination((
INSN *)i)) != 0) {
2703 if (i == first)
return 0;
2716 }
while ((i = i->next) != 0);
2722 int pos,
len = insn_len(insn);
2723 for (pos = 0; pos <
len; ++pos) {
2724 switch (insn_op_types(insn)[pos]) {
2726 unref_destination((
INSN *)i, pos);
2735 }
while ((i != end) && (i = i->next) != 0);
2744 ELEM_REMOVE(&iobj->
link);
2747 ELEM_REMOVE(&iobj->
link);
2750 iobj->
insn_id = BIN(adjuststack);
2756is_frozen_putstring(
INSN *insn,
VALUE *op)
2794 INSN *niobj, *ciobj, *dup = 0;
2799 case BIN(putstring):
2805 case BIN(putobject):
2808 default:
return FALSE;
2811 ciobj = (
INSN *)get_next_insn(iobj);
2816 ciobj = (
INSN *)get_next_insn(dup = ciobj);
2819 niobj = (
INSN *)get_next_insn(ciobj);
2830 case BIN(branchunless):
2845 ELEM_INSERT_NEXT(&niobj->
link, &dest->
link);
2858 vm_ci_flag(ci) |
add,
2882 optimize_checktype(iseq, iobj);
2885 INSN *niobj, *diobj, *piobj;
2886 diobj = (
INSN *)get_destination_insn(iobj);
2887 niobj = (
INSN *)get_next_insn(iobj);
2889 if (diobj == niobj) {
2896 unref_destination(iobj, 0);
2897 ELEM_REMOVE(&iobj->
link);
2900 else if (iobj != diobj &&
IS_INSN(&diobj->
link) &&
2914 replace_destination(iobj, diobj);
2915 remove_unreachable_chunk(iseq, iobj->
link.
next);
2931 unref_destination(iobj, 0);
2941 INSN *pdiobj = (
INSN *)get_destination_insn(piobj);
2942 if (niobj == pdiobj) {
2960 ? BIN(branchunless) : BIN(branchif);
2961 replace_destination(piobj, iobj);
2963 ELEM_REMOVE(&iobj->
link);
2970 else if (diobj == pdiobj) {
2986 ELEM_REPLACE(&piobj->
link, &popiobj->
link);
2989 if (remove_unreachable_chunk(iseq, iobj->
link.
next)) {
3006 VALUE str_beg, str_end;
3009 (end = (
INSN *)get_prev_insn(
range)) != 0 &&
3010 is_frozen_putstring(end, &str_end) &&
3011 (beg = (
INSN *)get_prev_insn(end)) != 0 &&
3012 is_frozen_putstring(beg, &str_beg)) {
3016 ELEM_REMOVE(&beg->
link);
3017 ELEM_REMOVE(&end->
link);
3018 range->insn_id = BIN(putobject);
3025 remove_unreachable_chunk(iseq, iobj->
link.
next);
3039 INSN *nobj = (
INSN *)get_destination_insn(iobj);
3061 int stop_optimization =
3064 if (!stop_optimization) {
3076 replace_destination(iobj, nobj);
3078 else if (prev_dup &&
IS_INSN_ID(nobj, dup) &&
3097 replace_destination(iobj, nobj);
3144 if (prev_dup || !
IS_INSN_ID(pobj, newarray)) {
3147 else if (!iseq_pop_newarray(iseq, pobj)) {
3149 ELEM_INSERT_PREV(&iobj->
link, &pobj->
link);
3154 ELEM_INSERT_NEXT(&iobj->
link, &pobj->
link);
3160 unref_destination(iobj, 0);
3161 ELEM_REMOVE(&iobj->
link);
3166 nobj = (
INSN *)get_destination_insn(nobj);
3180 enum ruby_vminsn_type previ = ((
INSN *)prev)->insn_id;
3181 if (previ == BIN(putobject) || previ == BIN(putnil) ||
3182 previ == BIN(putself) || previ == BIN(putstring) ||
3183 previ == BIN(dup) ||
3184 previ == BIN(getlocal) ||
3185 previ == BIN(getblockparam) ||
3186 previ == BIN(getblockparamproxy) ||
3188 previ == BIN(duparray)) {
3192 ELEM_REMOVE(&iobj->
link);
3194 else if (previ == BIN(newarray) && iseq_pop_newarray(iseq, (
INSN*)prev)) {
3195 ELEM_REMOVE(&iobj->
link);
3197 else if (previ == BIN(concatarray)) {
3202 else if (previ == BIN(concatstrings)) {
3207 ELEM_REMOVE(&iobj->
link);
3208 INSN_OF(prev) = BIN(adjuststack);
3260 ELEM_REMOVE(&next->
link);
3262 ELEM_REMOVE(&iobj->
link);
3276 next = get_destination_insn(jump = (
INSN *)next);
3283 ELEM_REMOVE(&label->
link);
3290 ELEM_INSERT_NEXT(next, &label->
link);
3291 CHECK(iseq_peephole_optimize(iseq, get_next_insn(jump), do_tailcallopt));
3299 if (do_tailcallopt &&
3328 next = get_destination_insn((
INSN *)next);
3366 ELEM_REMOVE(&iobj->
link);
3374 ELEM_REMOVE(set1->
next);
3384 niobj = niobj->
next;
3396 if (
IS_INSN_ID(iobj, opt_invokebuiltin_delegate)) {
3399 iobj->
insn_id = BIN(opt_invokebuiltin_delegate_leave);
3408insn_set_specialized_instruction(
rb_iseq_t *iseq,
INSN *iobj,
int insn_id)
3413 if (insn_id == BIN(opt_neq)) {
3418 iobj->
operands[1] = old_operands[0];
3436 switch (vm_ci_mid(ci)) {
3438 iobj->
insn_id = BIN(opt_newarray_max);
3439 ELEM_REMOVE(&niobj->
link);
3442 iobj->
insn_id = BIN(opt_newarray_min);
3443 ELEM_REMOVE(&niobj->
link);
3454#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
3456 switch (vm_ci_argc(ci)) {
3458 switch (vm_ci_mid(ci)) {
3468 switch (vm_ci_mid(ci)) {
3488 switch (vm_ci_mid(ci)) {
3496 iobj->
insn_id = BIN(opt_send_without_block);
3510 case ISEQ_TYPE_EVAL:
3511 case ISEQ_TYPE_MAIN:
3513 case ISEQ_TYPE_RESCUE:
3514 case ISEQ_TYPE_ENSURE:
3526 const int do_peepholeopt = ISEQ_COMPILE_DATA(iseq)->option->peephole_optimization;
3527 const int do_tailcallopt = tailcallable_p(iseq) &&
3528 ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization;
3529 const int do_si = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction;
3530 const int do_ou = ISEQ_COMPILE_DATA(iseq)->option->operands_unification;
3531 int rescue_level = 0;
3532 int tailcallopt = do_tailcallopt;
3534 list = FIRST_ELEMENT(anchor);
3538 if (do_peepholeopt) {
3539 iseq_peephole_optimize(iseq, list, tailcallopt);
3542 iseq_specialized_instruction(iseq, (
INSN *)list);
3545 insn_operands_unification((
INSN *)list);
3549 switch (((
LABEL *)list)->rescued) {
3552 tailcallopt =
FALSE;
3555 if (!--rescue_level) tailcallopt = do_tailcallopt;
3564#if OPT_INSTRUCTIONS_UNIFICATION
3576 for (i = 0; i <
size; i++) {
3577 iobj = (
INSN *)list;
3583 ptr = operands = compile_data_alloc2(iseq,
sizeof(
VALUE),
argc);
3588 for (i = 0; i <
size; i++) {
3589 iobj = (
INSN *)list;
3607#if OPT_INSTRUCTIONS_UNIFICATION
3613 list = FIRST_ELEMENT(anchor);
3616 iobj = (
INSN *)list;
3618 if (unified_insns_data[
id] != 0) {
3619 const int *
const *entry = unified_insns_data[
id];
3620 for (j = 1; j < (
intptr_t)entry[0]; j++) {
3621 const int *unified = entry[j];
3623 for (k = 2; k < unified[1]; k++) {
3625 ((
INSN *)li)->insn_id != unified[k]) {
3632 new_unified_insn(iseq, unified[0], unified[1] - 1,
3655#if OPT_STACK_CACHING
3657#define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
3658#define SC_NEXT(insn) sc_insn_next[(insn)]
3660#include "opt_sc.inc"
3670 nstate = SC_NEXT(iobj->
insn_id);
3672 if (insn_id == BIN(jump) ||
3673 insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
3689 if (insn_id == BIN(jump)) {
3693 else if (insn_id == BIN(leave)) {
3721#if OPT_STACK_CACHING
3727 list = FIRST_ELEMENT(anchor);
3733 switch (list->
type) {
3734 case ISEQ_ELEMENT_INSN:
3745 if (
state != SCS_AX) {
3747 new_insn_body(iseq, 0, BIN(reput), 0);
3796 state = insn_set_sc_state(iseq, anchor, iobj,
state);
3799 case ISEQ_ELEMENT_LABEL:
3802 lobj = (
LABEL *)list;
3816all_string_result_p(
const NODE *node)
3818 if (!node)
return FALSE;
3823 if (!node->nd_body || !node->nd_else)
return FALSE;
3824 if (all_string_result_p(node->nd_body))
3825 return all_string_result_p(node->nd_else);
3829 return all_string_result_p(node->nd_1st);
3830 if (!all_string_result_p(node->nd_1st))
3832 return all_string_result_p(node->nd_2nd);
3841 const NODE *list = node->nd_next;
3842 VALUE lit = node->nd_lit;
3857 if (
RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
3861 const NODE *
const head = list->nd_head;
3872 list = list->nd_next;
3874 if (
NIL_P(lit) && first_lit) {
3875 ELEM_REMOVE(first_lit);
3887 if (!node->nd_next) {
3894 CHECK(compile_dstr_fragments(iseq, ret, node, &
cnt));
3904 CHECK(compile_dstr_fragments(iseq, ret, node, &
cnt));
3913 const int line =
nd_line(node);
3924 ADD_INSNL(ret, line, branchunless, else_label);
3934 ADD_INSNL(ret, line, branchunless, then_label);
3951 CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label,
3958 cond = cond->nd_2nd;
3964 CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label,
3971 cond = cond->nd_2nd;
3995 CHECK(compile_flip_flop(iseq, ret, cond,
TRUE, then_label, else_label));
3998 CHECK(compile_flip_flop(iseq, ret, cond,
FALSE, then_label, else_label));
4001 CHECK(compile_defined_expr(iseq, ret, cond,
Qfalse));
4016keyword_node_p(
const NODE *
const node)
4023 const NODE *
const root_node,
4030 const NODE *node = root_node->nd_head;
4034 const NODE *key_node = node->nd_head;
4044 if (seen_nodes > 1 || node->nd_next->nd_next) {
4054 node = node->nd_next;
4055 node = node->nd_next;
4059 node = root_node->nd_head;
4061 int len = (
int)node->nd_alen / 2;
4068 *kw_arg_ptr = kw_arg;
4070 for (i=0; node !=
NULL; i++, node = node->nd_next->nd_next) {
4071 const NODE *key_node = node->nd_head;
4072 const NODE *val_node = node->nd_next->nd_head;
4089 for (; node;
len++, node = node->nd_next) {
4094 if (node->nd_next ==
NULL && keyword_node_p(node->nd_head)) {
4095 if (compile_keyword_arg(iseq, ret, node->nd_head, keywords_ptr, flag)) {
4099 compile_hash(iseq, ret, node->nd_head,
TRUE,
FALSE);
4111static_literal_node_p(
const NODE *node,
const rb_iseq_t *iseq)
4113 node = node->nd_head;
4121 return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal;
4130 node = node->nd_head;
4139 if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal ||
RTEST(
ruby_debug)) {
4150 return node->nd_lit;
4169 for (; node; node = node->nd_next) {
4212 const int max_stack_len = 0x100;
4213 const int min_tmp_ary_len = 0x40;
4215 int first_chunk = 1;
4218#define FLUSH_CHUNK(newarrayinsn) \
4220 ADD_INSN1(ret, line, newarrayinsn, INT2FIX(stack_len)); \
4221 if (!first_chunk) ADD_INSN(ret, line, concatarray); \
4222 first_chunk = stack_len = 0; \
4229 if (static_literal_node_p(node, iseq)) {
4231 const NODE *node_tmp = node->nd_next;
4232 for (; node_tmp && static_literal_node_p(node_tmp, iseq); node_tmp = node_tmp->nd_next)
4235 if ((first_chunk && stack_len == 0 && !node_tmp) ||
count >= min_tmp_ary_len) {
4241 rb_ary_push(ary, static_literal_value(node, iseq));
4259 for (;
count;
count--, node = node->nd_next) {
4267 if (!node->nd_next && keyword_node_p(node->nd_head)) {
4274 if (stack_len >= max_stack_len)
FLUSH_CHUNK(newarray);
4284static_literal_node_pair_p(
const NODE *node,
const rb_iseq_t *iseq)
4286 return node->nd_head && static_literal_node_p(node, iseq) && static_literal_node_p(node->nd_next, iseq);
4294 node = node->nd_head;
4306 for (; node; node = node->nd_next) {
4330 const int max_stack_len = 0x100;
4331 const int min_tmp_hash_len = 0x800;
4333 int first_chunk = 1;
4338#define FLUSH_CHUNK() \
4340 if (first_chunk) { \
4341 APPEND_LIST(ret, anchor); \
4342 ADD_INSN1(ret, line, newhash, INT2FIX(stack_len)); \
4345 ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \
4346 ADD_INSN(ret, line, swap); \
4347 APPEND_LIST(ret, anchor); \
4348 ADD_SEND(ret, line, id_core_hash_merge_ptr, INT2FIX(stack_len + 1)); \
4350 INIT_ANCHOR(anchor); \
4351 first_chunk = stack_len = 0; \
4358 if (static_literal_node_pair_p(node, iseq)) {
4360 const NODE *node_tmp = node->nd_next->nd_next;
4361 for (; node_tmp && static_literal_node_pair_p(node_tmp, iseq); node_tmp = node_tmp->nd_next->nd_next)
4364 if ((first_chunk && stack_len == 0 && !node_tmp) ||
count >= min_tmp_hash_len) {
4369 for (;
count;
count--, node = node->nd_next->nd_next) {
4371 elem[0] = static_literal_value(node, iseq);
4372 elem[1] = static_literal_value(node->nd_next, iseq);
4399 for (;
count;
count--, node = node->nd_next->nd_next) {
4405 if (node->nd_head) {
4408 NO_CHECK(
COMPILE_(anchor,
"hash value element", node->nd_next->nd_head, 0));
4418 const NODE *kw = node->nd_next->nd_head;
4420 int first_kw = first_chunk && stack_len == 0;
4421 int last_kw = !node->nd_next->nd_next;
4422 int only_kw = last_kw && first_kw;
4425 if (only_kw && method_call_keywords) {
4435 else if (first_kw) {
4446 if (only_kw && method_call_keywords) {
4484 VALUE v = node->nd_lit;
4509 LABEL *l1,
int only_special_literals,
VALUE literals)
4512 const NODE *val = vals->nd_head;
4516 only_special_literals = 0;
4531 if (!
COMPILE(cond_seq,
"when cond", val))
return -1;
4536 vals = vals->nd_next;
4538 return only_special_literals;
4543 LABEL *l1,
int only_special_literals,
VALUE literals)
4545 const int line =
nd_line(vals);
4549 if (when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals) < 0)
4557 ADD_INSNL(cond_seq, line, branchif, l1);
4560 CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
4561 CHECK(when_splat_vals(iseq, cond_seq, vals->nd_body, l1, only_special_literals, literals));
4564 CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
4566 CHECK(
COMPILE(cond_seq,
"when argspush body", vals->nd_body));
4568 ADD_INSNL(cond_seq, line, branchif, l1);
4575 ADD_INSNL(cond_seq, line, branchif, l1);
4593 iobj = (
INSN *)get_prev_insn((
INSN *)LAST_ELEMENT(ret));
4595 int argc = vm_ci_argc(ci) + 1;
4596 ci = ci_argc_set(iseq, ci,
argc);
4603 int argc = vm_ci_argc(ci);
4604 ci = ci_argc_set(iseq, ci,
argc - 1);
4617 ELEM_REMOVE(FIRST_ELEMENT(anchor));
4625 ELEM_REMOVE(FIRST_ELEMENT(anchor));
4637 CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next));
4638 CHECK(compile_massign_lhs(iseq, ret, lhsn->nd_head));
4645 const NODE *rhsn,
const NODE *orig_lhsn)
4650 int llen = 0, rlen = 0;
4652 const NODE *lhsn = orig_lhsn;
4654#define MEMORY(v) { \
4656 if (memindex == memsize) return 0; \
4657 for (i=0; i<memindex; i++) { \
4658 if (mem[i] == (v)) return 0; \
4660 mem[memindex++] = (v); \
4668 const NODE *ln = lhsn->nd_head;
4682 lhsn = lhsn->nd_next;
4693 rhsn = rhsn->nd_next;
4698 for (i=0; i<llen-rlen; i++) {
4703 compile_massign_opt_lhs(iseq, ret, orig_lhsn);
4711 do {
ADD_INSN(ret, line, putnil);}
while (++rlen < llen);
4713 else if (rlen > llen) {
4714 do {
ADD_INSN(ret, line, pop);}
while (--rlen > llen);
4721 const NODE *rhsn = node->nd_value;
4722 const NODE *splatn = node->nd_args;
4723 const NODE *lhsn = node->nd_head;
4726 if (!popped || splatn || !compile_massign_opt(iseq, ret, rhsn, lhsn)) {
4734 CHECK(compile_massign_lhs(iseq, lhsseq, lhsn->nd_head));
4736 lhsn = lhsn->nd_next;
4744 else if (!lhs_splat) {
4748 last->operand_size == 1) {
4753 adjust_stack(iseq, ret,
nd_line(node), rlen, llen);
4757 else if (llen > 2 && llen != rlen) {
4759 adjust_stack(iseq, ret,
nd_line(node), rlen, llen);
4763 else if (llen > 2) {
4764 last->insn_id = BIN(reverse);
4778 const NODE *postn = splatn->nd_2nd;
4779 const NODE *restn = splatn->nd_1st;
4780 int num = (
int)postn->nd_alen;
4787 CHECK(compile_massign_lhs(iseq, ret, restn));
4790 CHECK(compile_massign_lhs(iseq, ret, postn->nd_head));
4791 postn = postn->nd_next;
4796 CHECK(compile_massign_lhs(iseq, ret, splatn));
4804compile_const_prefix(
rb_iseq_t *iseq,
const NODE *
const node,
4809 debugi(
"compile_const_prefix - colon", node->nd_vid);
4814 debugi(
"compile_const_prefix - colon3", node->nd_mid);
4821 CHECK(compile_const_prefix(iseq, node->nd_head, pref, body));
4822 debugi(
"compile_const_prefix - colon2", node->nd_mid);
4841 else if (cpath->nd_head) {
4855private_recv_p(
const NODE *node)
4858 NODE *self = node->nd_recv;
4859 return self->nd_state != 0;
4874 const int line =
nd_line(node);
4893 const NODE *vals = node;
4896 defined_expr0(iseq, ret, vals->nd_head, lfinish,
Qfalse);
4901 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4902 }
while ((vals = vals->nd_next) !=
NULL);
4923 ID2SYM(node->nd_vid), needstr);
4929 ID2SYM(node->nd_entry), needstr);
4935 ID2SYM(node->nd_vid), needstr);
4941 ID2SYM(node->nd_vid), needstr);
4947 defined_expr0(iseq, ret, node->nd_head, lfinish,
Qfalse);
4948 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4954 ID2SYM(node->nd_mid), needstr);
4968 const int explicit_receiver =
4972 if (!lfinish[1] && (node->nd_args || explicit_receiver)) {
4975 if (node->nd_args) {
4976 defined_expr0(iseq, ret, node->nd_args, lfinish,
Qfalse);
4977 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4979 if (explicit_receiver) {
4980 defined_expr0(iseq, ret, node->nd_recv, lfinish,
Qfalse);
4981 ADD_INSNL(ret, line, branchunless, lfinish[1]);
4984 ID2SYM(node->nd_mid), needstr);
4989 ID2SYM(node->nd_mid), needstr);
5046 iseq_set_exception_local_table(iseq);
5054 defined_expr0(iseq, ret, node, lfinish, needstr);
5061 rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq,
NULL);
5062 rescue = new_child_iseq_with_callback(iseq, ifunc,
5065 iseq, ISEQ_TYPE_RESCUE, 0);
5077 const int line =
nd_line(node);
5078 if (!node->nd_head) {
5087 defined_expr(iseq, ret, node->nd_head, lfinish, needstr);
5089 ELEM_INSERT_NEXT(
last, &new_insn_body(iseq, line, BIN(putnil), 0)->
link);
5100make_name_for_block(
const rb_iseq_t *orig_iseq)
5107 if (iseq->
body->
type == ISEQ_TYPE_BLOCK) {
5128 enl->
prev = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
5130 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl;
5140 while (erange->
next != 0) {
5141 erange = erange->
next;
5145 ne->end = erange->
end;
5146 erange->
end = lstart;
5155 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
5167 add_ensure_range(iseq, enlp->
erange, lstart, lend);
5169 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enlp->
prev;
5182 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = prev_enlp;
5187check_keyword(
const NODE *node)
5192 while (node->nd_next) {
5193 node = node->nd_next;
5195 node = node->nd_head;
5198 return keyword_node_p(node);
5219 int rest_len = compile_args(iseq, args, argn->nd_body,
NULL,
NULL);
5229 if (check_keyword(argn->nd_body))
5250 int len = compile_args(iseq, args, argn, keywords, flag);
5267 unsigned int dup_rest = 1;
5274 if (LIST_INSN_SIZE_ONE(arg_block)) {
5276 if (elem->
type == ISEQ_ELEMENT_INSN) {
5278 if (iobj->
insn_id == BIN(getblockparam)) {
5279 iobj->
insn_id = BIN(getblockparamproxy);
5284 ret = setup_args_core(iseq, args, argn->nd_head, dup_rest, flag, keywords);
5288 ret = setup_args_core(iseq, args, argn, 0, flag, keywords);
5304 iseq_set_local_table(iseq, 0);
5315#if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0)
5321 ADD_INSNL(ret, line, branchunless, fail_label);
5323 for (vars = node; vars; vars = vars->nd_next) {
5325 if (vars->nd_next) {
5334#if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
5335 if (!vars->nd_next && vars == node) {
5356 for (vars = node; vars; vars = vars->nd_next) {
5360 ((
INSN*)
last)->insn_id = BIN(putnil);
5367optimizable_range_item_p(
const NODE *n)
5369 if (!n)
return FALSE;
5384 const NODE *
const node_body =
type ==
NODE_IF ? node->nd_body : node->nd_else;
5385 const NODE *
const node_else =
type ==
NODE_IF ? node->nd_else : node->nd_body;
5387 const int line =
nd_line(node);
5391 LABEL *then_label, *else_label, *end_label;
5404 compile_branch_condition(iseq, cond_seq, node->nd_cond,
5405 then_label, else_label);
5409 catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
5410 if (!then_label->
refcnt) {
5420 catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
5421 if (!else_label->
refcnt) {
5432 branches = decl_branch_base(iseq, node,
type ==
NODE_IF ?
"if" :
"unless");
5435 if (then_label->
refcnt) {
5437 if (else_label->
refcnt) {
5438 add_trace_branch_coverage(
5441 node_body ? node_body : node,
5446 ADD_INSNL(then_seq, line, jump, end_label);
5454 if (else_label->
refcnt) {
5456 if (then_label->
refcnt) {
5457 add_trace_branch_coverage(
5460 node_else ? node_else : node,
5479 const NODE *node = orig_node;
5480 LABEL *endlabel, *elselabel;
5484 int only_special_literals = 1;
5499 branches = decl_branch_base(iseq, node,
"case");
5501 node = node->nd_body;
5517 add_trace_branch_coverage(
5520 node->nd_body ? node->nd_body : node,
5524 CHECK(
COMPILE_(body_seq,
"when body", node->nd_body, popped));
5525 ADD_INSNL(body_seq, line, jump, endlabel);
5527 vals = node->nd_head;
5531 only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
5532 if (only_special_literals < 0)
return COMPILE_NG;
5537 only_special_literals = 0;
5538 CHECK(when_splat_vals(iseq, cond_seq, vals, l1, only_special_literals, literals));
5548 node = node->nd_next;
5559 add_trace_branch_coverage(iseq, cond_seq, node, branch_id,
"else", branches);
5561 ADD_INSNL(cond_seq, line, jump, endlabel);
5564 debugs(
"== else (implicit)\n");
5567 add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id,
"else", branches);
5574 if (only_special_literals && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
5576 ADD_INSN2(ret,
nd_line(orig_node), opt_case_dispatch, literals, elselabel);
5592 const NODE *node = orig_node->nd_body;
5598 branches = decl_branch_base(iseq, orig_node,
"case");
5604 const int line =
nd_line(node);
5607 add_trace_branch_coverage(
5610 node->nd_body ? node->nd_body : node,
5615 ADD_INSNL(body_seq, line, jump, endlabel);
5617 vals = node->nd_head;
5625 val = vals->nd_head;
5628 CHECK(compile_branch_condition(iseq, ret, val, l1, lnext));
5630 vals = vals->nd_next;
5644 node = node->nd_next;
5647 add_trace_branch_coverage(
5650 node ? node : orig_node,
5662static int iseq_compile_pattern_match(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
LABEL *unmatched,
int in_alt_pattern,
int deconstructed_pos);
5667iseq_compile_pattern_each(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
LABEL *matched,
LABEL *unmatched,
int in_alt_pattern,
int deconstructed_pos)
5669 const int line =
nd_line(node);
5730 const int min_argc = pre_args_num + post_args_num;
5734 LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
5744 if (deconstructed_pos) {
5745 deconstructed_pos++;
5749 if (node->nd_pconst) {
5753 ADD_INSNL(ret, line, branchunless, match_failed);
5756 CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, deconstructed_pos));
5762 ADD_INSNL(ret, line, branchunless, match_failed);
5764 for (i = 0; i < pre_args_num; i++) {
5768 CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern,
FALSE));
5769 args = args->nd_next;
5783 CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->
rest_arg, match_failed, in_alt_pattern,
FALSE));
5786 if (post_args_num > 0) {
5798 for (i = 0; i < post_args_num; i++) {
5806 CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern,
FALSE));
5807 args = args->nd_next;
5889 LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
5895 if (node->nd_pconst) {
5899 ADD_INSNL(ret, line, branchunless, match_failed);
5902 CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, deconstructed_pos));
5908 ADD_INSNL(ret, line, branchunless, match_failed);
5931 ADD_INSNL(ret, line, branchunless, find_failed);
5933 for (j = 0; j < args_num; j++) {
5942 CHECK(iseq_compile_pattern_match(iseq, ret,
args->nd_head, next_loop, in_alt_pattern,
FALSE));
5962 ADD_INSNL(ret, line, jump, find_succeeded);
5967 ADD_INSNL(ret, line, jump, while_begin);
5973 ADD_INSNL(ret, line, jump, match_failed);
6059 LABEL *match_failed, *type_error;
6065 if (node->nd_pkwargs && !node->nd_pkwrestarg) {
6066 const NODE *kw_args = node->nd_pkwargs->nd_head;
6070 kw_args = kw_args->nd_next->nd_next;
6074 if (node->nd_pconst) {
6078 ADD_INSNL(ret, line, branchunless, match_failed);
6084 ADD_INSNL(ret, line, branchunless, match_failed);
6097 ADD_INSNL(ret, line, branchunless, type_error);
6099 if (node->nd_pkwrestarg) {
6103 if (node->nd_pkwargs) {
6107 args = node->nd_pkwargs->nd_head;
6112 for (i = 0; i < keys_num; i++) {
6114 NODE *value_node =
args->nd_next->nd_head;
6120 key = key_node->nd_lit;
6125 ADD_INSNL(ret, line, branchunless, match_failed);
6130 CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_alt_pattern,
FALSE));
6139 ADD_INSNL(ret, line, branchunless, match_failed);
6142 if (node->nd_pkwrestarg) {
6146 ADD_INSNL(ret, line, branchunless, match_failed);
6150 CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_pkwrestarg, match_failed, in_alt_pattern,
FALSE));
6192 ADD_INSNL(ret, line, branchif, matched);
6197 ID id = node->nd_vid;
6200 if (in_alt_pattern) {
6216 ID id = node->nd_vid;
6218 idx = get_dyna_var_idx(iseq,
id, &lv, &ls);
6220 if (in_alt_pattern) {
6240 LABEL *match_failed;
6241 match_failed = unmatched;
6242 CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_body, unmatched, in_alt_pattern, deconstructed_pos));
6245 ADD_INSNL(ret, line, branchunless, match_failed);
6248 ADD_INSNL(ret, line, branchif, match_failed);
6255 LABEL *match_failed;
6265 CHECK(iseq_compile_pattern_match(iseq, ret, n->nd_head, match_failed, in_alt_pattern, deconstructed_pos ? deconstructed_pos + 1 :
FALSE));
6266 CHECK(iseq_compile_pattern_each(iseq, ret, n->nd_next->nd_head, matched, match_failed, in_alt_pattern,
FALSE));
6275 LABEL *match_succeeded, *fin;
6280 CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_1st, match_succeeded, fin,
TRUE, deconstructed_pos ? deconstructed_pos + 1 :
FALSE));
6286 CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_2nd, matched, unmatched,
TRUE, deconstructed_pos));
6296iseq_compile_pattern_match(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
LABEL *unmatched,
int in_alt_pattern,
int deconstructed_pos)
6299 CHECK(iseq_compile_pattern_each(iseq, ret, node, fin, unmatched, in_alt_pattern, deconstructed_pos));
6307 const int line =
nd_line(node);
6313 if (deconstructed_pos) {
6316 ADD_INSNL(ret, line, branchnil, deconstruct);
6320 ADD_INSNL(ret, line, branchunless, match_failed);
6325 ADD_INSNL(ret, line, jump, deconstructed);
6328 ADD_INSNL(ret, line, jump, deconstruct);
6337 if (deconstructed_pos) {
6341 ADD_INSNL(ret, line, branchunless, match_failed);
6346 if (deconstructed_pos) {
6352 ADD_INSNL(ret, line, branchunless, type_error);
6353 ADD_INSNL(ret, line, jump, deconstructed);
6363 const NODE *pattern;
6364 const NODE *node = orig_node;
6365 LABEL *endlabel, *elselabel;
6378 branches = decl_branch_base(iseq, node,
"case");
6380 node = node->nd_body;
6404 add_trace_branch_coverage(
6407 node->nd_body ? node->nd_body : node,
6411 CHECK(
COMPILE_(body_seq,
"in body", node->nd_body, popped));
6412 ADD_INSNL(body_seq, line, jump, endlabel);
6414 pattern = node->nd_head;
6416 int pat_line =
nd_line(pattern);
6418 ADD_INSN (cond_seq, pat_line, dup);
6421 CHECK(iseq_compile_pattern_each(iseq, cond_seq, pattern, l1, next_pat,
FALSE, 2));
6430 node = node->nd_next;
6442 add_trace_branch_coverage(iseq, cond_seq, node, branch_id,
"else", branches);
6444 ADD_INSNL(cond_seq, line, jump, endlabel);
6451 debugs(
"== else (implicit)\n");
6453 add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id,
"else", branches);
6482 LABEL *prev_start_label = ISEQ_COMPILE_DATA(iseq)->start_label;
6483 LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label;
6484 LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label;
6485 int prev_loopval_popped = ISEQ_COMPILE_DATA(iseq)->loopval_popped;
6490 LABEL *next_label = ISEQ_COMPILE_DATA(iseq)->start_label =
NEW_LABEL(line);
6491 LABEL *redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label =
NEW_LABEL(line);
6492 LABEL *break_label = ISEQ_COMPILE_DATA(iseq)->end_label =
NEW_LABEL(line);
6499 ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0;
6500 push_ensure_entry(iseq, &enl,
NULL,
NULL);
6502 if (node->nd_state == 1) {
6514 if (tmp_label)
ADD_LABEL(ret, tmp_label);
6517 branches = decl_branch_base(iseq, node,
type ==
NODE_WHILE ?
"while" :
"until");
6518 add_trace_branch_coverage(
6521 node->nd_body ? node->nd_body : node,
6529 compile_branch_condition(iseq, ret, node->nd_cond,
6530 redo_label, end_label);
6534 compile_branch_condition(iseq, ret, node->nd_cond,
6535 end_label, redo_label);
6541 if (node->nd_state ==
Qundef) {
6561 ISEQ_COMPILE_DATA(iseq)->redo_label);
6563 ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label;
6564 ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label;
6565 ISEQ_COMPILE_DATA(iseq)->redo_label = prev_redo_label;
6566 ISEQ_COMPILE_DATA(iseq)->loopval_popped = prev_loopval_popped;
6567 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->prev;
6574 const int line =
nd_line(node);
6575 const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(iseq)->current_block;
6582 CHECK(
COMPILE(ret,
"iter caller (for)", node->nd_iter));
6584 ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
6586 ISEQ_TYPE_BLOCK, line);
6590 ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
6592 ISEQ_TYPE_BLOCK, line);
6601 ISEQ_COMPILE_DATA(iseq)->current_block = prevblock;
6603 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l);
6613 const int line =
nd_line(node);
6614 const NODE *var = node->nd_var;
6622 ADD_INSNL(ret, line, branchunless, not_single);
6630 ADD_INSNL(ret, line, branchunless, not_ary);
6641 const int line =
nd_line(node);
6642 unsigned long throw_flag = 0;
6644 if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
6648 ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
6649 CHECK(
COMPILE_(ret,
"break val (while/until)", node->nd_stts,
6650 ISEQ_COMPILE_DATA(iseq)->loopval_popped));
6651 add_ensure_iseq(ret, iseq, 0);
6652 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
6663 if (!ISEQ_COMPILE_DATA(ip)) {
6668 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6671 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6674 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6684 CHECK(
COMPILE(ret,
"break val (block)", node->nd_stts));
6700 const int line =
nd_line(node);
6701 unsigned long throw_flag = 0;
6703 if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
6705 debugs(
"next in while loop\n");
6707 CHECK(
COMPILE(ret,
"next val/valid syntax?", node->nd_stts));
6708 add_ensure_iseq(ret, iseq, 0);
6709 ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
6710 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
6716 else if (ISEQ_COMPILE_DATA(iseq)->end_label) {
6718 debugs(
"next in block\n");
6720 ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label);
6722 add_ensure_iseq(ret, iseq, 0);
6723 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
6735 if (!ISEQ_COMPILE_DATA(ip)) {
6741 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6745 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6748 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6774 const int line =
nd_line(node);
6776 if (ISEQ_COMPILE_DATA(iseq)->redo_label) {
6780 ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
6781 add_ensure_iseq(ret, iseq, 0);
6782 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
6788 else if (iseq->
body->
type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label) {
6793 add_ensure_iseq(ret, iseq, 0);
6794 ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label);
6795 ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
6806 if (!ISEQ_COMPILE_DATA(ip)) {
6811 if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
6814 else if (ip->
body->
type == ISEQ_TYPE_BLOCK) {
6817 else if (ip->
body->
type == ISEQ_TYPE_EVAL) {
6843 const int line =
nd_line(node);
6845 if (iseq->
body->
type == ISEQ_TYPE_RESCUE) {
6863 const int line =
nd_line(node);
6869 ISEQ_TYPE_RESCUE, line);
6876 if (node->nd_else) {
6896 const int line =
nd_line(node);
6897 const NODE *resq = node;
6899 LABEL *label_miss, *label_hit;
6905 narg = resq->nd_args;
6913 ADD_INSNL(ret, line, branchif, label_hit);
6914 narg = narg->nd_next;
6923 ADD_INSNL(ret, line, branchif, label_hit);
6933 ADD_INSNL(ret, line, branchif, label_hit);
6938 if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
6943 resq = resq->nd_head;
6951 const int line =
nd_line(node);
6955 ISEQ_TYPE_ENSURE, line);
6973 push_ensure_entry(iseq, &enl, &er, node->nd_ensr);
6976 CHECK(
COMPILE_(ret,
"ensure head", node->nd_head, (popped | last_leave)));
6979 if (!popped && last_leave)
ADD_INSN(ret, line, putnil);
6981 if (last_leave)
ADD_INSN(ret, line, pop);
6983 erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange;
6988 erange = erange->
next;
6992 ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev;
6999 const int line =
nd_line(node);
7004 enum iseq_type
t =
type;
7005 const NODE *retval = node->nd_stts;
7008 while (
t == ISEQ_TYPE_RESCUE ||
t == ISEQ_TYPE_ENSURE) {
7014 case ISEQ_TYPE_MAIN:
7016 rb_warn(
"argument of top-level return is ignored");
7020 type = ISEQ_TYPE_METHOD;
7027 if (
type == ISEQ_TYPE_METHOD) {
7033 CHECK(
COMPILE(ret,
"return nd_stts (return val)", retval));
7035 if (
type == ISEQ_TYPE_METHOD) {
7036 add_ensure_iseq(ret, iseq, 1);
7060 if (!popped && !all_string_result_p(node)) {
7061 const int line =
nd_line(node);
7081 br = decl_branch_base(iseq, node,
"&.");
7084 ADD_INSNL(recv, line, branchnil, else_label);
7085 add_trace_branch_coverage(iseq, recv, node, 0,
"then", br);
7093 if (!else_label)
return;
7097 add_trace_branch_coverage(iseq, ret, node, 1,
"else", branches);
7108 (node->nd_mid == idFreeze || node->nd_mid ==
idUMinus) &&
7109 node->nd_args ==
NULL &&
7110 ISEQ_COMPILE_DATA(iseq)->current_block ==
NULL &&
7111 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
7119 new_callinfo(iseq, idFreeze, 0, 0,
NULL,
FALSE));
7130 if (node->nd_mid ==
idAREF && !private_recv_p(node) && node->nd_args &&
7133 ISEQ_COMPILE_DATA(iseq)->current_block ==
NULL &&
7134 !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
7135 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
7150iseq_has_builtin_function_table(
const rb_iseq_t *iseq)
7152 return ISEQ_COMPILE_DATA(iseq)->builtin_function_table !=
NULL;
7156iseq_builtin_function_lookup(
const rb_iseq_t *iseq,
const char *
name)
7159 const struct rb_builtin_function *table = ISEQ_COMPILE_DATA(iseq)->builtin_function_table;
7160 for (i=0; table[i].
index != -1; i++) {
7161 if (strcmp(table[i].
name,
name) == 0) {
7172 static const char prefix[] =
"__builtin_";
7173 const size_t prefix_len =
sizeof(
prefix) - 1;
7180 if (recv->nd_mid ==
rb_intern(
"__builtin")) {
7185 if (recv->nd_vid ==
rb_intern(
"Primitive")) {
7196 return &
name[prefix_len];
7213 unsigned int start=0;
7222 for (
unsigned int i=start; i-start<
argc; i++) {
7223 if (elem->
type == ISEQ_ELEMENT_INSN &&
7224 INSN_OF(elem) == BIN(getlocal)) {
7228 if (local_level == 0) {
7231 fprintf(stderr,
"lvar:%s (%d), id:%s (%d) local_index:%d, local_size:%d\n",
7258 *pstart_index = start;
7267compile_builtin_function_call(
rb_iseq_t *iseq,
LINK_ANCHOR *
const ret,
const NODE *
const node,
int line,
int popped,
7270 NODE *args_node = node->nd_args;
7272 if (parent_block !=
NULL) {
7273 COMPILE_ERROR(iseq, line,
"should not call builtins here.");
7277# define BUILTIN_INLINE_PREFIX "_bi"
7279 bool cconst =
false;
7284 if (strcmp(
"cstmt!", builtin_func) == 0 ||
7285 strcmp(
"cexpr!", builtin_func) == 0) {
7288 else if (strcmp(
"cconst!", builtin_func) == 0) {
7291 else if (strcmp(
"cinit!", builtin_func) == 0) {
7293 GET_VM()->builtin_inline_index++;
7296 else if (strcmp(
"attr!", builtin_func) == 0) {
7302 rb_bug(
"can't find builtin function:%s", builtin_func);
7309 if (GET_VM()->builtin_inline_index == INT_MAX) {
7310 rb_bug(
"builtin inline function index overflow:%s", builtin_func);
7312 int inline_index = GET_VM()->builtin_inline_index++;
7314 builtin_func = inline_func;
7320 typedef VALUE(*builtin_func0)(
void *,
VALUE);
7322 ADD_INSN1(ret, line, putobject, const_val);
7328 unsigned int flag = 0;
7338 unsigned int start_index;
7339 if (delegate_call_p(iseq,
FIX2INT(
argc), args, &start_index)) {
7340 ADD_INSN2(ret, line, opt_invokebuiltin_delegate, bf,
INT2FIX(start_index));
7347 if (popped)
ADD_INSN(ret, line, pop);
7361 ID mid = node->nd_mid;
7363 unsigned int flag = 0;
7365 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
7369 ISEQ_COMPILE_DATA(iseq)->current_block =
NULL;
7379 CONST_ID(id_answer,
"the_answer_to_life_the_universe_and_everything");
7381 if (mid == id_bitblt) {
7385 else if (mid == id_answer) {
7399 (mid == goto_id || mid == label_id)) {
7402 st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
7405 if (!labels_table) {
7407 ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
7410 SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
7412 label_name = node->nd_args->nd_head->nd_lit;
7419 label = (
LABEL *)data;
7427 if (mid == goto_id) {
7438 const char *builtin_func;
7439 if (
UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
7440 (builtin_func = iseq_builtin_function_name(
type, node->nd_recv, mid)) !=
NULL) {
7441 return compile_builtin_function_call(iseq, ret, node, line, popped, parent_block, args, builtin_func);
7448 if (mid == idCall &&
7450 iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) {
7453 else if (private_recv_p(node)) {
7462 else_label = qcall_branch_start(iseq, recv, &branches, node, line);
7471 argc = setup_args(iseq, args, node->nd_args, &flag, &
keywords);
7484 switch ((
int)
type) {
7494 qcall_branch_end(iseq, ret, else_label, branches, node, line);
7515 int lineno = ISEQ_COMPILE_DATA(iseq)->last_line;
7517 debugs(
"node: NODE_NIL(implicit)\n");
7522 return iseq_compile_each0(iseq, ret, node, popped);
7530 case ISEQ_TYPE_MAIN:
7531 case ISEQ_TYPE_CLASS:
7545 if (ISEQ_COMPILE_DATA(iseq)->last_line == line) {
7551 ISEQ_COMPILE_DATA(iseq)->last_line = line;
7561#define BEFORE_RETURN debug_node_end()
7567 (node->nd_next ? 1 : popped)));
7568 node = node->nd_next;
7577 CHECK(compile_if(iseq, ret, node, popped,
type));
7580 CHECK(compile_case(iseq, ret, node, popped));
7583 CHECK(compile_case2(iseq, ret, node, popped));
7586 CHECK(compile_case3(iseq, ret, node, popped));
7590 CHECK(compile_loop(iseq, ret, node, popped,
type));
7594 CHECK(compile_iter(iseq, ret, node, popped));
7597 CHECK(compile_for_masgn(iseq, ret, node, popped));
7600 CHECK(compile_break(iseq, ret, node, popped));
7603 CHECK(compile_next(iseq, ret, node, popped));
7606 CHECK(compile_redo(iseq, ret, node, popped));
7609 CHECK(compile_retry(iseq, ret, node, popped));
7616 CHECK(compile_rescue(iseq, ret, node, popped));
7619 CHECK(compile_resbody(iseq, ret, node, popped));
7622 CHECK(compile_ensure(iseq, ret, node, popped));
7633 ADD_INSNL(ret, line, branchunless, end_label);
7636 ADD_INSNL(ret, line, branchif, end_label);
7647 compile_massign(iseq, ret, node, popped);
7652 ID id = node->nd_vid;
7667 ID id = node->nd_vid;
7675 idx = get_dyna_var_idx(iseq,
id, &lv, &ls);
7699 ADD_INSN2(ret, line, setinstancevariable,
7701 get_ivar_ic_value(iseq,node->nd_vid));
7717 compile_cpath(ret, iseq, node->nd_else);
7733 unsigned int flag = 0;
7735 ID id = node->nd_mid;
7764 asgnflag =
COMPILE_RECV(ret,
"NODE_OP_ASGN1 recv", node);
7765 CHECK(asgnflag != -1);
7766 switch (
nd_type(node->nd_args->nd_head)) {
7774 argc = setup_args(iseq, ret, node->nd_args->nd_head, &flag,
NULL);
7798 ADD_INSNL(ret, line, branchunless, label);
7802 CHECK(
COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
7836 CHECK(
COMPILE(ret,
"NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
7867 ID atype = node->nd_next->nd_mid;
7915 asgnflag =
COMPILE_RECV(ret,
"NODE_OP_ASGN2#recv", node);
7916 CHECK(asgnflag != -1);
7917 if (node->nd_next->nd_aid) {
7931 ADD_INSNL(ret, line, branchunless, lcfin);
7934 CHECK(
COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
7954 CHECK(
COMPILE(ret,
"NODE_OP_ASGN2 val", node->nd_value));
7961 if (lskip && popped) {
7965 if (lskip && !popped) {
7976 switch (
nd_type(node->nd_head)) {
7981 CHECK(
COMPILE(ret,
"NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
7988 mid = node->nd_head->nd_mid;
7990 if (node->nd_aid ==
idOROP) {
7995 ADD_INSNL(ret, line, branchunless, lassign);
8003 if (!popped)
ADD_INSN(ret, line, dup);
8004 if (node->nd_aid ==
idOROP)
8007 ADD_INSNL(ret, line, branchunless, lfin);
8009 if (!popped)
ADD_INSN(ret, line, pop);
8011 CHECK(
COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
8021 if (!popped)
ADD_INSN(ret, line, swap);
8025 CHECK(
COMPILE(ret,
"NODE_OP_CDECL#nd_value", node->nd_value));
8047 defined_expr(iseq, ret, node->nd_head, lfinish,
Qfalse);
8048 lassign = lfinish[1];
8052 ADD_INSNL(ret, line, branchunless, lassign);
8058 CHECK(
COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
8062 ADD_INSNL(ret, line, branchunless, lfin);
8070 CHECK(
COMPILE(ret,
"NODE_OP_ASGN_AND/OR#nd_value", node->nd_value));
8081 if (compile_call_precheck_freeze(iseq, ret, node, line, popped) ==
TRUE) {
8087 if (compile_call(iseq, ret, node,
type, line, popped) ==
COMPILE_NG) {
8095 unsigned int flag = 0;
8097 const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
8100 ISEQ_COMPILE_DATA(iseq)->current_block =
NULL;
8102 VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &
keywords);
8111 const struct rb_iseq_param_keyword *
const local_kwd = local_body->
param.
keyword;
8112 int lvar_level = get_lvar_level(iseq);
8149 for (j=0; j<post_len; j++) {
8154 ADD_INSN (args, line, concatarray);
8159 for (j=0; j<post_len; j++) {
8163 argc = post_len + post_start;
8181 for (i = 0; i < local_kwd->num; ++i) {
8182 ID id = local_kwd->table[i];
8183 int idx = local_size - get_local_var_idx(liseq,
id);
8190 ADD_INSN (args, line, concatarray);
8201 ADD_INSN (args, line, concatarray);
8222 CHECK(compile_array(iseq, ret, node, popped) >= 0);
8232 const NODE *n = node;
8244 CHECK(compile_hash(iseq, ret, node,
FALSE, popped) >= 0);
8247 CHECK(compile_return(iseq, ret, node, popped));
8252 unsigned int flag = 0;
8257 if (check_yield_place(iseq) ==
FALSE) {
8262 if (node->nd_head) {
8263 argc = setup_args(iseq, args, node->nd_head, &flag, &
keywords);
8282 if (level > 0) access_outer_variables(iseq, level,
rb_intern(
"yield"),
true);
8287 ID id = node->nd_vid;
8297 debugi(
"nd_vid", node->nd_vid);
8299 idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
8317 debugi(
"nd_vid", node->nd_vid);
8319 ADD_INSN2(ret, line, getinstancevariable,
8321 get_ivar_ic_value(iseq,node->nd_vid));
8326 debugi(
"nd_vid", node->nd_vid);
8328 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
8330 int ic_index = body->
is_size++;
8358 if (!node->nd_nth) {
8370 INT2FIX(0x01 | (node->nd_nth << 1)));
8384 ADD_INSN1(recv, line, putobject, node->nd_lit);
8402 if (node->nd_args) {
8403 compile_named_capture_assign(iseq, ret, node->nd_args);
8414 ADD_INSN1(ret, line, putobject, node->nd_lit);
8422 VALUE lit = node->nd_lit;
8423 if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
8429 if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal ||
RTEST(
ruby_debug)) {
8445 compile_dstr(iseq, ret, node);
8466 compile_dstr(iseq, ret, node);
8475 CHECK(compile_evstr(iseq, ret, node->nd_body, popped));
8478 compile_dregx(iseq, ret, node);
8486 int ic_index = body->
is_size++;
8488 block_iseq =
NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line);
8519 CHECK(
COMPILE_(ret,
"argspush body", node->nd_body, popped));
8523 CHECK(
COMPILE_(ret,
"argspush body", node->nd_body, popped));
8539 ID mid = node->nd_mid;
8542 ISEQ_TYPE_METHOD, line);
8555 ID mid = node->nd_mid;
8558 ISEQ_TYPE_METHOD, line);
8562 ADD_INSN2(ret, line, definesmethod,
ID2SYM(mid), singleton_method_iseq);
8607 ISEQ_TYPE_CLASS, line);
8610 compile_cpath(ret, iseq, node->nd_cpath);
8624 ISEQ_TYPE_CLASS, line);
8626 compile_cpath(ret, iseq, node->nd_cpath);
8640 ISEQ_TYPE_CLASS, line);
8644 CONST_ID(singletonclass,
"singletonclass");
8646 ID2SYM(singletonclass), singleton_class,
8659 int ic_index = body->
is_size++;
8666 CHECK(compile_const_prefix(iseq, node, pref, body));
8667 if (LIST_INSN_SIZE_ZERO(pref)) {
8668 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
8677 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
8700 int ic_index = body->
is_size++;
8702 debugi(
"colon3#nd_mid", node->nd_mid);
8705 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
8714 if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
8728 const NODE *b = node->nd_beg;
8729 const NODE *e = node->nd_end;
8731 if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
8790 if (body->
type == ISEQ_TYPE_RESCUE) {
8797 if (ip->
body->
type == ISEQ_TYPE_RESCUE) {
8815 CHECK(compile_defined_expr(iseq, ret, node,
Qtrue));
8822 int is_index = body->
is_size++;
8824 rb_iseq_new_with_callback_new_callback(build_postexe_iseq, node->nd_body);
8826 new_child_iseq_with_callback(iseq, ifunc,
8827 rb_fstring(make_name_for_block(iseq)), iseq, ISEQ_TYPE_BLOCK, line);
8840 const NODE *default_value = node->nd_body->nd_value;
8863 ADD_INSNL(ret, line, branchif, end_label);
8871 compile_dstr(iseq, ret, node);
8883 unsigned int flag = 0;
8884 ID mid = node->nd_mid;
8892 if (mid ==
idASET && !private_recv_p(node) && node->nd_args &&
8895 ISEQ_COMPILE_DATA(iseq)->current_block ==
NULL &&
8896 !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
8897 ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
8901 CHECK(
COMPILE(ret,
"value", node->nd_args->nd_next->nd_head));
8915 argc = setup_args(iseq, args, node->nd_args, &flag,
NULL);
8919 CHECK(asgnflag != -1);
8920 flag |= (
unsigned int)asgnflag;
8928 else_label = qcall_branch_start(iseq, recv, &branches, node, line);
8960 qcall_branch_end(iseq, ret, else_label, branches, node, line);
8995insn_data_length(
INSN *iobj)
8997 return insn_len(iobj->
insn_id);
9001calc_sp_depth(
int depth,
INSN *insn)
9003 return comptime_insn_stack_increase(depth, insn->
insn_id, insn->
operands);
9007opobj_inspect(
VALUE obj)
9027insn_data_to_s_detail(
INSN *iobj)
9035 for (j = 0;
types[j]; j++) {
9092 if (dladdr(func, &info) && info.dli_sname) {
9129 printf(
"-- raw disasm--------\n");
9132 if (curr) printf(curr ==
link ?
"*" :
" ");
9133 switch (
link->type) {
9134 case ISEQ_ELEMENT_INSN:
9137 str = insn_data_to_s_detail(iobj);
9139 pos += insn_data_length(iobj);
9142 case ISEQ_ELEMENT_LABEL:
9146 dest == lobj ?
" <---" :
"");
9149 case ISEQ_ELEMENT_TRACE:
9152 printf(
" trace: %0x\n", trace->
event);
9155 case ISEQ_ELEMENT_ADJUST:
9167 printf(
"---------------------\n");
9174 return insn_name(i);
9182 for (i = 0; i < VM_INSTRUCTION_SIZE; i++) {
9195 if (
st_lookup(labels_table, obj, &tmp) == 0) {
9200 label = (
LABEL *)tmp;
9209 static VALUE symRescue, symEnsure, symRetry;
9210 static VALUE symBreak, symRedo, symNext;
9212 if (symRescue == 0) {
9213 symRescue =
ID2SYM(rb_intern_const(
"rescue"));
9214 symEnsure =
ID2SYM(rb_intern_const(
"ensure"));
9215 symRetry =
ID2SYM(rb_intern_const(
"retry"));
9216 symBreak =
ID2SYM(rb_intern_const(
"break"));
9217 symRedo =
ID2SYM(rb_intern_const(
"redo"));
9218 symNext =
ID2SYM(rb_intern_const(
"next"));
9221 if (
sym == symRescue)
return CATCH_TYPE_RESCUE;
9222 if (
sym == symEnsure)
return CATCH_TYPE_ENSURE;
9223 if (
sym == symRetry)
return CATCH_TYPE_RETRY;
9224 if (
sym == symBreak)
return CATCH_TYPE_BREAK;
9225 if (
sym == symRedo)
return CATCH_TYPE_REDO;
9226 if (
sym == symNext)
return CATCH_TYPE_NEXT;
9240 LABEL *lstart, *lend, *lcont;
9255 lstart = register_label(iseq, labels_table,
RARRAY_AREF(v, 2));
9256 lend = register_label(iseq, labels_table,
RARRAY_AREF(v, 3));
9257 lcont = register_label(iseq, labels_table,
RARRAY_AREF(v, 4));
9261 if (
type == CATCH_TYPE_RESCUE ||
9262 type == CATCH_TYPE_BREAK ||
9263 type == CATCH_TYPE_NEXT) {
9277insn_make_insn_table(
void)
9283 for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
9315 unsigned int flag = 0;
9326 if (!
NIL_P(vorig_argc)) orig_argc =
FIX2INT(vorig_argc);
9328 if (!
NIL_P(vkw_arg)) {
9330 int len = RARRAY_LENINT(vkw_arg);
9331 size_t n = rb_callinfo_kwarg_bytes(
len);
9335 for (i = 0; i <
len; i++) {
9351#define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern_const(#ev))) return ev;
9377 static struct st_table *insn_table;
9379 if (insn_table == 0) {
9380 insn_table = insn_make_insn_table();
9383 for (i=0; i<
len; i++) {
9392 LABEL *label = register_label(iseq, labels_table, obj);
9399 else if (RB_TYPE_P(obj,
T_ARRAY)) {
9401 int argc = RARRAY_LENINT(obj) - 1;
9409 "unknown instruction: %+"PRIsVALUE, insn);
9414 if (
argc != insn_len((
VALUE)insn_id)-1) {
9416 "operand size mismatch");
9427 (
enum ruby_vminsn_type)insn_id,
argc,
argv));
9429 for (j=0; j<
argc; j++) {
9431 switch (insn_op_type((
VALUE)insn_id, j)) {
9433 LABEL *label = register_label(iseq, labels_table, op);
9449 VALUE v = (
VALUE)iseq_build_load_iseq(iseq, op);
9468 argv[j] = iseq_build_callinfo_from_hash(iseq, op);
9484 register_label(iseq, labels_table,
sym);
9494#if SIZEOF_VALUE <= SIZEOF_LONG
9497 LONG_LONG funcptr =
NUM2LL(op);
9510 (
enum ruby_vminsn_type)insn_id,
argc,
NULL));
9518 validate_labels(iseq, labels_table);
9519 if (!ret)
return ret;
9520 return iseq_setup(iseq, anchor);
9523#define CHECK_ARRAY(v) rb_to_array_type(v)
9524#define CHECK_SYMBOL(v) rb_to_symbol_type(v)
9534 else if (!
NIL_P(val)) {
9541static const struct rb_iseq_param_keyword *
9545 int len = RARRAY_LENINT(keywords);
9550 struct rb_iseq_param_keyword *keyword =
ZALLOC(
struct rb_iseq_param_keyword);
9555#define SYM(s) ID2SYM(rb_intern_const(#s))
9556 (void)int_param(&keyword->bits_start, params,
SYM(kwbits));
9557 i = keyword->bits_start - keyword->num;
9562 for (i = 0; i <
len; i++) {
9566 goto default_values;
9569 keyword->required_num++;
9573 default_len =
len - i;
9574 if (default_len == 0) {
9575 keyword->table = ids;
9578 else if (default_len < 0) {
9584 for (j = 0; i <
len; i++, j++) {
9601 dvs[j] = default_val;
9604 keyword->table = ids;
9605 keyword->default_values = dvs;
9615 unsigned int pos = 0;
9618#ifdef STRICT_ALIGNMENT
9619 size_t padding = calc_padding((
void *)&storage->
buff[pos],
size);
9621 const size_t padding = 0;
9626 storage = storage->
next;
9629#ifdef STRICT_ALIGNMENT
9630 pos += (
int)padding;
9633 iobj = (
INSN *)&storage->
buff[pos];
9639 for (j = 0;
types[j]; j++) {
9668#define SYM(s) ID2SYM(rb_intern_const(#s))
9670 unsigned int arg_size, local_size, stack_max;
9676 VALUE sym_arg_rest =
ID2SYM(rb_intern_const(
"#arg_rest"));
9680 len = RARRAY_LENINT(locals);
9684 for (i = 0; i <
len; i++) {
9687 if (sym_arg_rest == lv) {
9695#define INT_PARAM(F) int_param(&iseq->body->param.F, params, SYM(F))
9705#define INT_PARAM(F) F = (int_param(&x, misc, SYM(F)) ? (unsigned int)x : 0)
9713 if (RB_TYPE_P(arg_opt_labels,
T_ARRAY)) {
9714 len = RARRAY_LENINT(arg_opt_labels);
9720 for (i = 0; i <
len; i++) {
9722 LABEL *label = register_label(iseq, labels_table, ent);
9723 opt_table[i] = (
VALUE)label;
9730 else if (!
NIL_P(arg_opt_labels)) {
9735 if (RB_TYPE_P(keywords,
T_ARRAY)) {
9738 else if (!
NIL_P(keywords)) {
9747 if (int_param(&i, params,
SYM(kwrest))) {
9748 struct rb_iseq_param_keyword *keyword = (
struct rb_iseq_param_keyword *)iseq->
body->
param.
keyword;
9752 keyword->rest_start = i;
9756 iseq_calc_param_size(iseq);
9759 iseq_build_from_ary_exception(iseq, labels_table, exception);
9762 iseq_build_from_ary_body(iseq, anchor, body, labels_wrapper);
9842 VALUE path, realpath;
9847 acc.
line = caller_location(&path, &realpath);
9849 rb_iseq_new_with_callback_new_callback(build, &acc);
9859 const int line = args->
line;
9862 iseq_set_local_table(iseq, 0);
9874 const int line = args->
line;
9876 static const ID vars[] = {1, idUScore};
9878 iseq_set_local_table(iseq, vars);
9893 return method_for_self(
name, arg, func, for_self_aref);
9902 return method_for_self(
name, arg, func, for_self_aset);
9907#ifndef IBF_ISEQ_DEBUG
9908#define IBF_ISEQ_DEBUG 0
9911#ifndef IBF_ISEQ_ENABLE_LOCAL_BUFFER
9912#define IBF_ISEQ_ENABLE_LOCAL_BUFFER 0
9916#define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
9918#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
9920#define IBF_DEVEL_VERSION 3
9921#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
9923#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
9977pinned_list_mark(
void *
ptr)
9981 for (i = 0; i < list->
size; i++) {
9989pinned_list_free(
void *
ptr)
9997pinned_list_memsize(
const void *
ptr)
10005 {pinned_list_mark, pinned_list_free, pinned_list_memsize,},
10038pinned_list_new(
long size)
10051ibf_dump_pos(
struct ibf_dump *dump)
10054#if SIZEOF_LONG > SIZEOF_INT
10055 if (pos >= UINT_MAX) {
10059 return (
unsigned int)pos;
10063ibf_dump_align(
struct ibf_dump *dump,
size_t align)
10067 static const char padding[
sizeof(
VALUE)];
10068 size_t size = align - ((size_t)pos % align);
10069#if SIZEOF_LONG > SIZEOF_INT
10070 if (pos +
size >= UINT_MAX) {
10074 for (;
size >
sizeof(padding);
size -=
sizeof(padding)) {
10082ibf_dump_write(
struct ibf_dump *dump,
const void *buff,
unsigned long size)
10091ibf_dump_write_byte(
struct ibf_dump *dump,
unsigned char byte)
10093 return ibf_dump_write(dump, &
byte,
sizeof(
unsigned char));
10097ibf_dump_overwrite(
struct ibf_dump *dump,
void *buff,
unsigned int size,
long offset)
10102 rb_bug(
"ibf_dump_overwrite: overflow");
10111 return load->current_buffer->buff + beg;
10118 size_t size = x * y;
10123#define IBF_W_ALIGN(type) (RUBY_ALIGNOF(type) > 1 ? ibf_dump_align(dump, RUBY_ALIGNOF(type)) : (void)0)
10125#define IBF_W(b, type, n) (IBF_W_ALIGN(type), (type *)(VALUE)IBF_WP(b, type, n))
10126#define IBF_WV(variable) ibf_dump_write(dump, &(variable), sizeof(variable))
10127#define IBF_WP(b, type, n) ibf_dump_write(dump, (b), sizeof(type) * (n))
10128#define IBF_R(val, type, n) (type *)ibf_load_alloc(load, IBF_OFFSET(val), sizeof(type), (n))
10129#define IBF_ZERO(variable) memset(&(variable), 0, sizeof(variable))
10147 int index = ibf_table_lookup(table,
key);
10159static void ibf_dump_object_list(
struct ibf_dump *dump,
ibf_offset_t *obj_list_offset,
unsigned int *obj_list_size);
10165ibf_dump_object_table_new(
void)
10185 return ibf_dump_object(dump,
rb_id2sym(
id));
10191 if (id_index == 0) {
10205 if (iseq ==
NULL) {
10213static unsigned char
10217 return (
unsigned char)
load->current_buffer->buff[(*offset)++];
10234 ibf_dump_write(dump, &x,
sizeof(
VALUE));
10238 enum { max_byte_length =
sizeof(
VALUE) + 1 };
10240 unsigned char bytes[max_byte_length];
10243 for (n = 0; n <
sizeof(
VALUE) && (x >> (7 - n)); n++, x >>= 8) {
10244 bytes[max_byte_length - 1 - n] = (
unsigned char)x;
10250 bytes[max_byte_length - 1 - n] = (
unsigned char)x;
10253 ibf_dump_write(dump, bytes + max_byte_length - n, n);
10260 union {
char s[
sizeof(
VALUE)];
VALUE v; } x;
10268 enum { max_byte_length =
sizeof(
VALUE) + 1 };
10270 const unsigned char *buffer = (
const unsigned char *)
load->current_buffer->buff;
10271 const unsigned char c = buffer[*
offset];
10275 c == 0 ? 9 : ntz_int32(c) + 1;
10278 if (*
offset + n >
load->current_buffer->size) {
10283 for (i = 1; i < n; i++) {
10299 ibf_dump_write_small_value(dump, (
VALUE)bf->
index);
10302 ibf_dump_write_small_value(dump, (
VALUE)
len);
10303 ibf_dump_write(dump, bf->
name,
len);
10314 fprintf(stderr,
"%.*s!!\n",
len,
name);
10337 for (code_index=0; code_index<
iseq_size;) {
10338 const VALUE insn = orig_code[code_index++];
10339 const char *
types = insn_op_types(insn);
10344 ibf_dump_write_small_value(dump, insn);
10347 for (op_index=0;
types[op_index]; op_index++, code_index++) {
10348 VALUE op = orig_code[code_index];
10351 switch (
types[op_index]) {
10354 wv = ibf_dump_object(dump, op);
10364 for (i=0; i<body->
is_size; i++) {
10377 wv = ibf_dump_id(dump, (
ID)op);
10389 ibf_dump_write_small_value(dump, wv);
10392 assert(insn_len(insn) == op_index+1);
10402 unsigned int code_index;
10410 for (code_index=0; code_index<iseq_size;) {
10412 const VALUE insn =
code[code_index++] = ibf_load_small_value(
load, &reading_pos);
10413 const char *
types = insn_op_types(insn);
10417 for (op_index=0;
types[op_index]; op_index++, code_index++) {
10418 switch (
types[op_index]) {
10422 VALUE op = ibf_load_small_value(
load, &reading_pos);
10424 code[code_index] = v;
10435 code[code_index] = v;
10446 VALUE op = ibf_load_small_value(
load, &reading_pos);
10447 code[code_index] = (
VALUE)&is_entries[op];
10453 code[code_index] = (
VALUE)cd_entries++;
10458 VALUE op = ibf_load_small_value(
load, &reading_pos);
10466 code[code_index] = (
VALUE)ibf_load_builtin(
load, &reading_pos);
10469 code[code_index] = ibf_load_small_value(
load, &reading_pos);
10473 if (insn_len(insn) != op_index+1) {
10480 assert(code_index == iseq_size);
10481 assert(reading_pos == bytecode_offset + bytecode_size);
10495 return ibf_dump_pos(dump);
10504 MEMCPY(table,
load->current_buffer->buff + opt_table_offset,
VALUE, opt_num+1);
10518 struct rb_iseq_param_keyword dump_kw = *kw;
10519 int dv_num = kw->num - kw->required_num;
10524 for (i=0; i<kw->num; i++) ids[i] = (
ID)ibf_dump_id(dump, kw->table[i]);
10525 for (i=0; i<dv_num; i++) dvs[i] = (
VALUE)ibf_dump_object(dump, kw->default_values[i]);
10527 dump_kw.table =
IBF_W(ids,
ID, kw->num);
10528 dump_kw.default_values =
IBF_W(dvs,
VALUE, dv_num);
10530 return ibf_dump_write(dump, &dump_kw,
sizeof(
struct rb_iseq_param_keyword) * 1);
10537static const struct rb_iseq_param_keyword *
10540 if (param_keyword_offset) {
10541 struct rb_iseq_param_keyword *kw =
IBF_R(param_keyword_offset,
struct rb_iseq_param_keyword, 1);
10542 ID *ids =
IBF_R(kw->table,
ID, kw->num);
10543 int dv_num = kw->num - kw->required_num;
10547 for (i=0; i<kw->num; i++) {
10548 ids[i] = ibf_load_id(
load, ids[i]);
10550 for (i=0; i<dv_num; i++) {
10551 dvs[i] = ibf_load_object(
load, dvs[i]);
10555 kw->default_values = dvs;
10571 ibf_dump_write_small_value(dump, entries[i].
line_no);
10572 ibf_dump_write_small_value(dump, entries[i].
events);
10585 for (i = 0; i <
size; i++) {
10586 entries[i].
line_no = (
int)ibf_load_small_value(
load, &reading_pos);
10594ibf_dump_insns_info_positions(
struct ibf_dump *dump,
const unsigned int *positions,
unsigned int size)
10598 unsigned int last = 0;
10600 for (i = 0; i <
size; i++) {
10601 ibf_dump_write_small_value(dump, positions[i] -
last);
10602 last = positions[i];
10608static unsigned int *
10612 unsigned int *positions =
ALLOC_N(
unsigned int,
size);
10614 unsigned int last = 0;
10616 for (i = 0; i <
size; i++) {
10617 positions[i] =
last + (
unsigned int)ibf_load_small_value(
load, &reading_pos);
10618 last = positions[i];
10632 for (i=0; i<
size; i++) {
10637 return ibf_dump_write(dump,
table,
sizeof(
ID) *
size);
10647 for (i=0; i<
size; i++) {
10663 int *iseq_indices =
ALLOCA_N(
int, table->size);
10666 for (i=0; i<table->size; i++) {
10667 iseq_indices[i] = ibf_dump_iseq(dump, table->entries[i].iseq);
10672 for (i=0; i<table->size; i++) {
10673 ibf_dump_write_small_value(dump, iseq_indices[i]);
10674 ibf_dump_write_small_value(dump, table->entries[i].type);
10675 ibf_dump_write_small_value(dump, table->entries[i].start);
10676 ibf_dump_write_small_value(dump, table->entries[i].end);
10677 ibf_dump_write_small_value(dump, table->entries[i].cont);
10678 ibf_dump_write_small_value(dump, table->entries[i].sp);
10683 return ibf_dump_pos(dump);
10687static struct iseq_catch_table *
10691 struct iseq_catch_table *table =
ruby_xmalloc(iseq_catch_table_bytes(
size));
10692 table->size =
size;
10697 for (i=0; i<table->size; i++) {
10698 int iseq_index = (
int)ibf_load_small_value(
load, &reading_pos);
10699 table->entries[i].type = (
enum catch_type)ibf_load_small_value(
load, &reading_pos);
10700 table->entries[i].start = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
10701 table->entries[i].end = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
10702 table->entries[i].cont = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
10703 table->entries[i].sp = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
10725 for (i = 0; i < ci_size; i++) {
10728 ibf_dump_write_small_value(dump, ibf_dump_id(dump, vm_ci_mid(ci)));
10729 ibf_dump_write_small_value(dump, vm_ci_flag(ci));
10730 ibf_dump_write_small_value(dump, vm_ci_argc(ci));
10735 ibf_dump_write_small_value(dump,
len);
10736 for (
int j=0; j<
len; j++) {
10738 ibf_dump_write_small_value(dump, keyword);
10742 ibf_dump_write_small_value(dump, 0);
10747 ibf_dump_write_small_value(dump, (
VALUE)-1);
10755dump_outer_variable(
ID id,
VALUE val,
void *dump)
10757 ibf_dump_write_small_value(dump, ibf_dump_id(dump,
id));
10758 ibf_dump_write_small_value(dump, val);
10775 ibf_dump_write_small_value(dump, (
VALUE)0);
10785 unsigned int ci_size,
10795 for (i = 0; i < ci_size; i++) {
10796 VALUE mid_index = ibf_load_small_value(
load, &reading_pos);
10797 if (mid_index != (
VALUE)-1) {
10798 ID mid = ibf_load_id(
load, mid_index);
10799 unsigned int flag = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
10800 unsigned int argc = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
10803 int kwlen = (
int)ibf_load_small_value(
load, &reading_pos);
10807 for (
int j=0; j<kwlen; j++) {
10808 VALUE keyword = ibf_load_small_value(
load, &reading_pos);
10832 size_t table_size = (size_t)ibf_load_small_value(
load, &reading_pos);
10834 if (table_size > 0) {
10838 for (
size_t i = 0; i < table_size; i++) {
10839 ID key = ibf_load_id(
load, (
ID)ibf_load_small_value(
load, &reading_pos));
10840 VALUE value = ibf_load_small_value(
load, &reading_pos);
10852 unsigned int *positions;
10860#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10866 buffer.obj_table = ibf_dump_object_table_new();
10870 const ibf_offset_t bytecode_offset = ibf_dump_code(dump, iseq);
10871 const ibf_offset_t bytecode_size = ibf_dump_pos(dump) - bytecode_offset;
10872 const ibf_offset_t param_opt_table_offset = ibf_dump_param_opt_table(dump, iseq);
10873 const ibf_offset_t param_keyword_offset = ibf_dump_param_keyword(dump, iseq);
10874 const ibf_offset_t insns_info_body_offset = ibf_dump_insns_info_body(dump, iseq);
10876 positions = rb_iseq_insns_info_decode_positions(iseq->
body);
10880 const ibf_offset_t local_table_offset = ibf_dump_local_table(dump, iseq);
10882 const ibf_offset_t catch_table_offset = ibf_dump_catch_table(dump, iseq);
10883 const int parent_iseq_index = ibf_dump_iseq(dump, iseq->
body->
parent_iseq);
10884 const int local_iseq_index = ibf_dump_iseq(dump, iseq->
body->
local_iseq);
10885 const ibf_offset_t ci_entries_offset = ibf_dump_ci_entries(dump, iseq);
10886 const ibf_offset_t outer_variables_offset = ibf_dump_outer_variables(dump, iseq);
10888#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10890 unsigned int local_obj_list_size;
10892 ibf_dump_object_list(dump, &local_obj_list_offset, &local_obj_list_size);
10898 unsigned int param_flags =
10910#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10911# define IBF_BODY_OFFSET(x) (x)
10913# define IBF_BODY_OFFSET(x) (body_offset - (x))
10916 ibf_dump_write_small_value(dump, body->
type);
10917 ibf_dump_write_small_value(dump, body->
iseq_size);
10919 ibf_dump_write_small_value(dump, bytecode_size);
10920 ibf_dump_write_small_value(dump, param_flags);
10921 ibf_dump_write_small_value(dump, body->
param.
size);
10923 ibf_dump_write_small_value(dump, body->
param.
opt_num);
10928 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(param_opt_table_offset));
10929 ibf_dump_write_small_value(dump, param_keyword_offset);
10930 ibf_dump_write_small_value(dump, location_pathobj_index);
10931 ibf_dump_write_small_value(dump, location_base_label_index);
10932 ibf_dump_write_small_value(dump, location_label_index);
10939 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(insns_info_body_offset));
10940 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(insns_info_positions_offset));
10942 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(local_table_offset));
10943 ibf_dump_write_small_value(dump, catch_table_size);
10944 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(catch_table_offset));
10945 ibf_dump_write_small_value(dump, parent_iseq_index);
10946 ibf_dump_write_small_value(dump, local_iseq_index);
10947 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(ci_entries_offset));
10948 ibf_dump_write_small_value(dump,
IBF_BODY_OFFSET(outer_variables_offset));
10951 ibf_dump_write_small_value(dump, body->
is_size);
10952 ibf_dump_write_small_value(dump, body->
ci_size);
10953 ibf_dump_write_small_value(dump, body->
stack_max);
10957#undef IBF_BODY_OFFSET
10959#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
10963 ibf_dump_write(dump,
RSTRING_PTR(buffer.str), iseq_length_bytes);
10966 ibf_dump_write_small_value(dump, iseq_start);
10967 ibf_dump_write_small_value(dump, iseq_length_bytes);
10968 ibf_dump_write_small_value(dump, body_offset);
10970 ibf_dump_write_small_value(dump, local_obj_list_offset);
10971 ibf_dump_write_small_value(dump, local_obj_list_size);
10977 return body_offset;
10998#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
11000 load->current_buffer = &
load->global_buffer;
11007 buffer.
buff =
load->global_buffer.buff + iseq_start;
11008 buffer.size = iseq_length_bytes;
11009 buffer.obj_list_offset = (
ibf_offset_t)ibf_load_small_value(
load, &reading_pos);
11010 buffer.obj_list_size = (
ibf_offset_t)ibf_load_small_value(
load, &reading_pos);
11011 buffer.obj_list = pinned_list_new(buffer.obj_list_size);
11013 load->current_buffer = &buffer;
11014 reading_pos = body_offset;
11017#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
11018# define IBF_BODY_OFFSET(x) (x)
11020# define IBF_BODY_OFFSET(x) (offset - (x))
11023 const unsigned int type = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11024 const unsigned int iseq_size = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11027 const unsigned int param_flags = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11028 const unsigned int param_size = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11029 const int param_lead_num = (
int)ibf_load_small_value(
load, &reading_pos);
11030 const int param_opt_num = (
int)ibf_load_small_value(
load, &reading_pos);
11031 const int param_rest_start = (
int)ibf_load_small_value(
load, &reading_pos);
11032 const int param_post_start = (
int)ibf_load_small_value(
load, &reading_pos);
11033 const int param_post_num = (
int)ibf_load_small_value(
load, &reading_pos);
11034 const int param_block_start = (
int)ibf_load_small_value(
load, &reading_pos);
11037 const VALUE location_pathobj_index = ibf_load_small_value(
load, &reading_pos);
11038 const VALUE location_base_label_index = ibf_load_small_value(
load, &reading_pos);
11039 const VALUE location_label_index = ibf_load_small_value(
load, &reading_pos);
11040 const VALUE location_first_lineno = ibf_load_small_value(
load, &reading_pos);
11041 const int location_node_id = (
int)ibf_load_small_value(
load, &reading_pos);
11042 const int location_code_location_beg_pos_lineno = (
int)ibf_load_small_value(
load, &reading_pos);
11043 const int location_code_location_beg_pos_column = (
int)ibf_load_small_value(
load, &reading_pos);
11044 const int location_code_location_end_pos_lineno = (
int)ibf_load_small_value(
load, &reading_pos);
11045 const int location_code_location_end_pos_column = (
int)ibf_load_small_value(
load, &reading_pos);
11048 const unsigned int insns_info_size = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11050 const unsigned int catch_table_size = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11052 const int parent_iseq_index = (
int)ibf_load_small_value(
load, &reading_pos);
11053 const int local_iseq_index = (
int)ibf_load_small_value(
load, &reading_pos);
11057 const unsigned int local_table_size = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11058 const unsigned int is_size = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11059 const unsigned int ci_size = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11060 const unsigned int stack_max = (
unsigned int)ibf_load_small_value(
load, &reading_pos);
11061 const char catch_except_p = (char)ibf_load_small_value(
load, &reading_pos);
11062 const bool builtin_inline_p = (bool)ibf_load_small_value(
load, &reading_pos);
11064#undef IBF_BODY_OFFSET
11086 load_body->
is_size = is_size;
11087 load_body->
ci_size = ci_size;
11091 ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
11104 ibf_load_ci_entries(
load, ci_entries_offset, ci_size, &load_body->
call_data);
11106 load_body->
param.
opt_table = ibf_load_param_opt_table(
load, param_opt_table_offset, param_opt_num);
11107 load_body->
param.
keyword = ibf_load_param_keyword(
load, param_keyword_offset);
11109 load_body->
insns_info.
body = ibf_load_insns_info_body(
load, insns_info_body_offset, insns_info_size);
11110 load_body->
insns_info.
positions = ibf_load_insns_info_positions(
load, insns_info_positions_offset, insns_info_size);
11111 load_body->
local_table = ibf_load_local_table(
load, local_table_offset, local_table_size);
11112 load_body->
catch_table = ibf_load_catch_table(
load, catch_table_offset, catch_table_size);
11116 ibf_load_code(
load, iseq, bytecode_offset, bytecode_size, iseq_size);
11117#if VM_INSN_INFO_TABLE_IMPL == 2
11121 rb_iseq_translate_threaded_code(iseq);
11123#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
11124 load->current_buffer = &
load->global_buffer;
11128 VALUE realpath =
Qnil, path = ibf_load_object(
load, location_pathobj_index);
11132 else if (RB_TYPE_P(path,
T_ARRAY)) {
11133 VALUE pathobj = path;
11139 if (!
NIL_P(realpath)) {
11140 if (!RB_TYPE_P(realpath,
T_STRING)) {
11143 realpath,
TYPE(realpath), path);
11157#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
11158 load->current_buffer = saved_buffer;
11160 verify_call_cache(iseq);
11196 for (i = 0; i <
size; i++) {
11205#define IBF_OBJECT_INTERNAL FL_PROMOTED0
11263#define IBF_ALIGNED_OFFSET(align, offset) \
11264 ((((offset) - 1) / (align) + 1) * (align))
11265#define IBF_OBJBODY(type, offset) (const type *)\
11266 ibf_load_check_offset(load, IBF_ALIGNED_OFFSET(RUBY_ALIGNOF(type), offset))
11280ibf_dump_object_unsupported(
struct ibf_dump *dump,
VALUE obj)
11318 rb_bug(
"unsupported class");
11320 ibf_dump_write_small_value(dump, (
VALUE)cindex);
11349 (void)
IBF_W(&dbl,
double, 1);
11372 ibf_dump_write_small_value(dump, encindex);
11373 ibf_dump_write_small_value(dump,
len);
11382 int encindex = (
int)ibf_load_small_value(
load, &reading_pos);
11383 const long len = (
long)ibf_load_small_value(
load, &reading_pos);
11384 const char *
ptr =
load->current_buffer->buff + reading_pos;
11403 VALUE srcstr = RREGEXP_SRC(obj);
11406 regexp.srcstr = (
long)ibf_dump_object(dump,
srcstr);
11408 ibf_dump_write_byte(dump, (
unsigned char)regexp.option);
11409 ibf_dump_write_small_value(dump, regexp.srcstr);
11417 regexp.srcstr = ibf_load_small_value(
load, &
offset);
11432 ibf_dump_write_small_value(dump,
len);
11433 for (i=0; i<
len; i++) {
11435 ibf_dump_write_small_value(dump, index);
11444 const long len = (
long)ibf_load_small_value(
load, &reading_pos);
11449 for (i=0; i<
len; i++) {
11450 const VALUE index = ibf_load_small_value(
load, &reading_pos);
11466 VALUE val_index = ibf_dump_object(dump, (
VALUE)val);
11468 ibf_dump_write_small_value(dump, key_index);
11469 ibf_dump_write_small_value(dump, val_index);
11477 ibf_dump_write_small_value(dump, (
VALUE)
len);
11489 for (i = 0; i <
len; i++) {
11494 VALUE val = ibf_load_object(
load, val_index);
11513 range.class_index = 0;
11543 ssize_t
len = BIGNUM_LEN(obj);
11544 ssize_t slen = BIGNUM_SIGN(obj) > 0 ?
len :
len * -1;
11545 BDIGIT *d = BIGNUM_DIGITS(obj);
11547 (void)
IBF_W(&slen, ssize_t, 1);
11555 int sign = bignum->
slen > 0;
11556 ssize_t
len = sign > 0 ? bignum->
slen : -1 * bignum->
slen;
11574 (void)
IBF_W(data,
long, 2);
11578 ibf_dump_object_unsupported(dump, obj);
11588 const char *data = (
const char *)&body[2];
11598 return ibf_load_object_unsupported(
load, header,
offset);
11602ibf_dump_object_complex_rational(
struct ibf_dump *dump,
VALUE obj)
11605 data[0] = (
long)ibf_dump_object(dump,
RCOMPLEX(obj)->real);
11606 data[1] = (
long)ibf_dump_object(dump,
RCOMPLEX(obj)->imag);
11608 (void)
IBF_W(data,
long, 2);
11629 VALUE str_index = ibf_dump_object(dump,
str);
11631 ibf_dump_write_small_value(dump, str_index);
11645 ibf_dump_object_unsupported,
11646 ibf_dump_object_unsupported,
11647 ibf_dump_object_class,
11648 ibf_dump_object_unsupported,
11649 ibf_dump_object_float,
11650 ibf_dump_object_string,
11651 ibf_dump_object_regexp,
11652 ibf_dump_object_array,
11653 ibf_dump_object_hash,
11654 ibf_dump_object_struct,
11655 ibf_dump_object_bignum,
11656 ibf_dump_object_unsupported,
11657 ibf_dump_object_data,
11658 ibf_dump_object_unsupported,
11659 ibf_dump_object_complex_rational,
11660 ibf_dump_object_complex_rational,
11661 ibf_dump_object_unsupported,
11662 ibf_dump_object_unsupported,
11663 ibf_dump_object_unsupported,
11664 ibf_dump_object_unsupported,
11665 ibf_dump_object_symbol,
11666 ibf_dump_object_unsupported,
11667 ibf_dump_object_unsupported,
11668 ibf_dump_object_unsupported,
11669 ibf_dump_object_unsupported,
11670 ibf_dump_object_unsupported,
11671 ibf_dump_object_unsupported,
11672 ibf_dump_object_unsupported,
11673 ibf_dump_object_unsupported,
11674 ibf_dump_object_unsupported,
11675 ibf_dump_object_unsupported,
11676 ibf_dump_object_unsupported,
11682 unsigned char byte =
11683 (header.
type << 0) |
11694 unsigned char byte = ibf_load_byte(
load,
offset);
11697 header.
type = (
byte >> 0) & 0x1f;
11699 header.
frozen = (
byte >> 6) & 0x01;
11700 header.
internal = (
byte >> 7) & 0x01;
11711 obj_header.type =
TYPE(obj);
11714 current_offset = ibf_dump_pos(dump);
11719 obj_header.special_const =
TRUE;
11720 obj_header.frozen =
TRUE;
11721 obj_header.internal =
TRUE;
11722 ibf_dump_object_object_header(dump, obj_header);
11723 ibf_dump_write_small_value(dump, obj);
11727 obj_header.special_const =
FALSE;
11729 ibf_dump_object_object_header(dump, obj_header);
11730 (*dump_object_functions[obj_header.type])(dump, obj);
11733 return current_offset;
11738 ibf_load_object_unsupported,
11739 ibf_load_object_unsupported,
11740 ibf_load_object_class,
11741 ibf_load_object_unsupported,
11742 ibf_load_object_float,
11743 ibf_load_object_string,
11744 ibf_load_object_regexp,
11745 ibf_load_object_array,
11746 ibf_load_object_hash,
11747 ibf_load_object_struct,
11748 ibf_load_object_bignum,
11749 ibf_load_object_unsupported,
11750 ibf_load_object_data,
11751 ibf_load_object_unsupported,
11752 ibf_load_object_complex_rational,
11753 ibf_load_object_complex_rational,
11754 ibf_load_object_unsupported,
11755 ibf_load_object_unsupported,
11756 ibf_load_object_unsupported,
11757 ibf_load_object_unsupported,
11758 ibf_load_object_symbol,
11759 ibf_load_object_unsupported,
11760 ibf_load_object_unsupported,
11761 ibf_load_object_unsupported,
11762 ibf_load_object_unsupported,
11763 ibf_load_object_unsupported,
11764 ibf_load_object_unsupported,
11765 ibf_load_object_unsupported,
11766 ibf_load_object_unsupported,
11767 ibf_load_object_unsupported,
11768 ibf_load_object_unsupported,
11769 ibf_load_object_unsupported,
11775 if (object_index == 0) {
11779 VALUE obj = pinned_list_fetch(
load->current_buffer->obj_list, (
long)object_index);
11786 fprintf(stderr,
"ibf_load_object: list=%#x offsets=%p offset=%#x\n",
11787 load->current_buffer->obj_list_offset, (
void *)offsets,
offset);
11788 fprintf(stderr,
"ibf_load_object: type=%#x special=%d frozen=%d internal=%d\n",
11798 obj = ibf_load_small_value(
load, &reading_pos);
11801 obj = (*load_object_functions[header.
type])(
load, &header,
offset);
11804 pinned_list_store(
load->current_buffer->obj_list, (
long)object_index, obj);
11808 object_index, obj);
11845 *obj_list_offset = ibf_dump_pos(
dump);
11850 for (i=0; i<
size; i++) {
11855 *obj_list_size = (
unsigned int)
size;
11859ibf_dump_mark(
void *
ptr)
11869ibf_dump_free(
void *
ptr)
11884ibf_dump_memsize(
const void *
ptr)
11887 size_t size =
sizeof(*dump);
11895 {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
11929 ibf_dump_setup(dump, dump_obj);
11931 ibf_dump_write(dump, &header,
sizeof(header));
11933 ibf_dump_iseq(dump, iseq);
11935 header.
magic[0] =
'Y';
11936 header.
magic[1] =
'A';
11937 header.
magic[2] =
'R';
11938 header.
magic[3] =
'B';
11941 ibf_dump_iseq_list(dump, &header);
11943 header.
size = ibf_dump_pos(dump);
11946 VALUE opt_str = opt;
11948 header.
extra_size = RSTRING_LENINT(opt_str);
11955 ibf_dump_overwrite(dump, &header,
sizeof(header), 0);
11958 ibf_dump_free(dump);
11978 fprintf(stderr,
"rb_ibf_load_iseq_complete: index=%#x offset=%#x size=%#x\n",
11980 load->header->size);
11983 ISEQ_COMPILE_DATA_CLEAR(
iseq);
11986 load->iseq = prev_src_iseq;
12001 int iseq_index = (
int)(
VALUE)index_iseq;
12004 fprintf(stderr,
"ibf_load_iseq: index_iseq=%p iseq_list=%p\n",
12005 (
void *)index_iseq, (
void *)
load->iseq_list);
12007 if (iseq_index == -1) {
12011 VALUE iseqv = pinned_list_fetch(
load->iseq_list, iseq_index);
12014 fprintf(stderr,
"ibf_load_iseq: iseqv=%p\n", (
void *)iseqv);
12022 fprintf(stderr,
"ibf_load_iseq: new iseq=%p\n", (
void *)
iseq);
12028 fprintf(stderr,
"ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n",
12029 (
void *)
iseq, (
void *)
load->loader_obj, iseq_index);
12031 pinned_list_store(
load->iseq_list, iseq_index, (
VALUE)
iseq);
12035 fprintf(stderr,
"ibf_load_iseq: loading iseq=%p\n", (
void *)
iseq);
12039 if (GET_VM()->builtin_function_table) {
12045 fprintf(stderr,
"ibf_load_iseq: iseq=%p loaded %p\n",
12046 (
void *)
iseq, (
void *)
load->iseq);
12057 load->global_buffer.buff = bytes;
12059 load->global_buffer.size =
load->header->size;
12060 load->global_buffer.obj_list_offset =
load->header->global_object_list_offset;
12061 load->global_buffer.obj_list_size =
load->header->global_object_list_size;
12063 RB_OBJ_WRITE(loader_obj, &
load->global_buffer.obj_list, pinned_list_new(
load->global_buffer.obj_list_size));
12066 load->current_buffer = &
load->global_buffer;
12068 if (size < load->header->size) {
12071 if (strncmp(
load->header->magic,
"YARB", 4) != 0) {
12084 load->header->iseq_list_offset);
12088 load->global_buffer.obj_list_offset);
12095 if (RSTRING_LENINT(
str) < (
int)
sizeof(
struct ibf_header)) {
12108ibf_loader_mark(
void *
ptr)
12117ibf_loader_free(
void *
ptr)
12124ibf_loader_memsize(
const void *
ptr)
12131 {ibf_loader_mark, ibf_loader_free, ibf_loader_memsize,},
#define offsetof(p_type, field)
VALUE rb_to_array_type(VALUE ary)
VALUE rb_ary_dup(VALUE ary)
VALUE rb_ary_push(VALUE ary, VALUE item)
void rb_ary_set_len(VALUE ary, long len)
VALUE rb_ary_new_capa(long capa)
VALUE rb_ary_tmp_new(long capa)
VALUE rb_ary_clear(VALUE ary)
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
VALUE rb_ary_entry(VALUE ary, long offset)
#define RUBY_ASSERT(expr)
Asserts that the given expression is truthy iff RUBY_DEBUG is truthy.
#define UNREACHABLE_RETURN
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
VALUE rb_big_cmp(VALUE x, VALUE y)
VALUE rb_dbl2big(double d)
VALUE rb_big_hash(VALUE x)
#define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block)
#define NEW_CHILD_ISEQ(node, name, type, line_no)
const rb_iseq_t * rb_method_for_self_aset(VALUE name, VALUE arg, const struct rb_builtin_function *func)
#define NEW_ISEQ(node, name, type, line_no)
#define BUILTIN_INLINE_PREFIX
#define COMPILE(anchor, desc, node)
struct iseq_label_data LABEL
#define INSERT_AFTER_INSN(prev, line, insn)
#define IS_INSN_ID(iobj, insn)
struct iseq_insn_data INSN
const ID rb_iseq_shared_exc_local_tbl[]
void rb_ibf_load_iseq_complete(rb_iseq_t *iseq)
#define IBF_ZERO(variable)
#define APPEND_LABEL(seq, before, label)
#define COMPILE_POPPED(anchor, desc, node)
#define ADD_SEND_R(seq, line, id, argc, block, flag, keywords)
struct iseq_adjust_data ADJUST
#define ADD_INSN1(seq, line, insn, op1)
#define INSERT_AFTER_INSN1(prev, line, insn, op1)
#define INSERT_BEFORE_INSN(next, line, insn)
#define ADD_GETLOCAL(seq, line, idx, level)
#define EXPECT_NODE(prefix, node, ndtype, errval)
#define IBF_MAJOR_VERSION
#define ADD_CALL_RECEIVER(seq, line)
#define LABEL_UNREMOVABLE(label)
#define ADD_TRACE_WITH_DATA(seq, event, data)
#define ISEQ_LAST_LINE(iseq)
VALUE(* ibf_load_object_function)(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
#define ADD_LABEL(seq, label)
#define UNKNOWN_NODE(prefix, node, errval)
VALUE rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
#define FLUSH_CHUNK(newarrayinsn)
#define COMPILE_RECV(anchor, desc, node)
int rb_dvar_defined(ID id, const rb_iseq_t *iseq)
#define COMPILE_(anchor, desc, node, popped)
rb_iseq_t * iseq_alloc(void)
#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc)
#define ADD_SETLOCAL(seq, line, idx, level)
#define INSERT_BEFORE_INSN1(next, line, insn, op1)
VALUE rb_insns_name_array(void)
#define BADINSN_DUMP(anchor, list, dest)
VALUE rb_iseq_ibf_load_extra_data(VALUE str)
#define debug_compile(msg, v)
#define CPDEBUG
debug function(macro) interface depend on CPDEBUG if it is less than 0, runtime option is in effect.
#define ADD_ADJUST(seq, line, label)
unsigned int ibf_offset_t
#define debugi(header, id)
#define IS_NEXT_INSN_ID(link, insn)
VALUE rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
void(* ibf_dump_object_function)(struct ibf_dump *dump, VALUE obj)
#define IBF_WP(b, type, n)
#define ADD_INSN2(seq, line, insn, op1, op2)
VALUE rb_node_case_when_optimizable_literal(const NODE *const node)
struct iseq_link_anchor LINK_ANCHOR
#define ADD_INSN(seq, line, insn)
const rb_iseq_t * rb_iseq_ibf_load(VALUE str)
#define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag)
#define DECL_ANCHOR(name)
const char * rb_insns_name(int i)
#define ADD_SEND(seq, line, id, argc)
#define ADD_CALL(seq, line, id, argc)
#define IBF_W_ALIGN(type)
#define IBF_W(b, type, n)
#define IBF_R(val, type, n)
VALUE rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback_callback_func *ifunc)
int rb_local_defined(ID id, const rb_iseq_t *iseq)
struct iseq_link_element LINK_ELEMENT
#define IBF_OBJBODY(type, offset)
@ IBF_OBJECT_DATA_ENCODING
@ IBF_OBJECT_CLASS_TYPE_ERROR
@ IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR
@ IBF_OBJECT_CLASS_STANDARD_ERROR
@ IBF_OBJECT_CLASS_OBJECT
#define INIT_ANCHOR(name)
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE exception, VALUE body)
#define debug_list(anc, cur)
#define OPERAND_AT(insn, idx)
#define ADD_INSNL(seq, line, insn, label)
const rb_iseq_t * rb_iseq_ibf_load_bytes(const char *bytes, size_t size)
#define ADD_ADJUST_RESTORE(seq, label)
#define debug_node_start(node)
#define debugp_param(header, value)
#define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval)
VALUE * rb_iseq_original_iseq(const rb_iseq_t *iseq)
#define IBF_MINOR_VERSION
void rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *storage)
#define INVALID_ISEQ_TYPE(type)
#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block)
const rb_iseq_t * rb_method_for_self_aref(VALUE name, VALUE arg, const struct rb_builtin_function *func)
#define ADD_INSN3(seq, line, insn, op1, op2, op3)
#define IBF_BODY_OFFSET(x)
#define ADD_TRACE(seq, event)
struct iseq_trace_data TRACE
#define ADD_SEQ(seq1, seq2)
Internal header for the compiler.
int rb_vm_insn_addr2insn(const void *)
#define OBJ_BUILTIN_TYPE(obj)
VALUE rb_complex_new(VALUE x, VALUE y)
st_index_t rb_complex_hash(VALUE self)
#define range(low, item, hi)
#define MJIT_FUNC_EXPORTED
@ RUBY_ENCINDEX_BUILTIN_MAX
int rb_enc_get_index(VALUE obj)
rb_encoding * rb_enc_from_index(int index)
int rb_data_is_encoding(VALUE obj)
rb_encoding * rb_enc_find(const char *name)
rb_encoding * rb_to_encoding(VALUE enc)
VALUE rb_enc_from_encoding(rb_encoding *encoding)
VALUE rb_enc_associate_index(VALUE obj, int idx)
int rb_enc_find_index(const char *name)
size_t map(int syms, int left, int len)
char str[HTML_ESCAPE_MAX_LEN+1]
#define RUBY_EVENT_B_RETURN
#define RUBY_EVENT_RETURN
#define RUBY_EVENT_B_CALL
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
void ruby_xfree(void *x)
Deallocates a storage instance.
const char * rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
void rb_mark_set(st_table *tbl)
void * rb_xmalloc_mul_add(size_t x, size_t y, size_t z)
void rb_gc_mark(VALUE ptr)
void * ruby_xmalloc(size_t size)
Allocates a storage instance.
void rb_obj_info_dump(VALUE obj)
void * ruby_xmalloc2(size_t n, size_t size)
Identical to ruby_xmalloc(), except it allocates nelems * elemsiz bytes.
size_t rb_size_mul_or_raise(size_t x, size_t y, VALUE exc)
#define rb_intern_str(string)
VALUE rb_syntax_error_append(VALUE exc, VALUE file, int line, int column, rb_encoding *enc, const char *fmt, va_list args)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_bug(const char *fmt,...)
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
const char * rb_builtin_type_name(int t)
VALUE rb_eNoMatchingPatternError
void rb_exc_fatal(VALUE mesg)
Raises a fatal error in the current thread.
void rb_warn(const char *fmt,...)
VALUE rb_iseqw_new(const rb_iseq_t *)
void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args)
VALUE rb_cObject
Object class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
unsigned short prefix[65536]
void rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
VALUE rb_hash_rehash(VALUE hash)
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
VALUE rb_hash_new_with_size(st_index_t size)
VALUE rb_hash_aref(VALUE hash, VALUE key)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
long rb_dbl_long_hash(double d)
VALUE rb_hash_lookup(VALUE hash, VALUE key)
@ id_core_set_method_alias
@ id_core_set_variable_alias
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
size_t rb_id_table_size(const struct rb_id_table *tbl)
struct rb_id_table * rb_id_table_create(size_t capa)
void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data)
rb_id_table_iterator_result
#define IMEMO_TYPE_P(v, t)
@ imemo_ifunc
iterator function
Thin wrapper to ruby/config.h.
Defines RBIMPL_HAS_BUILTIN.
#define INTEGER_PACK_LITTLE_ENDIAN
#define INTEGER_PACK_NEGATIVE
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
VALUE rb_range_new(VALUE, VALUE, int)
VALUE rb_rational_new(VALUE, VALUE)
int rb_reg_options(VALUE)
VALUE rb_str_freeze(VALUE)
VALUE rb_str_concat(VALUE, VALUE)
#define rb_str_new(str, len)
VALUE rb_str_cat(VALUE, const char *, long)
VALUE rb_str_tmp_new(long)
int rb_str_hash_cmp(VALUE, VALUE)
st_index_t rb_str_hash(VALUE)
#define rb_str_new_cstr(str)
VALUE rb_class_name(VALUE)
VALUE rb_ivar_set(VALUE, ID, VALUE)
const char * rb_id2name(ID)
ID rb_intern(const char *)
#define DECIMAL_SIZE_OF_BITS(n)
Internal header for Array.
Internal header for Complex.
Internal header for Encoding.
#define UNALIGNED_MEMBER_PTR(ptr, mem)
Internal header for Hash.
Internal header for Numeric.
int rb_float_cmp(VALUE x, VALUE y)
Internal header for Object.
Internal header for Rational.
VALUE rb_rational_hash(VALUE self)
Internal header for Regexp.
VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline)
#define rb_fstring_lit(str)
VALUE rb_to_symbol_type(VALUE obj)
Internal header for Thread.
#define COVERAGE_TARGET_ONESHOT_LINES
int rb_get_coverage_mode(void)
const void ** rb_vm_get_insns_address_table(void)
#define rb_ary_new_from_args(...)
#define rb_fstring_cstr(...)
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
VALUE rb_iseq_path(const rb_iseq_t *iseq)
void rb_iseq_init_trace(rb_iseq_t *iseq)
void rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq)
rb_iseq_t * rb_iseq_new_with_callback(const struct rb_iseq_new_with_callback_callback_func *ifunc, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, enum iseq_type type, const rb_compile_option_t *option)
void rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
rb_iseq_t * rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth, enum iseq_type type, const rb_compile_option_t *option)
VALUE rb_iseq_defined_string(enum defined_type type)
const rb_iseq_t * rb_iseqw_to_iseq(VALUE iseqw)
const char * ruby_node_name(int node)
VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq)
struct rb_iseq_constant_body * rb_iseq_constant_body_alloc(void)
VALUE rb_iseq_disasm(const rb_iseq_t *iseq)
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
VALUE rb_iseq_realpath(const rb_iseq_t *iseq)
#define ISEQ_LINE_COVERAGE(iseq)
#define ISEQ_COVERAGE(iseq)
#define ISEQ_COVERAGE_SET(iseq, cov)
#define ISEQ_NOT_LOADED_YET
#define ISEQ_MARKABLE_ISEQ
#define ISEQ_BRANCH_COVERAGE(iseq)
#define ISEQ_PC2BRANCHINDEX(iseq)
Internal header for Math.
#define MEMCPY(p1, p2, type, n)
#define ALLOCA_N(type, n)
#define MEMZERO(p, type, n)
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define nd_last_lineno(n)
#define nd_first_lineno(n)
#define nd_first_column(n)
#define NODE_NAMED_REST_P(node)
#define NODE_SPECIAL_REQUIRED_KEYWORD
#define NODE_SPECIAL_NO_REST_KEYWORD
#define nd_last_column(n)
#define NODE_SPECIAL_EXCESSIVE_COMMA
#define RARRAY_AREF(a, i)
void * load(const char *name, size_t *len)
#define RARRAY_CONST_PTR_TRANSIENT
#define Data_Wrap_Struct(klass, mark, free, sval)
#define RB_OBJ_WRITE(a, slot, b)
WB for new reference from ‘a’ to ‘b’.
#define RB_OBJ_WRITTEN(a, oldv, b)
WB for new reference from ‘a’ to ‘b’.
#define StringValuePtr(v)
#define StringValueCStr(v)
#define RTYPEDDATA_DATA(v)
#define TypedData_Get_Struct(obj, type, data_type, sval)
@ RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_WB_PROTECTED
#define TypedData_Make_Struct(klass, type, data_type, sval)
#define RB_INTEGER_TYPE_P(obj)
rb_atomic_t cnt[RUBY_NSIG]
VALUE rb_str_catf(VALUE, const char *,...)
VALUE rb_sprintf(const char *,...)
#define st_init_numtable_with_size
size_t strlen(const char *)
struct ensure_range * next
struct ibf_dump_buffer * current_buffer
struct ibf_dump_buffer global_buffer
ibf_offset_t obj_list_offset
unsigned int obj_list_size
struct ibf_load_buffer global_buffer
struct ibf_load_buffer * current_buffer
const struct ibf_header * header
BDIGIT digits[FLEX_ARY_LEN]
long keyval[FLEX_ARY_LEN]
enum iseq_catch_table_entry::catch_type type
struct iseq_compile_data_ensure_node_stack * prev
struct ensure_range * erange
struct iseq_compile_data_storage * next
struct iseq_insn_data::@2 insn_info
enum ruby_vminsn_type insn_id
enum iseq_link_element::@1 type
struct iseq_link_element * prev
struct iseq_link_element * next
unsigned int ruby2_keywords
const void *const func_ptr
const struct rb_callcache * cc
const struct rb_callinfo * ci
rb_code_position_t beg_pos
rb_code_position_t end_pos
const struct iseq_insn_info_entry * body
struct iseq_catch_table * catch_table
unsigned int ruby2_keywords
unsigned int ambiguous_param0
struct rb_iseq_constant_body::iseq_insn_info insns_info
enum rb_iseq_constant_body::iseq_type type
struct rb_id_table * outer_variables
const struct rb_iseq_constant_body::@188::rb_iseq_param_keyword * keyword
struct rb_iseq_struct * local_iseq
unsigned int local_table_size
struct rb_iseq_constant_body::@188::@190 flags
union iseq_inline_storage_entry * is_entries
rb_iseq_location_t location
struct rb_iseq_constant_body::@189 variable
unsigned int accepts_no_kwarg
struct rb_iseq_constant_body::@188 param
parameter information
const struct rb_iseq_struct * parent_iseq
struct rb_call_data * call_data
rb_code_location_t code_location
void(* func)(rb_iseq_t *, struct iseq_link_anchor *, const void *)
struct rb_iseq_constant_body * body
union rb_iseq_struct::@191 aux
struct rb_iseq_struct::@191::@192 loader
rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
#define VM_CALL_KW_SPLAT_MUT
#define VM_CALL_ARGS_BLOCKARG
#define vm_ci_new(mid, flag, argc, kwarg)
#define VM_CALL_ARGS_SPLAT
#define VM_CALL_ARGS_SIMPLE
@ VM_THROW_NO_ESCAPE_FLAG
#define VM_DEFINECLASS_FLAG_HAS_SUPERCLASS
@ VM_SPECIAL_OBJECT_CBASE
@ VM_SPECIAL_OBJECT_VMCORE
@ VM_SPECIAL_OBJECT_CONST_BASE
#define VM_DEFINECLASS_FLAG_SCOPED
#define RUBY_EVENT_COVERAGE_LINE
struct iseq_inline_constant_cache * IC
#define RUBY_EVENT_COVERAGE_BRANCH
@ VM_DEFINECLASS_TYPE_CLASS
@ VM_DEFINECLASS_TYPE_MODULE
@ VM_DEFINECLASS_TYPE_SINGLETON_CLASS
#define VM_CHECKMATCH_ARRAY
@ VM_CHECKMATCH_TYPE_RESCUE
@ VM_CHECKMATCH_TYPE_CASE
@ VM_CHECKMATCH_TYPE_WHEN
int link(const char *, const char *)
if((ID)(DISPID) nameid !=nameid)
int write(ozstream &zs, const T *x, Items items)
#define ZALLOC(strm, items, size)