Skip to content

Commit

Permalink
Don't guess size class.
Browse files Browse the repository at this point in the history
Since str_substr and ary_make_partial no longer estimate the embed_capa
of objects allocated by {str,ary}_alloc_heap, we don't estimate the
object size when using MMTk, either.
  • Loading branch information
wks committed Aug 4, 2023
1 parent 52a4faf commit 0c2db55
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 67 deletions.
56 changes: 23 additions & 33 deletions array.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,16 +779,30 @@ rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
return Qfalse;
}

#if USE_MMTK
// How large is the array allocated with ary_alloc_heap
static inline size_t
rb_mmtk_ary_heap_size(void)
{
// The main RArray plus the arrayext.
return sizeof(struct RArray) + sizeof(rb_mmtk_arrayext_t);
}
#endif

static VALUE
ary_alloc_embed(VALUE klass, long capa)
{
size_t size = ary_embed_size(capa);

#if USE_MMTK
if (rb_mmtk_enabled_p()) {
if (size < sizeof(struct RArray) + sizeof(rb_mmtk_arrayext_t)) {
// When using MMTk, we allocate at least 48 bytes, including a trailing rb_mmtk_arrayext_t.
size = sizeof(struct RArray) + sizeof(rb_mmtk_arrayext_t);
if (size < rb_mmtk_ary_heap_size()) {
// When using MMTk, we always allocate enough space to hold a heap array.
// The lowest size class for vanilla Ruby gc is 40 bytes,
// which is enough to hold a whole `struct RArray` for heap arrays.
// But we have one extra field in the trailing rb_mmtk_arrayext_t.
// So we manually ensure the allocated memory region is large enough.
size = rb_mmtk_ary_heap_size();
}
}
#endif
Expand All @@ -804,23 +818,6 @@ ary_alloc_embed(VALUE klass, long capa)
return (VALUE)ary;
}

#if USE_MMTK
// How large is the array allocated with ary_alloc_heap
static inline size_t
rb_mmtk_ary_heap_size(void)
{
// The main RArray plus the arrayext.
size_t size = sizeof(struct RArray) + sizeof(rb_mmtk_arrayext_t);

// Align up to the next size class.
if (size < 80) {
size = 80;
}

return size;
}
#endif

static VALUE
ary_alloc_heap(VALUE klass)
{
Expand Down Expand Up @@ -937,17 +934,13 @@ rb_ary_new_from_values(long n, const VALUE *elts)
static VALUE
ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
{
size_t size = ary_embed_size(capa);

#if USE_MMTK
if (rb_mmtk_enabled_p()) {
if (size < sizeof(struct RArray) + sizeof(rb_mmtk_arrayext_t)) {
// When using MMTk, we allocate at least 48 bytes, including a trailing rb_mmtk_arrayext_t.
size = sizeof(struct RArray) + sizeof(rb_mmtk_arrayext_t);
}
// The optimization about ec is unnecessary for MMTk. We avoid code duplication.
return ary_alloc_embed(klass, capa);
}
#endif

size_t size = ary_embed_size(capa);
assert(rb_gc_size_allocatable_p(size));
NEWOBJ_OF(ary, struct RArray, klass,
T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
Expand All @@ -962,18 +955,15 @@ ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
static VALUE
ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
{
size_t size = sizeof(struct RString);

#if USE_MMTK
if (rb_mmtk_enabled_p()) {
// When using MMTk, we include a trailing rb_mmtk_arrayext_t.
size = rb_mmtk_ary_heap_size();
// The optimization about ec is unnecessary for MMTk. We avoid code duplication.
return ary_alloc_heap(klass);
}
#endif

NEWOBJ_OF(ary, struct RArray, klass,
T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
size, ec);
sizeof(struct RArray), ec);
return (VALUE)ary;
}

Expand Down
58 changes: 24 additions & 34 deletions string.c
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,16 @@ must_not_null(const char *ptr)
}
}

#if USE_MMTK
// How large is the string allocated with str_alloc_heap
static inline size_t
rb_mmtk_str_heap_size(void)
{
// The main RString plus the stringext.
return sizeof(struct RString) + sizeof(rb_mmtk_stringext_t);
}
#endif

static inline VALUE
str_alloc_embed(VALUE klass, size_t capa)
{
Expand All @@ -980,9 +990,13 @@ str_alloc_embed(VALUE klass, size_t capa)

#if USE_MMTK
if (rb_mmtk_enabled_p()) {
if (size < sizeof(struct RString) + sizeof(rb_mmtk_stringext_t)) {
// When using MMTk, we allocate at least 48 bytes, including a trailing rb_mmtk_stringext_t.
size = sizeof(struct RString) + sizeof(rb_mmtk_stringext_t);
if (size < rb_mmtk_str_heap_size()) {
// When using MMTk, we always allocate enough space to hold a heap string.
// The lowest size class for vanilla Ruby gc is 40 bytes,
// which is enough to hold a whole `struct RString` for heap strings.
// But we have one extra field in the trailing rb_mmtk_stringext_t.
// So we manually ensure the allocated memory region is large enough.
size = rb_mmtk_str_heap_size();
}
}
#endif
Expand All @@ -995,23 +1009,6 @@ str_alloc_embed(VALUE klass, size_t capa)

}

#if USE_MMTK
// How large is the string allocated with str_alloc_heap
static inline size_t
rb_mmtk_str_heap_size(void)
{
// The main RString plus the stringext.
size_t size = sizeof(struct RString) + sizeof(rb_mmtk_stringext_t);

// Align up to the next size class.
if (size < 80) {
size = 80;
}

return size;
}
#endif

static inline VALUE
str_alloc_heap(VALUE klass)
{
Expand Down Expand Up @@ -1946,18 +1943,14 @@ str_replace(VALUE str, VALUE str2)
static inline VALUE
ec_str_alloc_embed(struct rb_execution_context_struct *ec, VALUE klass, size_t capa)
{
size_t size = rb_str_embed_size(capa);
assert(size > 0);

#if USE_MMTK
if (rb_mmtk_enabled_p()) {
if (size < sizeof(struct RString) + sizeof(rb_mmtk_stringext_t)) {
// When using MMTk, we allocate at least 48 bytes, including a trailing rb_mmtk_stringext_t.
size = sizeof(struct RString) + sizeof(rb_mmtk_stringext_t);
}
// The optimization about ec is unnecessary for MMTk. We avoid code duplication.
return str_alloc_embed(klass, capa);
}
#endif

size_t size = rb_str_embed_size(capa);
assert(size > 0);
assert(rb_gc_size_allocatable_p(size));

NEWOBJ_OF(str, struct RString, klass,
Expand All @@ -1969,17 +1962,14 @@ ec_str_alloc_embed(struct rb_execution_context_struct *ec, VALUE klass, size_t c
static inline VALUE
ec_str_alloc_heap(struct rb_execution_context_struct *ec, VALUE klass)
{
size_t size = sizeof(struct RString);

#if USE_MMTK
if (rb_mmtk_enabled_p()) {
// When using MMTk, we include a trailing rb_mmtk_stringext_t.
size = sizeof(struct RString) + sizeof(rb_mmtk_stringext_t);
// The optimization about ec is unnecessary for MMTk. We avoid code duplication.
return str_alloc_heap(klass);
}
#endif

NEWOBJ_OF(str, struct RString, klass,
T_STRING | STR_NOEMBED | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), size, ec);
T_STRING | STR_NOEMBED | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), sizeof(struct RString), ec);

return (VALUE)str;
}
Expand Down

0 comments on commit 0c2db55

Please sign in to comment.