From ed712e0e9d591bdaa84e9eaac832a9632aee5139 Mon Sep 17 00:00:00 2001 From: Matthew Draper Date: Thu, 24 Aug 2023 16:27:17 +0930 Subject: [PATCH] Skip allocation if handle_interrupt arg is already usable If the supplied hash is already frozen and compare-by-identity, we can use it directly (still checking its contents are valid symbols), without making a new copy. --- thread.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/thread.c b/thread.c index 4073325b9d..80a097f6f4 100644 --- a/thread.c +++ b/thread.c @@ -2018,10 +2018,12 @@ handle_interrupt_arg_check_i(VALUE key, VALUE val, VALUE args) rb_raise(rb_eArgError, "unknown mask signature"); } - if (!*maskp) { - *maskp = rb_ident_hash_new(); + if (maskp) { + if (!*maskp) { + *maskp = rb_ident_hash_new(); + } + rb_hash_aset(*maskp, key, val); } - rb_hash_aset(*maskp, key, val); return ST_CONTINUE; } @@ -2147,13 +2149,20 @@ rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg) rb_raise(rb_eArgError, "block is needed."); } - mask = 0; mask_arg = rb_to_hash_type(mask_arg); - rb_hash_foreach(mask_arg, handle_interrupt_arg_check_i, (VALUE)&mask); - if (!mask) { - return rb_yield(Qnil); + + if (OBJ_FROZEN(mask_arg) && rb_hash_compare_by_id_p(mask_arg)) { + rb_hash_foreach(mask_arg, handle_interrupt_arg_check_i, 0); + mask = mask_arg; + } else { + mask = 0; + rb_hash_foreach(mask_arg, handle_interrupt_arg_check_i, (VALUE)&mask); + if (!mask) { + return rb_yield(Qnil); + } + OBJ_FREEZE_RAW(mask); } - OBJ_FREEZE_RAW(mask); + rb_ary_push(th->pending_interrupt_mask_stack, mask); if (!rb_threadptr_pending_interrupt_empty_p(th)) { th->pending_interrupt_queue_checked = 0;