aboutsummaryrefslogtreecommitdiffstats
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2023-06-27 23:14:10 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-06-27 23:14:10 +0900
commit913e01e80ec5fd771ae096c992893d5e736e7fae (patch)
treed32c73f3a8cd5aa31b0bfbb0c8ce302f537c03dd /vm_insnhelper.c
parentdf5ae0a55005f7f02adbf21790300f28dc2e12fc (diff)
downloadruby-913e01e80ec5fd771ae096c992893d5e736e7fae.tar.gz
Stop allocating unused backref strings at `defined?`
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c30
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;