mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
Encode iseq node_id with LEB128
Node ids are small non-negative integers (-1 for synthetic instructions), so a LEB128 stores them in 1-2 bytes instead of a 4-byte int. On Shopify's monolith, this reduces the boot heap memsize by 40MB.
This commit is contained in:
1 parent
78a7f126f3
commit
2c09f747ce
4 files changed
+53
-20
Notes:
git
2026-10-25 10:59:39 +00:00
No files matched your search
@@ -2624,6 +2624,19 @@ fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
|
||||
return stack_max;
|
||||
}
|
||||
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
static void
|
||||
add_node_id(uint8_t *node_ids, unsigned int *node_ids_size, int node_id)
|
||||
{
|
||||
uint32_t v = (uint32_t)node_id + 1;
|
||||
do {
|
||||
uint8_t byte = v & 0x7f;
|
||||
v >>= 7;
|
||||
node_ids[(*node_ids_size)++] = v ? (byte | 0x80) : byte;
|
||||
} while (v);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
add_insn_info(struct iseq_insn_info_entry *insns_info, unsigned int *positions,
|
||||
int insns_info_index, int code_index, const INSN *iobj)
|
||||
@@ -2771,7 +2784,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
|
||||
const int positions_size = insn_num;
|
||||
positions = ALLOC_N(unsigned int, insn_num);
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
int *node_ids = ALLOC_N(int, insn_num);
|
||||
uint8_t *node_ids = ALLOC_N(uint8_t, (size_t)insn_num * 5);
|
||||
unsigned int node_ids_size = 0;
|
||||
#endif
|
||||
if (ISEQ_IS_SIZE(body)) {
|
||||
@@ -2952,7 +2965,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
|
||||
}
|
||||
if (add_insn_info(insns_info, positions, insns_info_index, code_index, iobj)) insns_info_index++;
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
node_ids[node_ids_size++] = iobj->insn_info.node_id;
|
||||
add_node_id(node_ids, &node_ids_size, iobj->insn_info.node_id);
|
||||
#endif
|
||||
code_index += len;
|
||||
break;
|
||||
@@ -2990,7 +3003,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
|
||||
}
|
||||
if (add_adjust_info(insns_info, positions, insns_info_index, code_index, adjust)) insns_info_index++;
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
node_ids[node_ids_size++] = -1;
|
||||
add_node_id(node_ids, &node_ids_size, -1);
|
||||
#endif
|
||||
}
|
||||
if (diff > 1) {
|
||||
@@ -3006,7 +3019,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
|
||||
SIZED_FREE_N(insns_info, insns_info_size);
|
||||
SIZED_FREE_N(positions, positions_size);
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
SIZED_FREE_N(node_ids, insns_info_size);
|
||||
SIZED_FREE_N(node_ids, (size_t)insns_info_size * 5);
|
||||
#endif
|
||||
if (ISEQ_MBITS_BUFLEN(code_size) > 1) {
|
||||
SIZED_FREE_N(mark_offset_bits, ISEQ_MBITS_BUFLEN(code_index));
|
||||
@@ -3058,6 +3071,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
|
||||
body->insns_info.positions_or_succ_index_table.positions = positions;
|
||||
body->insns_info.size = insns_info_index;
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
SIZED_REALLOC_N(node_ids, uint8_t, node_ids_size, (size_t)insns_info_size * 5);
|
||||
body->insns_info.node_ids = node_ids;
|
||||
body->insns_info.node_ids_size = node_ids_size;
|
||||
#endif
|
||||
@@ -12800,7 +12814,7 @@ typedef uint32_t ibf_offset_t;
|
||||
|
||||
#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
|
||||
#ifdef RUBY_DEVEL
|
||||
#define IBF_DEVEL_VERSION 10
|
||||
#define IBF_DEVEL_VERSION 11
|
||||
#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
|
||||
#else
|
||||
#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
|
||||
@@ -13528,7 +13542,7 @@ ibf_dump_insns_info_body(struct ibf_dump *dump, const rb_iseq_t *iseq)
|
||||
}
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
if (body->insns_info.node_ids_size > 0) {
|
||||
ibf_dump_write(dump, body->insns_info.node_ids, sizeof(int) * body->insns_info.node_ids_size);
|
||||
ibf_dump_write(dump, body->insns_info.node_ids, body->insns_info.node_ids_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13552,11 +13566,11 @@ ibf_load_insns_info_body(const struct ibf_load *load, ibf_offset_t body_offset,
|
||||
}
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
if (node_ids_size > 0) {
|
||||
if ((size_t)node_ids_size > (load->current_buffer->size - reading_pos) / sizeof(int)) {
|
||||
if (node_ids_size > load->current_buffer->size - reading_pos) {
|
||||
rb_raise(rb_eRuntimeError, "invalid byte sequence");
|
||||
}
|
||||
int *node_ids = ALLOC_N(int, node_ids_size);
|
||||
memcpy(node_ids, load->current_buffer->buff + reading_pos, sizeof(int) * node_ids_size);
|
||||
uint8_t *node_ids = ALLOC_N(uint8_t, node_ids_size);
|
||||
memcpy(node_ids, load->current_buffer->buff + reading_pos, node_ids_size);
|
||||
load_body->insns_info.node_ids = node_ids;
|
||||
load_body->insns_info.node_ids_size = node_ids_size;
|
||||
}
|
||||
|
||||
@@ -597,7 +597,7 @@ rb_iseq_memsize(const rb_iseq_t *iseq)
|
||||
size += body->iseq_size * sizeof(VALUE);
|
||||
size += body->insns_info.size * (sizeof(struct iseq_insn_info_entry) + sizeof(unsigned int));
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
size += body->insns_info.node_ids_size * sizeof(int);
|
||||
size += body->insns_info.node_ids_size;
|
||||
#endif
|
||||
size += body->local_table_size * sizeof(ID); // body->local_table
|
||||
if (!ISEQ_LVAR_STATES_EMBED_P(body->local_table_size) && body->lvar_states.list) {
|
||||
@@ -2578,6 +2578,21 @@ rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
|
||||
}
|
||||
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
static int
|
||||
node_id_stream_read(const uint8_t **ptr, const uint8_t *end)
|
||||
{
|
||||
uint32_t v = 0;
|
||||
unsigned int shift = 0;
|
||||
while (*ptr < end) {
|
||||
uint8_t byte = **ptr;
|
||||
(*ptr)++;
|
||||
v |= (uint32_t)(byte & 0x7f) << shift;
|
||||
if (!(byte & 0x80)) break;
|
||||
shift += 7;
|
||||
}
|
||||
return (int)v - 1;
|
||||
}
|
||||
|
||||
int
|
||||
rb_iseq_node_id(const rb_iseq_t *iseq, size_t pos)
|
||||
{
|
||||
@@ -2587,17 +2602,17 @@ rb_iseq_node_id(const rb_iseq_t *iseq, size_t pos)
|
||||
}
|
||||
|
||||
const VALUE *code = rb_iseq_original_iseq(iseq);
|
||||
const int *node_ids = body->insns_info.node_ids;
|
||||
unsigned int i = 0;
|
||||
const uint8_t *ptr = body->insns_info.node_ids;
|
||||
const uint8_t *end = ptr + body->insns_info.node_ids_size;
|
||||
size_t code_pos = 0;
|
||||
|
||||
while (i < body->insns_info.node_ids_size && code_pos < body->iseq_size) {
|
||||
while (ptr < end && code_pos < body->iseq_size) {
|
||||
size_t len = (size_t)insn_len(code[code_pos]);
|
||||
int node_id = node_id_stream_read(&ptr, end);
|
||||
if (pos < code_pos + len) {
|
||||
return node_ids[i];
|
||||
return node_id;
|
||||
}
|
||||
code_pos += len;
|
||||
i++;
|
||||
}
|
||||
|
||||
VM_ASSERT(0); /* node_ids out of sync with the instruction sequence */
|
||||
@@ -3783,6 +3798,10 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
|
||||
prev_insn_info = NULL;
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
VALUE node_ids = rb_ary_new();
|
||||
/* The node id stream holds one varint per instruction, in the same
|
||||
* order as the instructions in nbody. */
|
||||
const uint8_t *nid_ptr = iseq_body->insns_info.node_ids;
|
||||
const uint8_t *nid_end = nid_ptr ? nid_ptr + iseq_body->insns_info.node_ids_size : NULL;
|
||||
#endif
|
||||
|
||||
for (l=0, pos=0; l<RARRAY_LEN(nbody); l++) {
|
||||
@@ -3796,9 +3815,9 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
|
||||
|
||||
info = get_insn_info(iseq, pos);
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
VM_ASSERT(l < (long)iseq_body->insns_info.node_ids_size);
|
||||
rb_ary_push(node_ids, INT2FIX(l < (long)iseq_body->insns_info.node_ids_size ?
|
||||
iseq_body->insns_info.node_ids[l] : -1));
|
||||
VM_ASSERT(nid_ptr && nid_ptr < nid_end);
|
||||
rb_ary_push(node_ids, INT2FIX(nid_ptr && nid_ptr < nid_end ?
|
||||
node_id_stream_read(&nid_ptr, nid_end) : -1));
|
||||
#endif
|
||||
|
||||
if (prev_insn_info != info) {
|
||||
|
||||
@@ -533,7 +533,7 @@ struct rb_iseq_constant_body {
|
||||
} positions_or_succ_index_table;
|
||||
unsigned int size;
|
||||
#ifdef USE_ISEQ_NODE_ID
|
||||
const int *node_ids;
|
||||
const uint8_t *node_ids;
|
||||
unsigned int node_ids_size;
|
||||
#endif
|
||||
} insns_info;
|
||||
|
||||
Generated
+1
-1
@@ -1276,7 +1276,7 @@ pub struct rb_iseq_constant_body_iseq_insn_info {
|
||||
pub body: *const iseq_insn_info_entry,
|
||||
pub positions_or_succ_index_table: rb_iseq_constant_body_iseq_insn_info__bindgen_ty_1,
|
||||
pub size: ::std::os::raw::c_uint,
|
||||
pub node_ids: *const ::std::os::raw::c_int,
|
||||
pub node_ids: *const u8,
|
||||
pub node_ids_size: ::std::os::raw::c_uint,
|
||||
}
|
||||
#[repr(C)]
|
||||
|
||||
Reference in new issue
Block a user