diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-06-27 23:14:10 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-06-27 23:14:10 +0900 |
commit | 913e01e80ec5fd771ae096c992893d5e736e7fae (patch) | |
tree | d32c73f3a8cd5aa31b0bfbb0c8ce302f537c03dd /vm_insnhelper.c | |
parent | df5ae0a55005f7f02adbf21790300f28dc2e12fc (diff) | |
download | ruby-913e01e80ec5fd771ae096c992893d5e736e7fae.tar.gz |
Stop allocating unused backref strings at `defined?`
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c index cbcd51cce9..f60a7c4ee2 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -672,6 +672,30 @@ vm_getspecial(const rb_execution_context_t *ec, const VALUE *lep, rb_num_t key, return val; } +static inline VALUE +vm_backref_defined(const rb_execution_context_t *ec, const VALUE *lep, rb_num_t type) +{ + VALUE backref = lep_svar_get(ec, lep, VM_SVAR_BACKREF); + int nth = 0; + + if (type & 0x01) { + switch (type >> 1) { + case '&': + case '`': + case '\'': + break; + case '+': + return rb_reg_last_defined(backref); + default: + rb_bug("unexpected back-ref"); + } + } + else { + nth = (int)(type >> 1); + } + return rb_reg_nth_defined(nth, backref); +} + PUREFUNC(static rb_callable_method_entry_t *check_method_entry(VALUE obj, int can_be_svar)); static rb_callable_method_entry_t * check_method_entry(VALUE obj, int can_be_svar) @@ -5064,10 +5088,8 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_ } } break; - case DEFINED_REF:{ - return vm_getspecial(ec, GET_LEP(), Qfalse, FIX2INT(obj)) != Qnil; - break; - } + case DEFINED_REF: + return RTEST(vm_backref_defined(ec, GET_LEP(), FIX2INT(obj))); default: rb_bug("unimplemented defined? type (VM)"); break; |