diff options
author | Peter Zhu <peter@peterzhu.ca> | 2022-11-18 10:07:06 -0500 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2022-11-21 11:26:26 -0500 |
commit | 5f95228c76e6f6994eb4149217fe3e38f9ff8a27 (patch) | |
tree | 97753292d455b7e99d8116174676b10ce10559b8 /gc.c | |
parent | b7a0ce32da751b437b976b032e73281b9a56b509 (diff) | |
download | ruby-5f95228c76e6f6994eb4149217fe3e38f9ff8a27.tar.gz |
Add RVALUE_OVERHEAD and move ractor_belonging_id
This commit adds RVALUE_OVERHEAD for storing metadata at the end of the
slot. This commit moves the ractor_belonging_id in debug builds from the
flags to RVALUE_OVERHEAD which frees the 16 bits in the headers for
object shapes.
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 53 |
1 files changed, 39 insertions, 14 deletions
@@ -621,17 +621,29 @@ typedef struct RVALUE { VALUE v3; } values; } as; + + /* Start of RVALUE_OVERHEAD. + * Do not directly read these members from the RVALUE as they're located + * at the end of the slot (which may differ in size depending on the size + * pool). */ +#if RACTOR_CHECK_MODE + uint32_t _ractor_belonging_id; +#endif #if GC_DEBUG const char *file; int line; #endif } RVALUE; -#if GC_DEBUG -STATIC_ASSERT(sizeof_rvalue, offsetof(RVALUE, file) == SIZEOF_VALUE * 5); +#if RACTOR_CHECK_MODE +# define RVALUE_OVERHEAD (sizeof(RVALUE) - offsetof(RVALUE, _ractor_belonging_id)) +#elif GC_DEBUG +# define RVALUE_OVERHEAD (sizeof(RVALUE) - offsetof(RVALUE, file)) #else -STATIC_ASSERT(sizeof_rvalue, sizeof(RVALUE) == SIZEOF_VALUE * 5); +# define RVALUE_OVERHEAD 0 #endif + +STATIC_ASSERT(sizeof_rvalue, sizeof(RVALUE) == (SIZEOF_VALUE * 5) + RVALUE_OVERHEAD); STATIC_ASSERT(alignof_rvalue, RUBY_ALIGNOF(RVALUE) == SIZEOF_VALUE); typedef uintptr_t bits_t; @@ -2576,7 +2588,7 @@ newobj_init(VALUE klass, VALUE flags, int wb_protected, rb_objspace_t *objspace, size_t rb_gc_obj_slot_size(VALUE obj) { - return GET_HEAP_PAGE(obj)->slot_size; + return GET_HEAP_PAGE(obj)->slot_size - RVALUE_OVERHEAD; } static inline size_t @@ -2591,6 +2603,8 @@ size_pool_slot_size(unsigned char pool_id) GC_ASSERT(size_pools[pool_id].slot_size == (short)slot_size); #endif + slot_size -= RVALUE_OVERHEAD; + return slot_size; } @@ -2705,6 +2719,8 @@ static inline size_t size_pool_idx_for_size(size_t size) { #if USE_RVARGC + size += RVALUE_OVERHEAD; + size_t slot_count = CEILDIV(size, BASE_SLOT_SIZE); /* size_pool_idx is ceil(log2(slot_count)) */ @@ -2914,7 +2930,7 @@ rb_ec_wb_protected_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flag VALUE rb_newobj(void) { - return newobj_of(0, T_NONE, 0, 0, 0, FALSE, sizeof(RVALUE)); + return newobj_of(0, T_NONE, 0, 0, 0, FALSE, RVALUE_SIZE); } static size_t @@ -2966,7 +2982,7 @@ rb_newobj_of(VALUE klass, VALUE flags) return rb_class_instance_allocate_internal(klass, (flags | ROBJECT_EMBED) & ~FL_WB_PROTECTED, flags & FL_WB_PROTECTED); } else { - return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED, sizeof(RVALUE)); + return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED, RVALUE_SIZE); } } @@ -3004,7 +3020,7 @@ rb_imemo_name(enum imemo_type type) VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0) { - size_t size = sizeof(RVALUE); + size_t size = RVALUE_SIZE; VALUE flags = T_IMEMO | (type << FL_USHIFT); return newobj_of(v0, flags, v1, v2, v3, TRUE, size); } @@ -3012,7 +3028,7 @@ rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0) static VALUE rb_imemo_tmpbuf_new(VALUE v1, VALUE v2, VALUE v3, VALUE v0) { - size_t size = sizeof(RVALUE); + size_t size = sizeof(struct rb_imemo_tmpbuf_struct); VALUE flags = T_IMEMO | (imemo_tmpbuf << FL_USHIFT); return newobj_of(v0, flags, v1, v2, v3, FALSE, size); } @@ -3093,7 +3109,7 @@ rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FU { RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1); if (klass) rb_data_object_check(klass); - return newobj_of(klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, FALSE, sizeof(RVALUE)); + return newobj_of(klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, FALSE, sizeof(struct RTypedData)); } VALUE @@ -3109,7 +3125,7 @@ rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type) { RBIMPL_NONNULL_ARG(type); if (klass) rb_data_object_check(klass); - return newobj_of(klass, T_DATA, (VALUE)type, (VALUE)1, (VALUE)datap, type->flags & RUBY_FL_WB_PROTECTED, sizeof(RVALUE)); + return newobj_of(klass, T_DATA, (VALUE)type, (VALUE)1, (VALUE)datap, type->flags & RUBY_FL_WB_PROTECTED, sizeof(struct RTypedData)); } VALUE @@ -4974,7 +4990,7 @@ obj_memsize_of(VALUE obj, int use_all_types) BUILTIN_TYPE(obj), (void*)obj); } - return size + GET_HEAP_PAGE(obj)->slot_size; + return size + rb_gc_obj_slot_size(obj); } size_t @@ -9883,6 +9899,14 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t src_slot_size, s /* Move the object */ memcpy(dest, src, MIN(src_slot_size, slot_size)); + + if (RVALUE_OVERHEAD > 0) { + void *dest_overhead = (void *)(((uintptr_t)dest) + slot_size - RVALUE_OVERHEAD); + void *src_overhead = (void *)(((uintptr_t)src) + src_slot_size - RVALUE_OVERHEAD); + + memcpy(dest_overhead, src_overhead, RVALUE_OVERHEAD); + } + memset(src, 0, src_slot_size); /* Set bits for object in new location */ @@ -10005,7 +10029,7 @@ gc_ref_update_array(rb_objspace_t * objspace, VALUE v) } #if USE_RVARGC - if ((size_t)GET_HEAP_PAGE(v)->slot_size >= rb_ary_size_as_embedded(v)) { + if (rb_gc_obj_slot_size(v) >= rb_ary_size_as_embedded(v)) { if (rb_ary_embeddable_p(v)) { rb_ary_make_embedded(v); } @@ -10516,7 +10540,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) // if, after move the string is not embedded, and can fit in the // slot it's been placed in, then re-embed it - if ((size_t)GET_HEAP_PAGE(obj)->slot_size >= rb_str_size_as_embedded(obj)) { + if (rb_gc_obj_slot_size(obj) >= rb_str_size_as_embedded(obj)) { if (!STR_EMBED_P(obj) && rb_str_reembeddable_p(obj)) { rb_str_make_embedded(obj); } @@ -14339,7 +14363,8 @@ Init_GC(void) gc_constants = rb_hash_new(); rb_hash_aset(gc_constants, ID2SYM(rb_intern("DEBUG")), RBOOL(GC_DEBUG)); - rb_hash_aset(gc_constants, ID2SYM(rb_intern("BASE_SLOT_SIZE")), SIZET2NUM(BASE_SLOT_SIZE)); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("BASE_SLOT_SIZE")), SIZET2NUM(BASE_SLOT_SIZE - RVALUE_OVERHEAD)); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), SIZET2NUM(RVALUE_OVERHEAD)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(sizeof(RVALUE))); rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_OBJ_LIMIT")), SIZET2NUM(HEAP_PAGE_OBJ_LIMIT)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_SIZE")), SIZET2NUM(HEAP_PAGE_BITMAP_SIZE)); |