20 #define RUBY_VM_INSNS_INFO 1
29 #include "insns_info.inc"
36 #if VM_INSN_INFO_TABLE_IMPL == 2
38 static unsigned int *succ_index_table_invert(
int max_pos,
struct succ_index_table *sd,
int size);
42 #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass)
45 obj_resurrect(
VALUE obj)
93 if (iseq && iseq->
body) {
99 #if VM_INSN_INFO_TABLE_IMPL == 2
122 compile_data_free(ISEQ_COMPILE_DATA(iseq));
133 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
135 rb_vm_insn_addr2insn2(
const void *addr)
142 rb_vm_insn_null_translator(
const void *addr)
153 VALUE insn = translator((
void *)code[pos]);
154 int len = insn_len(insn);
156 const char *
types = insn_op_types(insn);
158 for (op_no = 0;
types[op_no]; op_no++) {
165 VALUE op = code[pos + op_no + 1];
167 VALUE newop = func(data, op);
169 code[pos + op_no + 1] = newop;
200 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
203 rb_vm_insn_null_translator;
209 for (n = 0; n <
size;) {
210 n += iseq_extract_values(code, n, func, data, translator);
215 update_each_insn_value(
void *ctx,
VALUE obj)
238 rb_iseq_each_value(iseq, update_each_insn_value,
NULL);
239 VALUE *original_iseq = ISEQ_ORIGINAL_ISEQ(iseq);
244 n += iseq_extract_values(original_iseq, n, update_each_insn_value,
NULL, rb_vm_insn_null_translator);
263 struct iseq_catch_table *table = body->
catch_table;
265 for (i = 0; i < table->size; i++) {
274 mjit_update_references(
iseq);
280 each_insn_value(
void *ctx,
VALUE obj)
297 rb_iseq_each_value(iseq, each_insn_value,
NULL);
307 if (body->
param.
flags.has_kw && ISEQ_COMPILE_DATA(iseq) ==
NULL) {
308 const struct rb_iseq_param_keyword *
const keyword = body->
param.
keyword;
311 i = keyword->required_num;
313 for (j = 0; i < keyword->num; i++, j++) {
314 VALUE obj = keyword->default_values[j];
322 const struct iseq_catch_table *table = body->
catch_table;
324 for (i = 0; i < table->size; i++) {
351 if (iseq->
aux.
exec.local_hooks) {
360 param_keyword_size(
const struct rb_iseq_param_keyword *pkw)
364 if (!pkw)
return size;
366 size +=
sizeof(
struct rb_iseq_param_keyword);
367 size +=
sizeof(
VALUE) * (pkw->num - pkw->required_num);
414 compile_data = ISEQ_COMPILE_DATA(iseq);
430 static uintptr_t fresh_iseq_unique_id = 0;
456 if (path == realpath ||
553 set_relation(iseq, parent);
556 iseq_location_setup(iseq,
name, path, realpath, first_lineno, code_location, node_id);
561 ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
564 ISEQ_COMPILE_DATA_ALLOC(iseq);
565 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info);
568 ISEQ_COMPILE_DATA(iseq)->node.storage_head = ISEQ_COMPILE_DATA(iseq)->node.storage_current = new_arena();
569 ISEQ_COMPILE_DATA(iseq)->insn.storage_head = ISEQ_COMPILE_DATA(iseq)->insn.storage_current = new_arena();
570 ISEQ_COMPILE_DATA(iseq)->option = option;
572 ISEQ_COMPILE_DATA(iseq)->ivar_cache_table =
NULL;
574 ISEQ_COMPILE_DATA(iseq)->builtin_function_table =
GET_VM()->builtin_function_table;
578 if (
RTEST(coverages)) {
590 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
591 static void validate_get_insn_info(
const rb_iseq_t *iseq);
597 #if VM_INSN_INFO_TABLE_IMPL == 2
604 #if VM_CHECK_MODE == 0
611 #if VM_INSN_INFO_TABLE_IMPL == 2
618 return succ_index_table_invert(max_pos, sd,
size);
625 iseq->
aux.
exec.global_trace_events = 0;
637 ISEQ_COMPILE_DATA_CLEAR(iseq);
638 compile_data_free(data);
640 #if VM_INSN_INFO_TABLE_IMPL == 2
647 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
648 validate_get_insn_info(iseq);
680 #define SET_COMPILE_OPTION(o, h, mem) \
681 { VALUE flag = rb_hash_aref((h), ID2SYM(rb_intern(#mem))); \
682 if (flag == Qtrue) { (o)->mem = 1; } \
683 else if (flag == Qfalse) { (o)->mem = 0; } \
685 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
686 { VALUE num = rb_hash_aref(opt, ID2SYM(rb_intern(#mem))); \
687 if (!NIL_P(num)) (o)->mem = NUM2INT(num); \
700 #undef SET_COMPILE_OPTION
701 #undef SET_COMPILE_OPTION_NUM
708 set_compile_option_from_hash(option, opt);
715 *option = COMPILE_OPTION_DEFAULT;
718 *option = COMPILE_OPTION_FALSE;
720 else if (opt ==
Qtrue) {
723 ((
int *)option)[i] = 1;
726 *option = COMPILE_OPTION_DEFAULT;
727 set_compile_option_from_hash(option, opt);
738 #define SET_COMPILE_OPTION(o, h, mem) \
739 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse)
740 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
741 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem))
755 #undef SET_COMPILE_OPTION
756 #undef SET_COMPILE_OPTION_NUM
765 &COMPILE_OPTION_DEFAULT);
772 if (
RTEST(coverages)) {
781 &COMPILE_OPTION_DEFAULT);
796 VALUE v1 = iseqw_new(iseq);
811 const NODE *node = ast ? ast->
root : 0;
816 new_opt = option ? *option : COMPILE_OPTION_DEFAULT;
819 prepare_iseq_build(iseq,
name, path, realpath, first_lineno, node ? &node->
nd_loc :
NULL, node ?
nd_node_id(node) : -1, parent,
type, &new_opt);
822 finish_iseq_build(iseq);
824 return iseq_translate(iseq);
837 if (!option) option = &COMPILE_OPTION_DEFAULT;
838 prepare_iseq_build(iseq,
name, path, realpath, first_lineno,
NULL, -1, parent,
type, option);
841 finish_iseq_build(iseq);
843 return iseq_translate(iseq);
852 return iseqw_check(iseqv);
858 #define CHECK_ARRAY(v) rb_to_array_type(v)
859 #define CHECK_HASH(v) rb_to_hash_type(v)
860 #define CHECK_STRING(v) rb_str_to_str(v)
861 #define CHECK_SYMBOL(v) rb_to_symbol_type(v)
896 VALUE magic, version1, version2, format_type, misc;
897 VALUE name, path, realpath, first_lineno, code_location, node_id;
898 VALUE type, body, locals, params, exception;
917 ((void)magic, (
void)version1, (void)version2, (
void)format_type);
948 make_compile_option(&option, opt);
950 prepare_iseq_build(iseq,
name, path, realpath, first_lineno, &tmp_loc,
NUM2INT(node_id),
955 finish_iseq_build(iseq);
957 return iseqw_new(iseq);
968 return iseq_load(data,
NULL, opt);
982 #if !defined(__GNUC__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 8)
983 # define INITIALIZED volatile
992 make_compile_option(&option, opt);
1009 ast = (*parse)(parser, file, src, ln);
1012 if (!ast->body.root) {
1092 remove_coverage_i(
void *vstart,
void *vend,
size_t stride,
void *data)
1095 for (; v != (
VALUE)vend; v += stride) {
1096 void *
ptr = asan_poisoned_object_p(v);
1097 asan_unpoison_object(v,
false);
1099 if (rb_obj_is_iseq(v)) {
1118 iseqw_mark(
void *
ptr)
1124 iseqw_memsize(
const void *
ptr)
1131 {iseqw_mark,
NULL, iseqw_memsize,},
1142 union {
const rb_iseq_t *in;
void *out; } deconst;
1159 return iseqw_new(iseq);
1204 case 5: opt =
argv[--i];
1205 case 4: line =
argv[--i];
1206 case 3: path =
argv[--i];
1207 case 2: file =
argv[--i];
1211 if (
NIL_P(path)) path = file;
1217 return iseqw_new(rb_iseq_compile_with_option(src, file, path, line, opt));
1252 case 2: opt =
argv[--i];
1270 make_compile_option(&option, opt);
1275 line,
NULL, ISEQ_TYPE_TOP, &option));
1312 iseqw_s_compile_option_set(
VALUE self,
VALUE opt)
1315 make_compile_option(&option, opt);
1316 COMPILE_OPTION_DEFAULT = option;
1329 iseqw_s_compile_option_get(
VALUE self)
1331 return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
1335 iseqw_check(
VALUE iseqw)
1352 return iseqw_check(iseqw);
1364 iseqw_eval(
VALUE self)
1374 iseqw_inspect(
VALUE self)
1376 const rb_iseq_t *iseq = iseqw_check(
self);
1415 iseqw_path(
VALUE self)
1437 iseqw_absolute_path(
VALUE self)
1466 iseqw_label(
VALUE self)
1492 iseqw_base_label(
VALUE self)
1508 iseqw_first_lineno(
VALUE self)
1597 iseqw_to_a(
VALUE self)
1599 const rb_iseq_t *iseq = iseqw_check(
self);
1600 return iseq_data_to_ary(iseq);
1603 #if VM_INSN_INFO_TABLE_IMPL == 1
1605 get_insn_info_binary_search(
const rb_iseq_t *iseq,
size_t pos)
1611 const int debug = 0;
1615 printf(
"insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1616 (
size_t)0, positions[0], insns_info[0].
line_no, pos);
1622 else if (
size == 1) {
1623 return &insns_info[0];
1626 size_t l = 1, r =
size - 1;
1628 size_t m = l + (r - l) / 2;
1629 if (positions[m] == pos) {
1630 return &insns_info[m];
1632 if (positions[m] < pos) {
1640 return &insns_info[
size-1];
1642 if (positions[l] > pos) {
1643 return &insns_info[l-1];
1645 return &insns_info[l];
1650 get_insn_info(
const rb_iseq_t *iseq,
size_t pos)
1652 return get_insn_info_binary_search(iseq, pos);
1656 #if VM_INSN_INFO_TABLE_IMPL == 2
1658 get_insn_info_succinct_bitvector(
const rb_iseq_t *iseq,
size_t pos)
1663 const int debug = 0;
1666 #if VM_CHECK_MODE > 0
1669 printf(
"insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1670 (
size_t)0, positions[0], insns_info[0].
line_no, pos);
1674 (
size_t)0, insns_info[0].
line_no, pos);
1681 else if (
size == 1) {
1682 return &insns_info[0];
1688 return &insns_info[index-1];
1693 get_insn_info(
const rb_iseq_t *iseq,
size_t pos)
1695 return get_insn_info_succinct_bitvector(iseq, pos);
1699 #if VM_CHECK_MODE > 0 || VM_INSN_INFO_TABLE_IMPL == 0
1701 get_insn_info_linear_search(
const rb_iseq_t *iseq,
size_t pos)
1707 const int debug = 0;
1711 printf(
"insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1712 i, positions[i], insns_info[i].
line_no, pos);
1718 else if (
size == 1) {
1719 return &insns_info[0];
1722 for (i=1; i<
size; i++) {
1724 i, positions[i], insns_info[i].
line_no, pos);
1726 if (positions[i] == pos) {
1727 return &insns_info[i];
1729 if (positions[i] > pos) {
1730 return &insns_info[i-1];
1734 return &insns_info[i-1];
1738 #if VM_INSN_INFO_TABLE_IMPL == 0
1740 get_insn_info(
const rb_iseq_t *iseq,
size_t pos)
1742 return get_insn_info_linear_search(iseq, pos);
1746 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
1748 validate_get_insn_info(
const rb_iseq_t *iseq)
1753 if (get_insn_info_linear_search(iseq, i) != get_insn_info(iseq, i)) {
1754 rb_bug(
"validate_get_insn_info: get_insn_info_linear_search(iseq, %"PRIuSIZE") != get_insn_info(iseq, %"PRIuSIZE")", i, i);
1791 if (!(entry->
events & iseq->
aux.
exec.global_trace_events)) {
1806 for (i = 0; i < level; i++) {
1832 const char *
types = insn_op_types(insn);
1842 if (insn == BIN(defined) && op_no == 0) {
1860 else if (insn == BIN(checktype) && op_no == 0) {
1871 if (
types[op_no+1] == TS_NUM && pnop) {
1887 op = obj_resurrect(op);
1888 if (insn == BIN(defined) && op_no == 1 &&
FIXNUM_P(op)) {
1956 # define CALL_FLAG(n) if (ci->flag & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n))
1984 if (dladdr((
void *)op, &info) && info.dli_sname) {
2011 while (end-- > beg && *end ==
' ');
2024 VALUE insn = code[pos];
2025 int len = insn_len(insn);
2027 const char *
types = insn_op_types(insn);
2029 const char *insn_name_buff;
2031 insn_name_buff = insn_name(insn);
2033 extern const int rb_vm_max_insn_name_size;
2038 (
int)strcspn(insn_name_buff,
"_"), insn_name_buff);
2041 for (j = 0;
types[j]; j++) {
2043 len, pos, &code[pos + j + 2],
2055 if (line_no && line_no != prev) {
2057 slen = (slen > 70) ? 0 : (70 - slen);
2092 catch_type(
int type)
2095 case CATCH_TYPE_RESCUE:
2097 case CATCH_TYPE_ENSURE:
2099 case CATCH_TYPE_RETRY:
2101 case CATCH_TYPE_BREAK:
2103 case CATCH_TYPE_REDO:
2105 case CATCH_TYPE_NEXT:
2149 enum {header_minlen = 72};
2152 const char *indent_str;
2184 "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
2186 (
int)entry->
end, (
int)entry->
sp, (
int)entry->
cont);
2203 "-----------------------------------\n");
2208 const struct rb_iseq_param_keyword *
const keyword = body->
param.
keyword;
2211 "local table (size: %d, argc: %d "
2212 "[opts: %d, rest: %d, post: %d, block: %d, kw: %d@%d, kwrest: %d])\n",
2219 body->
param.
flags.has_kw ? keyword->num : -1,
2220 body->
param.
flags.has_kw ? keyword->required_num : -1,
2221 body->
param.
flags.has_kwrest ? keyword->rest_start : -1);
2226 VALUE name = local_var_name(iseq, 0, i);
2234 if (li >=
argc && li <
argc + opts) {
2240 snprintf(argi,
sizeof(argi),
"%s%s%s%s%s%s",
2245 (body->
param.
flags.has_kwrest && keyword->rest_start == li) ?
"Kwrest" :
"",
2260 for (n = 0; n <
size;) {
2280 return rb_iseq_disasm_recursive(iseq,
rb_str_new(0, 0));
2302 iseqw_disasm(
VALUE self)
2308 iseq_iterate_children(
const rb_iseq_t *iseq,
void (*iter_func)(
const rb_iseq_t *child_iseq,
void *data),
void *data)
2320 child = entry->
iseq;
2324 (*iter_func)(child, data);
2331 VALUE insn = code[i];
2332 int len = insn_len(insn);
2333 const char *
types = insn_op_types(insn);
2336 for (j=0;
types[j]; j++) {
2343 (*iter_func)(child, data);
2358 yield_each_children(
const rb_iseq_t *child_iseq,
void *data)
2372 iseqw_each_child(
VALUE self)
2375 iseq_iterate_children(
iseq, yield_each_children,
NULL);
2382 #define C(ev, cstr, l) if (events & ev) rb_ary_push(ary, rb_ary_new_from_args(2, l, ID2SYM(rb_intern(cstr))));
2401 iseqw_trace_points(
VALUE self)
2458 iseq = vm_proc_iseq(body);
2460 if (!rb_obj_is_iseq((
VALUE)iseq)) {
2471 return iseq ? iseqw_new(iseq) :
Qnil;
2529 VALUE iseqw = iseqw_s_of(klass, body);
2537 #include "node_name.inc"
2539 rb_bug(
"unknown node: %d", node);
2544 #define DECL_SYMBOL(name) \
2545 static ID sym_##name
2547 #define INIT_SYMBOL(name) \
2548 sym_##name = rb_intern(#name)
2551 register_label(
struct st_table *table,
unsigned long idx)
2563 case CATCH_TYPE_RESCUE:
CONST_ID(
id,
"rescue");
break;
2564 case CATCH_TYPE_ENSURE:
CONST_ID(
id,
"ensure");
break;
2565 case CATCH_TYPE_RETRY:
CONST_ID(
id,
"retry");
break;
2566 case CATCH_TYPE_BREAK:
CONST_ID(
id,
"break");
break;
2567 case CATCH_TYPE_REDO:
CONST_ID(
id,
"redo");
break;
2568 case CATCH_TYPE_NEXT:
CONST_ID(
id,
"next");
break;
2570 rb_bug(
"unknown exception type: %d", (
int)
type);
2598 VALUE *seq, *iseq_original;
2609 static ID insn_syms[VM_INSTRUCTION_SIZE/2];
2625 for (i=0; i<
numberof(insn_syms); i++) {
2640 switch (iseq_body->
type) {
2641 case ISEQ_TYPE_TOP:
type = sym_top;
break;
2642 case ISEQ_TYPE_METHOD:
type = sym_method;
break;
2643 case ISEQ_TYPE_BLOCK:
type = sym_block;
break;
2644 case ISEQ_TYPE_CLASS:
type = sym_class;
break;
2645 case ISEQ_TYPE_RESCUE:
type = sym_rescue;
break;
2646 case ISEQ_TYPE_ENSURE:
type = sym_ensure;
break;
2647 case ISEQ_TYPE_EVAL:
type = sym_eval;
break;
2648 case ISEQ_TYPE_MAIN:
type = sym_main;
break;
2649 case ISEQ_TYPE_PLAIN:
type = sym_plain;
break;
2650 default:
rb_bug(
"unsupported iseq type: %d", (
int)iseq_body->
type);
2671 const struct rb_iseq_param_keyword *
const keyword = iseq_body->
param.
keyword;
2678 for (j = 0; j <
len; j++) {
2694 for (i=0; i<keyword->required_num; i++) {
2697 for (j=0; i<keyword->num; i++, j++) {
2699 if (keyword->default_values[j] !=
Qundef) {
2706 INT2FIX(keyword->bits_start));
2716 for (seq = iseq_original; seq < iseq_original + iseq_body->
iseq_size; ) {
2717 VALUE insn = *seq++;
2718 int j,
len = insn_len(insn);
2723 for (j=0; j<
len-1; j++, seq++) {
2724 switch (insn_op_type(insn, j)) {
2726 unsigned long idx = nseq - iseq_original + *seq;
2727 rb_ary_push(ary, register_label(labels_table, idx));
2741 VALUE val = iseq_data_to_ary(rb_iseq_check(iseq));
2803 unsigned long idx = nseq - iseq_original + pos;
2806 register_label(labels_table, idx));
2813 #if SIZEOF_VALUE <= SIZEOF_LONG
2824 #if SIZEOF_VALUE <= SIZEOF_LONG
2837 rb_bug(
"unknown operand: %c", insn_op_type(insn, j));
2866 prev_insn_info =
NULL;
2873 if (
st_lookup(labels_table, pos, &label)) {
2877 info = get_insn_info(iseq, pos);
2879 if (prev_insn_info != info) {
2883 if (line > 0 && last_line != line) {
2887 #define CHECK_EVENT(ev) if (events & ev) rb_ary_push(body, ID2SYM(rb_intern(#ev)));
2896 prev_insn_info = info;
2943 const struct rb_iseq_param_keyword *
const keyword = body->
param.
keyword;
2945 ID req, opt, rest, block,
key, keyrest;
2946 #define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
2947 #define PARAM_ID(i) body->local_table[(i)]
2948 #define PARAM(i, type) ( \
2950 rb_id2str(PARAM_ID(i)) ? \
2951 rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
2969 for (; i < r; i++) {
3001 if (keyword->required_num > 0) {
3004 for (; i < keyword->required_num; i++) {
3013 for (; i < keyword->num; i++) {
3035 static const char expr_names[][18] = {
3037 "instance-variable",
3054 if ((
unsigned)(
type - 1) >= (
unsigned)
numberof(expr_names))
return 0;
3055 estr = expr_names[
type - 1];
3056 if (!estr[0])
return 0;
3057 defs =
GET_VM()->defined_strings;
3060 GET_VM()->defined_strings = defs;
3075 static st_table *encoded_insn_data;
3082 static insn_data_t insn_data[VM_INSTRUCTION_SIZE/2];
3087 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
3089 #define INSN_CODE(insn) ((VALUE)table[insn])
3091 #define INSN_CODE(insn) (insn)
3096 for (insn = 0; insn < VM_INSTRUCTION_SIZE/2; insn++) {
3097 int traced_insn = insn;
3098 if (traced_insn == BIN(opt_invokebuiltin_delegate_leave)) {
3099 traced_insn = BIN(opt_invokebuiltin_delegate);
3104 insn_data[insn].
insn = (int)insn;
3105 insn_data[insn].
insn_len = insn_len(insn);
3122 return (
int)e->
insn;
3125 rb_bug(
"rb_vm_insn_addr2insn: invalid insn address: %p", addr);
3140 rb_bug(
"trace_instrument: invalid insn address: %p", (
void *)*iseq_encoded_insn);
3165 unsigned int line = (int)entry->
line_no;
3167 if (target_line == 0 || target_line == line) {
3174 if (pc_events & target_events) {
3177 pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->
aux.
exec.global_trace_events));
3198 iseq_add_local_tracepoint_i(
const rb_iseq_t *iseq,
void *p)
3202 iseq_iterate_children(iseq, iseq_add_local_tracepoint_i, p);
3214 iseq_add_local_tracepoint_i(iseq, (
void *)&data);
3224 if (iseq->
aux.
exec.local_hooks) {
3231 local_events = iseq->
aux.
exec.local_hooks->events;
3233 if (local_events == 0) {
3234 if (iseq->
aux.
exec.local_hooks->running == 0) {
3242 pc += encoded_iseq_trace_instrument(&
iseq_encoded[pc], pc_events & (local_events | iseq->
aux.
exec.global_trace_events));
3254 iseq_remove_local_tracepoint_i(
const rb_iseq_t *iseq,
void *p)
3257 data->
n += iseq_remove_local_tracepoint(iseq, data->
tpval);
3258 iseq_iterate_children(iseq, iseq_remove_local_tracepoint_i, p);
3268 iseq_remove_local_tracepoint_i(iseq, (
void *)&data);
3275 if (iseq->
aux.
exec.global_trace_events == turnon_events) {
3289 ((
rb_iseq_t *)iseq)->aux.exec.global_trace_events = turnon_events;
3290 enabled_events = turnon_events | local_events;
3294 pc += encoded_iseq_trace_instrument(&
iseq_encoded[pc], pc_events & enabled_events);
3300 trace_set_i(
void *vstart,
void *vend,
size_t stride,
void *data)
3305 for (; v != (
VALUE)vend; v += stride) {
3306 void *
ptr = asan_poisoned_object_p(v);
3307 asan_unpoison_object(v,
false);
3309 if (rb_obj_is_iseq(v)) {
3385 #if VM_INSN_INFO_TABLE_IMPL == 2
3418 #define IMMEDIATE_TABLE_SIZE 54
3429 #define imm_block_rank_set(v, i, r) (v) |= (uint64_t)(r) << (7 * (i))
3430 #define imm_block_rank_get(v, i) (((int)((v) >> ((i) * 7))) & 0x7f)
3431 #define small_block_rank_set(v, i, r) (v) |= (uint64_t)(r) << (9 * ((i) - 1))
3432 #define small_block_rank_get(v, i) ((i) == 0 ? 0 : (((int)((v) >> (((i) - 1) * 9))) & 0x1ff))
3435 succ_index_table_create(
int max_pos,
int *data,
int size)
3442 succ_size,
sizeof(
struct succ_dict_block));
3446 for (j = 0; j < imm_size; j++) {
3447 for (i = 0; i < 9; i++) {
3448 if (r <
size && data[r] == j * 9 + i) r++;
3452 for (k = 0; k < succ_size; k++) {
3453 struct succ_dict_block *sd_block = &sd->
succ_part[k];
3456 for (j = 0; j < 8; j++) {
3459 for (i = 0; i < 64; i++) {
3465 sd_block->bits[j] = bits;
3466 small_rank += rb_popcount64(bits);
3472 static unsigned int *
3477 unsigned int *positions =
ALLOC_N(
unsigned int,
size), *p;
3478 int i, j, k, r = -1;
3480 for (j = 0; j < imm_size; j++) {
3481 for (i = 0; i < 9; i++) {
3483 if (r != nr) *p++ = j * 9 + i;
3487 for (k = 0; k < succ_size; k++) {
3488 for (j = 0; j < 8; j++) {
3489 for (i = 0; i < 64; i++) {
3503 const int i = x / 9;
3504 const int j = x % 9;
3509 const struct succ_dict_block *block = &sd->
succ_part[block_index];
3511 const int small_block_index = block_bit_index / 64;
3512 const int small_block_popcount =
small_block_rank_get(block->small_block_ranks, small_block_index);
3513 const int popcnt = rb_popcount64(block->bits[small_block_index] << (63 - block_bit_index % 64));
3515 return block->rank + small_block_popcount + popcnt;