Skip to content

Commit deb3663

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 6d978f5 commit deb3663

File tree

2 files changed

+58
-20
lines changed

2 files changed

+58
-20
lines changed

ext/date/date_core.c

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3195,34 +3195,70 @@ 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+
#ifdef RUBY_TYPED_EMBEDDABLE
3231+
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
3232+
#else
3233+
# ifdef HAVE_CONST_RUBY_TYPED_EMBEDDABLE
3234+
# define RUBY_TYPED_EMBEDDABLE RUBY_TYPED_EMBEDDABLE
3235+
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
3236+
# else
3237+
# define RUBY_TYPED_EMBEDDABLE 0
3238+
# endif
3239+
#endif
3240+
3241+
static size_t
3242+
d_lite_memsize(const void *ptr)
3243+
{
3244+
#ifdef HAVE_RUBY_TYPED_EMBEDDABLE
3245+
return 0;
3246+
#else
3247+
return sizeof(union DateData);
3248+
#endif
3249+
}
3250+
32213251
static const rb_data_type_t d_lite_type = {
3222-
"Date",
3223-
{d_lite_gc_mark, RUBY_TYPED_DEFAULT_FREE, d_lite_memsize,},
3224-
0, 0,
3225-
RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_FROZEN_SHAREABLE,
3252+
.wrap_struct_name = "Date",
3253+
.function = {
3254+
.dmark = d_lite_gc_mark,
3255+
.dfree = RUBY_TYPED_DEFAULT_FREE,
3256+
.dsize = d_lite_memsize,
3257+
#ifdef HAVE_RB_GC_MARK_MOVABLE
3258+
.dcompact = d_lite_gc_compact,
3259+
#endif
3260+
},
3261+
.flags = RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_EMBEDDABLE|RUBY_TYPED_FROZEN_SHAREABLE,
32263262
};
32273263

32283264
inline static VALUE
@@ -3232,11 +3268,11 @@ d_simple_new_internal(VALUE klass,
32323268
int y, int m, int d,
32333269
unsigned flags)
32343270
{
3235-
struct SimpleDateData *dat;
3271+
union DateData *u_dat;
32363272
VALUE obj;
32373273

3238-
obj = TypedData_Make_Struct(klass, struct SimpleDateData,
3239-
&d_lite_type, dat);
3274+
obj = TypedData_Make_Struct(klass, union DateData, &d_lite_type, u_dat);
3275+
struct SimpleDateData *dat = &u_dat->s;
32403276
set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags);
32413277

32423278
assert(have_jd_p(dat) || have_civil_p(dat));
@@ -3253,11 +3289,12 @@ d_complex_new_internal(VALUE klass,
32533289
int h, int min, int s,
32543290
unsigned flags)
32553291
{
3256-
struct ComplexDateData *dat;
3292+
3293+
union DateData *u_dat;
32573294
VALUE obj;
32583295

3259-
obj = TypedData_Make_Struct(klass, struct ComplexDateData,
3260-
&d_lite_type, dat);
3296+
obj = TypedData_Make_Struct(klass, union DateData, &d_lite_type, u_dat);
3297+
struct ComplexDateData *dat = &u_dat->c;
32613298
set_to_complex(obj, dat, nth, jd, df, sf, of, sg,
32623299
y, m, d, h, min, s, flags);
32633300

@@ -7804,8 +7841,6 @@ d_lite_marshal_load(VALUE self, VALUE a)
78047841
if (simple_dat_p(dat)) {
78057842
if (df || !f_zero_p(sf) || of) {
78067843
/* loading a fractional date; promote to complex */
7807-
dat = ruby_xrealloc(dat, sizeof(struct ComplexDateData));
7808-
RTYPEDDATA(self)->data = dat;
78097844
goto complex_data;
78107845
}
78117846
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
@@ -10,4 +10,7 @@
1010
have_var("altzone", "time.h", opt)
1111
end
1212

13+
have_func("rb_gc_mark_movable", "ruby.h") # RUBY_VERSION >= 2.7
14+
have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
15+
1316
create_makefile('date_core')

0 commit comments

Comments
 (0)