Extract KW_SPECIFIED_BITS_MAX for JITs (GH-15039)

Rename to `VM_KW_SPECIFIED_BITS_MAX` now that it's in `vm_core.h`.
This commit is contained in:
Jacob 2025-11-18 17:32:11 -05:00 committed by GitHub
parent cbe65ebbc3
commit f3f3e76882
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2025-11-18 22:32:41 +00:00
Merged: https://github.com/ruby/ruby/pull/15039

Merged-By: XrXr
9 changed files with 13 additions and 10 deletions

View File

@ -318,8 +318,6 @@ args_setup_kw_parameters_lookup(const ID key, VALUE *ptr, const VALUE *const pas
return FALSE;
}
#define KW_SPECIFIED_BITS_MAX (32-1) /* TODO: 32 -> Fixnum's max bits */
static void
args_setup_kw_parameters(rb_execution_context_t *const ec, const rb_iseq_t *const iseq, const rb_callable_method_entry_t *cme,
VALUE *const passed_values, const int passed_keyword_len, const VALUE *const passed_keywords,
@ -355,7 +353,7 @@ args_setup_kw_parameters(rb_execution_context_t *const ec, const rb_iseq_t *cons
if (UNDEF_P(default_values[di])) {
locals[i] = Qnil;
if (LIKELY(i < KW_SPECIFIED_BITS_MAX)) {
if (LIKELY(i < VM_KW_SPECIFIED_BITS_MAX)) {
unspecified_bits |= 0x01 << di;
}
else {
@ -364,7 +362,7 @@ args_setup_kw_parameters(rb_execution_context_t *const ec, const rb_iseq_t *cons
int j;
unspecified_bits_value = rb_hash_new();
for (j=0; j<KW_SPECIFIED_BITS_MAX; j++) {
for (j=0; j<VM_KW_SPECIFIED_BITS_MAX; j++) {
if (unspecified_bits & (0x01 << j)) {
rb_hash_aset(unspecified_bits_value, INT2FIX(j), Qtrue);
}
@ -450,7 +448,7 @@ args_setup_kw_parameters_from_kwsplat(rb_execution_context_t *const ec, const rb
if (UNDEF_P(default_values[di])) {
locals[i] = Qnil;
if (LIKELY(i < KW_SPECIFIED_BITS_MAX)) {
if (LIKELY(i < VM_KW_SPECIFIED_BITS_MAX)) {
unspecified_bits |= 0x01 << di;
}
else {
@ -459,7 +457,7 @@ args_setup_kw_parameters_from_kwsplat(rb_execution_context_t *const ec, const rb
int j;
unspecified_bits_value = rb_hash_new();
for (j=0; j<KW_SPECIFIED_BITS_MAX; j++) {
for (j=0; j<VM_KW_SPECIFIED_BITS_MAX; j++) {
if (unspecified_bits & (0x01 << j)) {
rb_hash_aset(unspecified_bits_value, INT2FIX(j), Qtrue);
}

View File

@ -317,6 +317,8 @@ struct rb_calling_info {
#define VM_ARGC_STACK_MAX 128
#endif
#define VM_KW_SPECIFIED_BITS_MAX (32-1) /* TODO: 32 -> Fixnum's max bits */
# define CALLING_ARGC(calling) ((calling)->heap_argv ? RARRAY_LENINT((calling)->heap_argv) : (calling)->argc)
struct rb_execution_context_struct;

View File

@ -5808,7 +5808,7 @@ vm_check_keyword(lindex_t bits, lindex_t idx, const VALUE *ep)
if (FIXNUM_P(kw_bits)) {
unsigned int b = (unsigned int)FIX2ULONG(kw_bits);
if ((idx < KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
if ((idx < VM_KW_SPECIFIED_BITS_MAX) && (b & (0x01 << idx)))
return Qfalse;
}
else {

View File

@ -155,6 +155,7 @@ fn main() {
.opaque_type("rb_callcache.*")
.allowlist_type("rb_callinfo")
.allowlist_var("VM_ENV_DATA_INDEX_ME_CREF")
.allowlist_var("VM_KW_SPECIFIED_BITS_MAX")
.allowlist_var("rb_block_param_proxy")
.allowlist_function("rb_range_new")
.allowlist_function("rb_intern")

View File

@ -2747,7 +2747,7 @@ fn gen_checkkeyword(
) -> Option<CodegenStatus> {
// When a keyword is unspecified past index 32, a hash will be used
// instead. This can only happen in iseqs taking more than 32 keywords.
if unsafe { (*get_iseq_body_param_keyword(jit.iseq)).num >= 32 } {
if unsafe { (*get_iseq_body_param_keyword(jit.iseq)).num >= VM_KW_SPECIFIED_BITS_MAX.try_into().unwrap() } {
return None;
}

View File

@ -165,6 +165,7 @@ pub const NIL_REDEFINED_OP_FLAG: u32 = 512;
pub const TRUE_REDEFINED_OP_FLAG: u32 = 1024;
pub const FALSE_REDEFINED_OP_FLAG: u32 = 2048;
pub const PROC_REDEFINED_OP_FLAG: u32 = 4096;
pub const VM_KW_SPECIFIED_BITS_MAX: u32 = 31;
pub const VM_ENV_DATA_SIZE: u32 = 3;
pub const VM_ENV_DATA_INDEX_ME_CREF: i32 = -2;
pub const VM_ENV_DATA_INDEX_SPECVAL: i32 = -1;

View File

@ -101,6 +101,7 @@ fn main() {
.allowlist_function("rb_shape_get_iv_index")
.allowlist_function("rb_shape_transition_add_ivar_no_warnings")
.allowlist_var("rb_invalid_shape_id")
.allowlist_var("VM_KW_SPECIFIED_BITS_MAX")
.allowlist_var("SHAPE_ID_NUM_BITS")
.allowlist_function("rb_obj_is_kind_of")
.allowlist_function("rb_obj_frozen_p")

View File

@ -227,6 +227,7 @@ pub const NIL_REDEFINED_OP_FLAG: u32 = 512;
pub const TRUE_REDEFINED_OP_FLAG: u32 = 1024;
pub const FALSE_REDEFINED_OP_FLAG: u32 = 2048;
pub const PROC_REDEFINED_OP_FLAG: u32 = 4096;
pub const VM_KW_SPECIFIED_BITS_MAX: u32 = 31;
pub const VM_ENV_DATA_SIZE: u32 = 3;
pub const VM_ENV_DATA_INDEX_ME_CREF: i32 = -2;
pub const VM_ENV_DATA_INDEX_SPECVAL: i32 = -1;

View File

@ -4848,8 +4848,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
// When a keyword is unspecified past index 32, a hash will be used instead.
// This can only happen in iseqs taking more than 32 keywords.
// In this case, we side exit to the interpreter.
// TODO(Jacob): Replace the magic number 32 with a named constant. (Can be completed after PR 15039)
if unsafe {(*rb_get_iseq_body_param_keyword(iseq)).num >= 32} {
if unsafe {(*rb_get_iseq_body_param_keyword(iseq)).num >= VM_KW_SPECIFIED_BITS_MAX.try_into().unwrap()} {
fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::TooManyKeywordParameters });
break;
}