Refactor Enumerator::ArithmeticSequence to not use ivars

It's an embedded TypedData, it can much more efficiently store
the references it need without using ivars.
This commit is contained in:
Jean Boussier 2025-06-10 17:12:10 +02:00
parent 585dcffff1
commit bcb4fbe2eb
Notes: git 2025-06-10 17:26:51 +00:00

View File

@ -3748,6 +3748,55 @@ enumerator_s_product(int argc, VALUE *argv, VALUE klass)
return obj;
}
struct arith_seq {
struct enumerator enumerator;
VALUE begin;
VALUE end;
VALUE step;
bool exclude_end;
};
RUBY_REFERENCES(arith_seq_refs) = {
RUBY_REF_EDGE(struct enumerator, obj),
RUBY_REF_EDGE(struct enumerator, args),
RUBY_REF_EDGE(struct enumerator, fib),
RUBY_REF_EDGE(struct enumerator, dst),
RUBY_REF_EDGE(struct enumerator, lookahead),
RUBY_REF_EDGE(struct enumerator, feedvalue),
RUBY_REF_EDGE(struct enumerator, stop_exc),
RUBY_REF_EDGE(struct enumerator, size),
RUBY_REF_EDGE(struct enumerator, procs),
RUBY_REF_EDGE(struct arith_seq, begin),
RUBY_REF_EDGE(struct arith_seq, end),
RUBY_REF_EDGE(struct arith_seq, step),
RUBY_REF_END
};
static const rb_data_type_t arith_seq_data_type = {
"arithmetic_sequence",
{
RUBY_REFS_LIST_PTR(arith_seq_refs),
RUBY_TYPED_DEFAULT_FREE,
NULL, // Nothing allocated externally, so don't need a memsize function
NULL,
},
.parent = &enumerator_data_type,
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
};
static VALUE
arith_seq_allocate(VALUE klass)
{
struct arith_seq *ptr;
VALUE enum_obj;
enum_obj = TypedData_Make_Struct(klass, struct arith_seq, &arith_seq_data_type, ptr);
ptr->enumerator.obj = Qundef;
return enum_obj;
}
/*
* Document-class: Enumerator::ArithmeticSequence
*
@ -3765,12 +3814,16 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
rb_enumerator_size_func *size_fn,
VALUE beg, VALUE end, VALUE step, int excl)
{
VALUE aseq = enumerator_init(enumerator_allocate(rb_cArithSeq),
VALUE aseq = enumerator_init(arith_seq_allocate(rb_cArithSeq),
obj, meth, argc, argv, size_fn, Qnil, rb_keyword_given_p());
rb_ivar_set(aseq, id_begin, beg);
rb_ivar_set(aseq, id_end, end);
rb_ivar_set(aseq, id_step, step);
rb_ivar_set(aseq, id_exclude_end, RBOOL(excl));
struct arith_seq *ptr;
TypedData_Get_Struct(aseq, struct arith_seq, &enumerator_data_type, ptr);
RB_OBJ_WRITE(aseq, &ptr->begin, beg);
RB_OBJ_WRITE(aseq, &ptr->end, end);
RB_OBJ_WRITE(aseq, &ptr->step, step);
ptr->exclude_end = excl;
return aseq;
}
@ -3783,7 +3836,9 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
static inline VALUE
arith_seq_begin(VALUE self)
{
return rb_ivar_get(self, id_begin);
struct arith_seq *ptr;
TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
return ptr->begin;
}
/*
@ -3794,7 +3849,9 @@ arith_seq_begin(VALUE self)
static inline VALUE
arith_seq_end(VALUE self)
{
return rb_ivar_get(self, id_end);
struct arith_seq *ptr;
TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
return ptr->end;
}
/*
@ -3806,7 +3863,9 @@ arith_seq_end(VALUE self)
static inline VALUE
arith_seq_step(VALUE self)
{
return rb_ivar_get(self, id_step);
struct arith_seq *ptr;
TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
return ptr->step;
}
/*
@ -3817,13 +3876,17 @@ arith_seq_step(VALUE self)
static inline VALUE
arith_seq_exclude_end(VALUE self)
{
return rb_ivar_get(self, id_exclude_end);
struct arith_seq *ptr;
TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
return RBOOL(ptr->exclude_end);
}
static inline int
arith_seq_exclude_end_p(VALUE self)
{
return RTEST(arith_seq_exclude_end(self));
struct arith_seq *ptr;
TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
return ptr->exclude_end;
}
int