Stop allocating unused backref strings at `defined?`

This commit is contained in:
Nobuyoshi Nakada 2023-06-27 23:14:10 +09:00
Родитель df5ae0a550
Коммит 913e01e80e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 3582D74E1FEE4465
3 изменённых файлов: 49 добавлений и 10 удалений

Просмотреть файл

@ -23,5 +23,6 @@ void rb_backref_set_string(VALUE string, long pos, long len);
void rb_match_unbusy(VALUE);
int rb_match_count(VALUE match);
VALUE rb_reg_new_ary(VALUE ary, int options);
VALUE rb_reg_last_defined(VALUE match);
#endif /* INTERNAL_RE_H */

28
re.c
Просмотреть файл

@ -1935,21 +1935,37 @@ rb_reg_match_post(VALUE match)
return str;
}
VALUE
rb_reg_match_last(VALUE match)
static int
match_last_index(VALUE match)
{
int i;
struct re_registers *regs;
if (NIL_P(match)) return Qnil;
if (NIL_P(match)) return -1;
match_check(match);
regs = RMATCH_REGS(match);
if (BEG(0) == -1) return Qnil;
if (BEG(0) == -1) return -1;
for (i=regs->num_regs-1; BEG(i) == -1 && i > 0; i--)
;
if (i == 0) return Qnil;
return rb_reg_nth_match(i, match);
return i;
}
VALUE
rb_reg_match_last(VALUE match)
{
int i = match_last_index(match);
if (i <= 0) return Qnil;
struct re_registers *regs = RMATCH_REGS(match);
return rb_str_subseq(RMATCH(match)->str, BEG(i), END(i) - BEG(i));
}
VALUE
rb_reg_last_defined(VALUE match)
{
int i = match_last_index(match);
if (i < 0) return Qnil;
return RBOOL(i);
}
static VALUE

Просмотреть файл

@ -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;