Skip to content

Commit 01c821a

Browse files
committed
Implement compaction and embedded structs
Currently dates are allocated in a 40B slot plus a 32B (simple) or 48B (complex) external struct. Once embedded they entirely fit into a 80B slot.
1 parent 2140246 commit 01c821a

2 files changed

Lines changed: 54 additions & 18 deletions

File tree

ext/date/date_core.c

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3195,34 +3195,66 @@ date_s_gregorian_leap_p(VALUE klass, VALUE y)
31953195
return f_boolcast(c_gregorian_leap_p(ry));
31963196
}
31973197

3198+
#ifndef HAVE_RB_GC_MARK_MOVABLE
3199+
#define rb_gc_mark_movable rb_gc_mark
3200+
#else
31983201
static void
3199-
d_lite_gc_mark(void *ptr)
3202+
d_lite_gc_compact(void *ptr)
32003203
{
32013204
union DateData *dat = ptr;
32023205
if (simple_dat_p(dat))
3203-
rb_gc_mark(dat->s.nth);
3206+
dat->s.nth = rb_gc_location(dat->s.nth);
32043207
else {
3205-
rb_gc_mark(dat->c.nth);
3206-
rb_gc_mark(dat->c.sf);
3208+
dat->c.nth = rb_gc_location(dat->c.nth);
3209+
dat->c.sf = rb_gc_location(dat->c.sf);
32073210
}
32083211
}
3212+
#endif
32093213

3210-
static size_t
3211-
d_lite_memsize(const void *ptr)
3214+
static void
3215+
d_lite_gc_mark(void *ptr)
32123216
{
3213-
const union DateData *dat = ptr;
3214-
return complex_dat_p(dat) ? sizeof(struct ComplexDateData) : sizeof(struct SimpleDateData);
3217+
union DateData *dat = ptr;
3218+
if (simple_dat_p(dat))
3219+
rb_gc_mark_movable(dat->s.nth);
3220+
else {
3221+
rb_gc_mark_movable(dat->c.nth);
3222+
rb_gc_mark_movable(dat->c.sf);
3223+
}
32153224
}
32163225

32173226
#ifndef HAVE_RB_EXT_RACTOR_SAFE
32183227
# define RUBY_TYPED_FROZEN_SHAREABLE 0
32193228
#endif
32203229

3230+
#if defined(RUBY_TYPED_EMBEDDABLE) || defined(HAVE_CONST_RUBY_TYPED_EMBEDDABLE)
3231+
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
3232+
#else
3233+
# define RUBY_TYPED_EMBEDDABLE 0
3234+
#endif
3235+
3236+
static size_t
3237+
d_lite_memsize(const void *ptr)
3238+
{
3239+
#ifdef HAVE_RUBY_TYPED_EMBEDDABLE
3240+
return 0;
3241+
#else
3242+
return sizeof(union DateData);
3243+
#endif
3244+
}
3245+
32213246
static const rb_data_type_t d_lite_type = {
32223247
"Date",
3223-
{d_lite_gc_mark, RUBY_TYPED_DEFAULT_FREE, d_lite_memsize,},
3248+
{
3249+
d_lite_gc_mark,
3250+
RUBY_TYPED_DEFAULT_FREE,
3251+
d_lite_memsize,
3252+
#ifdef HAVE_RB_GC_MARK_MOVABLE
3253+
d_lite_gc_compact,
3254+
#endif
3255+
},
32243256
0, 0,
3225-
RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_FROZEN_SHAREABLE,
3257+
RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_EMBEDDABLE|RUBY_TYPED_FROZEN_SHAREABLE,
32263258
};
32273259

32283260
inline static VALUE
@@ -3232,11 +3264,12 @@ d_simple_new_internal(VALUE klass,
32323264
int y, int m, int d,
32333265
unsigned flags)
32343266
{
3235-
struct SimpleDateData *dat;
3267+
union DateData *u_dat;
32363268
VALUE obj;
3269+
struct SimpleDateData *dat;
32373270

3238-
obj = TypedData_Make_Struct(klass, struct SimpleDateData,
3239-
&d_lite_type, dat);
3271+
obj = TypedData_Make_Struct(klass, union DateData, &d_lite_type, u_dat);
3272+
dat = &u_dat->s;
32403273
set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags);
32413274

32423275
assert(have_jd_p(dat) || have_civil_p(dat));
@@ -3253,11 +3286,13 @@ d_complex_new_internal(VALUE klass,
32533286
int h, int min, int s,
32543287
unsigned flags)
32553288
{
3256-
struct ComplexDateData *dat;
3289+
3290+
union DateData *u_dat;
32573291
VALUE obj;
3292+
struct ComplexDateData *
32583293

3259-
obj = TypedData_Make_Struct(klass, struct ComplexDateData,
3260-
&d_lite_type, dat);
3294+
obj = TypedData_Make_Struct(klass, union DateData, &d_lite_type, u_dat);
3295+
dat = &u_dat->c;
32613296
set_to_complex(obj, dat, nth, jd, df, sf, of, sg,
32623297
y, m, d, h, min, s, flags);
32633298

@@ -7804,8 +7839,6 @@ d_lite_marshal_load(VALUE self, VALUE a)
78047839
if (simple_dat_p(dat)) {
78057840
if (df || !f_zero_p(sf) || of) {
78067841
/* loading a fractional date; promote to complex */
7807-
dat = ruby_xrealloc(dat, sizeof(struct ComplexDateData));
7808-
RTYPEDDATA(self)->data = dat;
78097842
goto complex_data;
78107843
}
78117844
set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);

ext/date/extconf.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@
1313
have_var("altzone", "time.h", opt)
1414
end
1515

16+
have_func("rb_gc_mark_movable", "ruby.h") # RUBY_VERSION >= 2.7
17+
have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
18+
1619
create_makefile('date_core')

0 commit comments

Comments
 (0)