Make union for positions and succ_index_table in rb_iseq_constant_body

We only use either positions and succ_index_table (when VM_INSN_INFO_TABLE_IMPL == 2,
positions is converted to succ_index_table), so we waste 8 bytes in
rb_iseq_constant_body. This changes it so that they are in a union.
This commit is contained in:
Peter Zhu committed 2026-08-24 22:34:06 +09:00
1 parent 53bc085645
commit b548f16e30
5 files changed
+62 -73
Notes: git 2026-08-24 13:34:39 +00:00

No files matched your search

+22 -36
View File
@@ -983,49 +983,35 @@ define print_lineno
set $index = 0
set $size = $iseq->body->insns_info.size
set $table = $iseq->body->insns_info.body
set $positions = $iseq->body->insns_info.positions
#printf "size: %d\n", $size
if $size == 0
else
if $size == 1
printf "%d", $table[0].line_no
else
if $positions
# get_insn_info_linear_search
set $index = 1
while $index < $size
#printf "table[%d]: position: %d, line: %d, pos: %d\n", $i, $positions[$i], $table[$i].line_no, $pos
if $positions[$index] > $pos
loop_break
end
set $index = $index + 1
if $positions[$index] == $pos
loop_break
end
end
# get_insn_info_succinct_bitvector (VM_INSN_INFO_TABLE_IMPL == 2).
# insns_info.positions and insns_info.succ_index_table share a union, and
# an iseq running on the stack always has succ_index_table.
set $sd = $iseq->body->insns_info.positions_or_succ_index_table.succ_index_table
set $immediate_table_size = sizeof($sd->imm_part) / sizeof(uint64_t) * 9
if $pos < $immediate_table_size
set $i = $pos / 9
set $j = $pos % 9
set $index = ((int)($sd->imm_part[$i] >> ($j * 7))) & 0x7f
else
# get_insn_info_succinct_bitvector
set $sd = $iseq->body->insns_info.succ_index_table
set $immediate_table_size = sizeof($sd->imm_part) / sizeof(uint64_t) * 9
if $pos < $immediate_table_size
set $i = $pos / 9
set $j = $pos % 9
set $index = ((int)($sd->imm_part[$i] >> ($j * 7))) & 0x7f
else
set $block_index = ($pos - $immediate_table_size) / 512
set $block = &$sd->succ_part[$block_index]
set $block_bit_index = ($pos - $immediate_table_size) % 512
set $small_block_index = $block_bit_index / 64
set $small_block_popcount = $small_block_index == 0 ? 0 : (((int)($block->small_block_ranks >> (($small_block_index - 1) * 9))) & 0x1ff)
set $x = $block->bits[$small_block_index] << (63 - $block_bit_index % 64)
set $x = ($x & 0x5555555555555555) + ($x >> 1 & 0x5555555555555555)
set $x = ($x & 0x3333333333333333) + ($x >> 2 & 0x3333333333333333)
set $x = ($x & 0x0707070707070707) + ($x >> 4 & 0x0707070707070707)
set $x = ($x & 0x001f001f001f001f) + ($x >> 8 & 0x001f001f001f001f)
set $x = ($x & 0x0000003f0000003f) + ($x >>16 & 0x0000003f0000003f)
set $popcnt = ($x & 0x7f) + ($x >>32 & 0x7f)
set $index = $block->rank + $small_block_popcount + $popcnt
end
set $block_index = ($pos - $immediate_table_size) / 512
set $block = &$sd->succ_part[$block_index]
set $block_bit_index = ($pos - $immediate_table_size) % 512
set $small_block_index = $block_bit_index / 64
set $small_block_popcount = $small_block_index == 0 ? 0 : (((int)($block->small_block_ranks >> (($small_block_index - 1) * 9))) & 0x1ff)
set $x = $block->bits[$small_block_index] << (63 - $block_bit_index % 64)
set $x = ($x & 0x5555555555555555) + ($x >> 1 & 0x5555555555555555)
set $x = ($x & 0x3333333333333333) + ($x >> 2 & 0x3333333333333333)
set $x = ($x & 0x0707070707070707) + ($x >> 4 & 0x0707070707070707)
set $x = ($x & 0x001f001f001f001f) + ($x >> 8 & 0x001f001f001f001f)
set $x = ($x & 0x0000003f0000003f) + ($x >>16 & 0x0000003f0000003f)
set $popcnt = ($x & 0x7f) + ($x >>32 & 0x7f)
set $index = $block->rank + $small_block_popcount + $popcnt
end
printf "%d", $table[$index-1].line_no
end
+5 -7
View File
@@ -1700,10 +1700,8 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
}
#if VM_INSN_INFO_TABLE_IMPL == 2
if (ISEQ_BODY(iseq)->insns_info.succ_index_table == NULL) {
debugs("[compile step 7 (rb_iseq_insns_info_encode_positions)] \n");
rb_iseq_insns_info_encode_positions(iseq);
}
debugs("[compile step 7 (rb_iseq_insns_info_encode_positions)] \n");
rb_iseq_insns_info_encode_positions(iseq);
#endif
if (compile_debug > 1) {
@@ -2976,12 +2974,12 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
/* get rid of memory leak when REALLOC failed */
body->insns_info.body = insns_info;
body->insns_info.positions = positions;
body->insns_info.positions_or_succ_index_table.positions = positions;
SIZED_REALLOC_N(insns_info, struct iseq_insn_info_entry, insns_info_index, insns_info_size);
body->insns_info.body = insns_info;
SIZED_REALLOC_N(positions, unsigned int, insns_info_index, positions_size);
body->insns_info.positions = positions;
body->insns_info.positions_or_succ_index_table.positions = positions;
body->insns_info.size = insns_info_index;
return COMPILE_OK;
@@ -14044,7 +14042,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->param.keyword = ibf_load_param_keyword(load, param_keyword_offset);
load_body->param.flags.has_kw = (param_flags >> 4) & 1;
load_body->insns_info.body = ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size);
load_body->insns_info.positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size);
load_body->insns_info.positions_or_succ_index_table.positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size);
load_body->local_table = ibf_load_local_table(load, local_table_offset, local_table_size);
load_body->lvar_states = ibf_load_lvar_states(load, lvar_states_offset, local_table_size, load_body->local_table);
ibf_load_catch_table(load, catch_table_offset, catch_table_size, iseq);
+22 -24
View File
@@ -203,9 +203,10 @@ rb_iseq_free(const rb_iseq_t *iseq)
#endif
SIZED_FREE_N(body->iseq_encoded, body->iseq_size);
SIZED_FREE_N(body->insns_info.body, body->insns_info.size);
SIZED_FREE_N(body->insns_info.positions, body->insns_info.size);
#if VM_INSN_INFO_TABLE_IMPL == 2
ruby_xfree(body->insns_info.succ_index_table);
ruby_xfree(body->insns_info.positions_or_succ_index_table.succ_index_table);
#else
SIZED_FREE_N(body->insns_info.positions_or_succ_index_table.positions, body->insns_info.size);
#endif
SIZED_FREE_N(body->is_entries, ISEQ_IS_SIZE(body));
SIZED_FREE_N(body->call_data, body->ci_size);
@@ -806,13 +807,10 @@ rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq)
struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
int size = body->insns_info.size;
int max_pos = body->iseq_size;
int *data = (int *)body->insns_info.positions;
if (body->insns_info.succ_index_table) ruby_xfree(body->insns_info.succ_index_table);
body->insns_info.succ_index_table = succ_index_table_create(max_pos, data, size);
#if VM_CHECK_MODE == 0
SIZED_FREE_N(body->insns_info.positions, body->insns_info.size);
body->insns_info.positions = NULL;
#endif
unsigned int *positions = body->insns_info.positions_or_succ_index_table.positions;
struct succ_index_table *sd = succ_index_table_create(max_pos, (int *)positions, size);
SIZED_FREE_N(positions, size);
body->insns_info.positions_or_succ_index_table.succ_index_table = sd;
#endif
}
@@ -822,7 +820,7 @@ rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body)
{
int size = body->insns_info.size;
int max_pos = body->iseq_size;
struct succ_index_table *sd = body->insns_info.succ_index_table;
struct succ_index_table *sd = body->insns_info.positions_or_succ_index_table.succ_index_table;
return succ_index_table_invert(max_pos, sd, size);
}
#endif
@@ -2364,7 +2362,7 @@ get_insn_info_binary_search(const rb_iseq_t *iseq, size_t pos)
const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
size_t size = body->insns_info.size;
const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
const unsigned int *positions = body->insns_info.positions;
const unsigned int *positions = body->insns_info.positions_or_succ_index_table.positions;
const int debug = 0;
if (debug) {
@@ -2420,16 +2418,9 @@ get_insn_info_succinct_bitvector(const rb_iseq_t *iseq, size_t pos)
const int debug = 0;
if (debug) {
#if VM_CHECK_MODE > 0
const unsigned int *positions = body->insns_info.positions;
printf("size: %"PRIuSIZE"\n", size);
printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
(size_t)0, positions[0], insns_info[0].line_no, pos);
#else
printf("size: %"PRIuSIZE"\n", size);
printf("insns_info[%"PRIuSIZE"]: line: %d, pos: %"PRIuSIZE"\n",
(size_t)0, insns_info[0].line_no, pos);
#endif
}
if (size == 0) {
@@ -2440,8 +2431,8 @@ get_insn_info_succinct_bitvector(const rb_iseq_t *iseq, size_t pos)
}
else {
int index;
VM_ASSERT(body->insns_info.succ_index_table != NULL);
index = succ_index_lookup(body->insns_info.succ_index_table, (int)pos);
VM_ASSERT(body->insns_info.positions_or_succ_index_table.succ_index_table != NULL);
index = succ_index_lookup(body->insns_info.positions_or_succ_index_table.succ_index_table, (int)pos);
return &insns_info[index-1];
}
}
@@ -2455,12 +2446,11 @@ get_insn_info(const rb_iseq_t *iseq, size_t pos)
#if VM_CHECK_MODE > 0 || VM_INSN_INFO_TABLE_IMPL == 0
static const struct iseq_insn_info_entry *
get_insn_info_linear_search(const rb_iseq_t *iseq, size_t pos)
get_insn_info_linear_search(const rb_iseq_t *iseq, const unsigned int *positions, size_t pos)
{
const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
size_t i = 0, size = body->insns_info.size;
const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
const unsigned int *positions = body->insns_info.positions;
const int debug = 0;
if (debug) {
@@ -2496,7 +2486,7 @@ get_insn_info_linear_search(const rb_iseq_t *iseq, size_t pos)
static const struct iseq_insn_info_entry *
get_insn_info(const rb_iseq_t *iseq, size_t pos)
{
return get_insn_info_linear_search(iseq, pos);
return get_insn_info_linear_search(iseq, ISEQ_BODY(iseq)->insns_info.positions_or_succ_index_table.positions, pos);
}
#endif
@@ -2506,11 +2496,19 @@ validate_get_insn_info(const rb_iseq_t *iseq)
{
const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
size_t i;
#if VM_INSN_INFO_TABLE_IMPL == 2
unsigned int *positions = rb_iseq_insns_info_decode_positions(body);
#else
const unsigned int *positions = body->insns_info.positions_or_succ_index_table.positions;
#endif
for (i = 0; i < body->iseq_size; i++) {
if (get_insn_info_linear_search(iseq, i) != get_insn_info(iseq, i)) {
if (get_insn_info_linear_search(iseq, positions, i) != get_insn_info(iseq, i)) {
rb_bug("validate_get_insn_info: get_insn_info_linear_search(iseq, %"PRIuSIZE") != get_insn_info(iseq, %"PRIuSIZE")", i, i);
}
}
#if VM_INSN_INFO_TABLE_IMPL == 2
SIZED_FREE_N(positions, body->insns_info.size);
#endif
}
#endif
+5 -3
View File
@@ -504,11 +504,13 @@ struct rb_iseq_constant_body {
/* insn info, must be freed */
struct iseq_insn_info {
const struct iseq_insn_info_entry *body;
unsigned int *positions;
unsigned int size;
union {
unsigned int *positions;
#if VM_INSN_INFO_TABLE_IMPL == 2
struct succ_index_table *succ_index_table;
struct succ_index_table *succ_index_table;
#endif
} positions_or_succ_index_table;
unsigned int size;
} insns_info;
const ID *local_table; /* must free */
+8 -3
View File
@@ -1260,11 +1260,16 @@ pub struct rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword {
pub default_values: *mut VALUE,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[derive(Copy, Clone)]
pub struct rb_iseq_constant_body_iseq_insn_info {
pub body: *const iseq_insn_info_entry,
pub positions: *mut ::std::os::raw::c_uint,
pub positions_or_succ_index_table: rb_iseq_constant_body_iseq_insn_info__bindgen_ty_1,
pub size: ::std::os::raw::c_uint,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union rb_iseq_constant_body_iseq_insn_info__bindgen_ty_1 {
pub positions: *mut ::std::os::raw::c_uint,
pub succ_index_table: *mut succ_index_table,
}
#[repr(C)]
@@ -2094,7 +2099,7 @@ pub struct zjit_jit_frame {
pub stack: __IncompleteArrayField<VALUE>,
}
pub const ISEQ_BODY_OFFSET_PARAM: zjit_struct_offsets = 16;
pub const ISEQ_BODY_OFFSET_OUTER_VARIABLES: zjit_struct_offsets = 288;
pub const ISEQ_BODY_OFFSET_OUTER_VARIABLES: zjit_struct_offsets = 280;
pub const RUBY_OFFSET_THREAD_RACTOR: zjit_struct_offsets = 24;
pub type zjit_struct_offsets = u32;
#[repr(C)]