Remove has_source_hash from iseq_body

We can use a special value of 0 in source_hash to denote that it does not
have source_hash. This removes the has_source_hash field which saves us 8
bytes per iseq.
This commit is contained in:
Peter Zhu committed 2026-08-21 08:35:40 +09:00
1 parent ba269a0e9f
commit ae574e7219
5 files changed
+15 -19
Notes: git 2026-08-20 23:36:12 +00:00

No files matched your search

+5 -10
View File
@@ -1506,7 +1506,7 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node,
// The child AST wrapper does not carry the source hash, so copy it from
// the enclosing iseq before compiling, for grandchildren to inherit it.
if (ISEQ_BODY(iseq)->has_source_hash) {
if (ISEQ_BODY(iseq)->source_hash) {
rb_ast_t *child_ast = rb_ruby_ast_data_get(ast_value);
child_ast->body.source_hash = ISEQ_BODY(iseq)->source_hash;
child_ast->body.has_source_hash = 1;
@@ -12481,7 +12481,6 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
VALUE source_hash = rb_hash_aref(misc, ID2SYM(rb_intern("source_hash")));
if (!NIL_P(source_hash)) {
ISEQ_BODY(iseq)->source_hash = NUM2ULL(source_hash);
ISEQ_BODY(iseq)->has_source_hash = true;
}
VALUE node_ids = Qfalse;
@@ -13790,12 +13789,10 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
ibf_dump_write_small_value(dump, location_label_index);
ibf_dump_write_small_value(dump, body->location.first_lineno);
ibf_dump_write_small_value(dump, body->location.node_id);
/* Dump the source hash in two 32-bit halves, because VALUE may be
* 32 bits wide. */
uint64_t source_hash = body->has_source_hash ? body->source_hash : 0;
ibf_dump_write_small_value(dump, (VALUE)(uint32_t)(source_hash >> 32));
ibf_dump_write_small_value(dump, (VALUE)(uint32_t)source_hash);
ibf_dump_write_small_value(dump, body->has_source_hash ? 1 : 0);
/* Dump the source hash (0 if unavailable) in two 32-bit halves, because
* VALUE may be 32 bits wide. */
ibf_dump_write_small_value(dump, (VALUE)(uint32_t)(body->source_hash >> 32));
ibf_dump_write_small_value(dump, (VALUE)(uint32_t)body->source_hash);
ibf_dump_write_small_value(dump, body->location.code_location.beg_pos.lineno);
ibf_dump_write_small_value(dump, body->location.code_location.beg_pos.column);
ibf_dump_write_small_value(dump, body->location.code_location.end_pos.lineno);
@@ -13911,7 +13908,6 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
const uint64_t source_hash_hi = (uint64_t)ibf_load_small_value(load, &reading_pos);
const uint64_t source_hash_lo = (uint64_t)ibf_load_small_value(load, &reading_pos);
const uint64_t source_hash = (source_hash_hi << 32) | (uint32_t)source_hash_lo;
const bool has_source_hash = ibf_load_small_value(load, &reading_pos) != 0;
const int location_code_location_beg_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
const int location_code_location_beg_pos_column = (int)ibf_load_small_value(load, &reading_pos);
const int location_code_location_end_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
@@ -14013,7 +14009,6 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->location.first_lineno = location_first_lineno;
load_body->location.node_id = location_node_id;
load_body->source_hash = source_hash;
load_body->has_source_hash = has_source_hash;
load_body->location.code_location.beg_pos.lineno = location_code_location_beg_pos_lineno;
load_body->location.code_location.beg_pos.column = location_code_location_beg_pos_column;
load_body->location.code_location.end_pos.lineno = location_code_location_end_pos_lineno;
+4 -4
View File
@@ -1140,7 +1140,7 @@ rb_iseq_new_with_opt(VALUE ast_value, VALUE name, VALUE path, VALUE realpath,
if (body && body->has_source_hash) {
ISEQ_BODY(iseq)->source_hash = body->source_hash;
ISEQ_BODY(iseq)->has_source_hash = true;
RUBY_ASSERT(ISEQ_BODY(iseq)->source_hash != 0);
}
rb_iseq_compile_node(iseq, node);
@@ -1164,7 +1164,7 @@ pm_iseq_build(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath,
ISEQ_BODY(iseq)->prism = true;
ISEQ_BODY(iseq)->source_hash = node->source_hash;
ISEQ_BODY(iseq)->has_source_hash = true;
RUBY_ASSERT(ISEQ_BODY(iseq)->source_hash != 0);
rb_compile_option_t next_option;
if (!option) option = &COMPILE_OPTION_DEFAULT;
@@ -3764,7 +3764,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq_body->local_table_size));
rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq_body->stack_max));
rb_hash_aset(misc, ID2SYM(rb_intern("node_id")), INT2FIX(iseq_body->location.node_id));
rb_hash_aset(misc, ID2SYM(rb_intern("source_hash")), iseq_body->has_source_hash ? ULL2NUM(iseq_body->source_hash) : Qnil);
rb_hash_aset(misc, ID2SYM(rb_intern("source_hash")), iseq_body->source_hash ? ULL2NUM(iseq_body->source_hash) : Qnil);
rb_hash_aset(misc, ID2SYM(rb_intern("code_location")),
rb_ary_new_from_args(4,
INT2FIX(iseq_body->location.code_location.beg_pos.lineno),
@@ -4607,7 +4607,7 @@ static VALUE
iseqw_source_hash(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
if (!ISEQ_BODY(iseq)->has_source_hash) return Qnil;
if (!ISEQ_BODY(iseq)->source_hash) return Qnil;
return ULL2NUM(ISEQ_BODY(iseq)->source_hash);
}
+2 -1
View File
@@ -1119,7 +1119,8 @@ rb_source_hash_update(rb_source_hash_state_t *state, const uint8_t *ptr, size_t
uint64_t
rb_source_hash_finalize(const rb_source_hash_state_t *state)
{
return state->hash;
/* A hash of 0 means no source hash, so remap it to another value. */
return state->hash == 0 ? 1 : state->hash;
}
VALUE
+1 -1
View File
@@ -601,7 +601,7 @@ location_source_range_m(VALUE self)
if (node_id == -1) {
rb_raise(rb_eRuntimeError, "cannot get source range for location without a node ID");
}
if (!ISEQ_BODY(iseq)->has_source_hash) {
if (!ISEQ_BODY(iseq)->source_hash) {
rb_raise(rb_eRuntimeError, "cannot get source range because the source hash is unavailable");
}
uint64_t source_hash = ISEQ_BODY(iseq)->source_hash;
+3 -3
View File
@@ -580,10 +580,10 @@ struct rb_iseq_constant_body {
void *zjit_payload;
#endif
// Hash of the source this iseq was compiled from. Meaningful only when
// has_source_hash is set.
// Hash of the source this iseq was compiled from, or 0 if it is
// unavailable. A computed hash of 0 is remapped to another value, so
// 0 never denotes a real hash.
uint64_t source_hash;
bool has_source_hash;
};
/* T_IMEMO/iseq */