# UNDF: UNDF-2026-000000265 diff --git a/vm_args.c b/vm_args.c --- a/vm_args.c +++ b/vm_args.c @@ -299,30 +299,50 @@ static inline int -args_setup_kw_parameters_lookup(const ID key, VALUE *ptr, - const VALUE *const passed_keywords, VALUE *passed_values, - const int passed_keyword_len) -{ - int i; - const VALUE keyname = ID2SYM(key); - - for (i=0; i value-slot index. + * Replaces O(K * P) double-loop with O(K + P): one pass to build the map, + * one O(1) lookup per accepted keyword. + */ +static st_table * +build_passed_kw_table(const VALUE *const passed_keywords, + const int passed_keyword_len) +{ + st_table *tbl = st_init_numtable_with_size(passed_keyword_len); + for (int i = 0; i < passed_keyword_len; i++) { + st_insert(tbl, (st_data_t)passed_keywords[i], (st_data_t)i); + } + return tbl; +} 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, VALUE *const locals) { const ID *acceptable_keywords = ISEQ_BODY(iseq)->param.keyword->table; const int req_key_num = ISEQ_BODY(iseq)->param.keyword->required_num; const int key_num = ISEQ_BODY(iseq)->param.keyword->num; const VALUE * const default_values = ISEQ_BODY(iseq)->param.keyword->default_values; VALUE missing = 0; int i, di, found = 0; int unspecified_bits = 0; VALUE unspecified_bits_value = Qnil; + /* Build O(1) lookup map once — replaces O(K*P) nested loop */ + st_table *kw_map = (passed_keyword_len > 0) + ? build_passed_kw_table(passed_keywords, passed_keyword_len) + : NULL; + for (i=0; i