java-topology/defects/ruby/patch/0001-kwarg-setup-hash-lookup.patch
russell@unturf.com 9934133dcf whitepaper: 312 sites / 151 ecosystems — wave2+3 defect tables and PDF rebuild
Add 88 new defect entries to HIGH and MEDIUM tables:
  HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
        vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
        tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
        allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
        mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
        linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
        perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002

  MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
          cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
          pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
          ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
          r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
          ovs-0001, onos-0003, odl-0002, jetty-0001

PDF: 976K
2026-03-27 15:23:43 -04:00

85 lines
3.2 KiB
Diff

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<passed_keyword_len; i++) { /* O(passed_keyword_len) */
- if (keyname == passed_keywords[i]) {
- *ptr = passed_values[i];
- passed_values[i] = Qundef;
- return TRUE;
- }
- }
-
- return FALSE;
-}
+/* Build a temporary st_table from passed keyword symbol -> 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<req_key_num; i++) {
ID key = acceptable_keywords[i];
- if (args_setup_kw_parameters_lookup(key, &locals[i], passed_keywords, passed_values, passed_keyword_len)) {
+ VALUE keyname = ID2SYM(key);
+ st_data_t idx;
+ if (kw_map && st_lookup(kw_map, (st_data_t)keyname, &idx)) {
+ locals[i] = passed_values[idx];
+ passed_values[idx] = Qundef;
found++;
- }
- else {
+ } else {
if (!missing) missing = rb_ary_hidden_new(1);
rb_ary_push(missing, ID2SYM(key));
}
}
if (missing) argument_kw_error(ec, iseq, cme, "missing", missing);
for (di=0; i<key_num; i++, di++) {
- if (args_setup_kw_parameters_lookup(acceptable_keywords[i], &locals[i], passed_keywords, passed_values, passed_keyword_len)) {
+ VALUE keyname = ID2SYM(acceptable_keywords[i]);
+ st_data_t idx;
+ if (kw_map && st_lookup(kw_map, (st_data_t)keyname, &idx)) {
+ locals[i] = passed_values[idx];
+ passed_values[idx] = Qundef;
found++;
- }
- else {
+ } else {