ruby-changes:74302
From: John <ko1@a...>
Date: Tue, 1 Nov 2022 06:05:59 +0900 (JST)
Subject: [ruby-changes:74302] 02f1554224 (master): Implement object shapes for T_CLASS and T_MODULE (#6637)
https://git.ruby-lang.org/ruby.git/commit/?id=02f1554224 From 02f15542245222ee392e68fb244b3b8c4a12ad82 Mon Sep 17 00:00:00 2001 From: John Hawthorn <john@h...> Date: Mon, 31 Oct 2022 14:05:37 -0700 Subject: Implement object shapes for T_CLASS and T_MODULE (#6637) * Avoid RCLASS_IV_TBL in marshal.c * Avoid RCLASS_IV_TBL for class names * Avoid RCLASS_IV_TBL for autoload * Avoid RCLASS_IV_TBL for class variables * Avoid copying RCLASS_IV_TBL onto ICLASSes * Use object shapes for Class and Module IVs --- class.c | 21 +--- gc.c | 23 ++-- internal/class.h | 4 +- internal/variable.h | 2 +- marshal.c | 2 +- object.c | 18 +-- shape.c | 9 +- shape.h | 24 ++++ variable.c | 336 +++++++++++++++++++++++++++++----------------------- vm_insnhelper.c | 28 +++-- 10 files changed, 265 insertions(+), 202 deletions(-) diff --git a/class.c b/class.c index 3d8e205007..d181fb0b2e 100644 --- a/class.c +++ b/class.c @@ -213,7 +213,6 @@ class_alloc(VALUE flags, VALUE klass) https://github.com/ruby/ruby/blob/trunk/class.c#L213 #endif /* ZALLOC - RCLASS_IV_TBL(obj) = 0; RCLASS_CONST_TBL(obj) = 0; RCLASS_M_TBL(obj) = 0; RCLASS_IV_INDEX_TBL(obj) = 0; @@ -402,23 +401,19 @@ class_init_copy_check(VALUE clone, VALUE orig) https://github.com/ruby/ruby/blob/trunk/class.c#L401 static void copy_tables(VALUE clone, VALUE orig) { - if (RCLASS_IV_TBL(clone)) { - st_free_table(RCLASS_IV_TBL(clone)); - RCLASS_IV_TBL(clone) = 0; - } if (RCLASS_CONST_TBL(clone)) { rb_free_const_table(RCLASS_CONST_TBL(clone)); RCLASS_CONST_TBL(clone) = 0; } RCLASS_M_TBL(clone) = 0; - if (RCLASS_IV_TBL(orig)) { + if (!RB_TYPE_P(clone, T_ICLASS)) { st_data_t id; rb_iv_tbl_copy(clone, orig); CONST_ID(id, "__tmp_classpath__"); - st_delete(RCLASS_IV_TBL(clone), &id, 0); + rb_attr_delete(clone, id); CONST_ID(id, "__classpath__"); - st_delete(RCLASS_IV_TBL(clone), &id, 0); + rb_attr_delete(clone, id); } if (RCLASS_CONST_TBL(orig)) { struct clone_const_arg arg; @@ -520,7 +515,6 @@ rb_mod_init_copy(VALUE clone, VALUE orig) https://github.com/ruby/ruby/blob/trunk/class.c#L515 prev_clone_p = clone_p; RCLASS_M_TBL(clone_p) = RCLASS_M_TBL(p); RCLASS_CONST_TBL(clone_p) = RCLASS_CONST_TBL(p); - RCLASS_IV_TBL(clone_p) = RCLASS_IV_TBL(p); RCLASS_ALLOCATOR(clone_p) = RCLASS_ALLOCATOR(p); if (RB_TYPE_P(clone, T_CLASS)) { RCLASS_SET_INCLUDER(clone_p, clone); @@ -607,9 +601,7 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach) https://github.com/ruby/ruby/blob/trunk/class.c#L601 RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass)); RCLASS_ALLOCATOR(clone) = RCLASS_ALLOCATOR(klass); - if (RCLASS_IV_TBL(klass)) { - rb_iv_tbl_copy(clone, klass); - } + rb_iv_tbl_copy(clone, klass); if (RCLASS_CONST_TBL(klass)) { struct clone_const_arg arg; arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0); @@ -1062,13 +1054,10 @@ rb_include_class_new(VALUE module, VALUE super) https://github.com/ruby/ruby/blob/trunk/class.c#L1054 module = METACLASS_OF(module); } RUBY_ASSERT(!RB_TYPE_P(module, T_ICLASS)); - if (!RCLASS_IV_TBL(module)) { - RCLASS_IV_TBL(module) = st_init_numtable(); - } if (!RCLASS_CONST_TBL(module)) { RCLASS_CONST_TBL(module) = rb_id_table_create(0); } - RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); + RCLASS_CVC_TBL(klass) = RCLASS_CVC_TBL(module); RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); diff --git a/gc.c b/gc.c index 76a1f0f2de..75b330ede5 100644 --- a/gc.c +++ b/gc.c @@ -3447,8 +3447,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L3447 case T_CLASS: rb_id_table_free(RCLASS_M_TBL(obj)); cc_table_free(objspace, obj, FALSE); - if (RCLASS_IV_TBL(obj)) { - st_free_table(RCLASS_IV_TBL(obj)); + if (RCLASS_IVPTR(obj)) { + xfree(RCLASS_IVPTR(obj)); } if (RCLASS_CONST_TBL(obj)) { rb_free_const_table(RCLASS_CONST_TBL(obj)); @@ -4865,15 +4865,11 @@ obj_memsize_of(VALUE obj, int use_all_types) https://github.com/ruby/ruby/blob/trunk/gc.c#L4865 if (RCLASS_M_TBL(obj)) { size += rb_id_table_memsize(RCLASS_M_TBL(obj)); } - if (RCLASS_IV_TBL(obj)) { - size += st_memsize(RCLASS_IV_TBL(obj)); - } + // class IV sizes are allocated as powers of two + size += SIZEOF_VALUE << bit_length(RCLASS_IV_COUNT(obj)); if (RCLASS_CVC_TBL(obj)) { size += rb_id_table_memsize(RCLASS_CVC_TBL(obj)); } - if (RCLASS_EXT(obj)->iv_tbl) { - size += st_memsize(RCLASS_EXT(obj)->iv_tbl); - } if (RCLASS_EXT(obj)->const_tbl) { size += rb_id_table_memsize(RCLASS_EXT(obj)->const_tbl); } @@ -7212,7 +7208,9 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L7208 mark_m_tbl(objspace, RCLASS_M_TBL(obj)); cc_table_mark(objspace, obj); - mark_tbl_no_pin(objspace, RCLASS_IV_TBL(obj)); + for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) { + gc_mark(objspace, RCLASS_IVPTR(obj)[i]); + } mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); break; @@ -10439,7 +10437,9 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L10437 update_cvc_tbl(objspace, obj); update_superclasses(objspace, obj); - gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj)); + for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) { + UPDATE_IF_MOVED(objspace, RCLASS_IVPTR(obj)[i]); + } update_class_ext(objspace, RCLASS_EXT(obj)); update_const_tbl(objspace, RCLASS_CONST_TBL(obj)); @@ -10454,9 +10454,6 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L10454 UPDATE_IF_MOVED(objspace, RCLASS(obj)->super); } if (!RCLASS_EXT(obj)) break; - if (RCLASS_IV_TBL(obj)) { - gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj)); - } update_class_ext(objspace, RCLASS_EXT(obj)); update_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj)); update_cc_tbl(objspace, obj); diff --git a/internal/class.h b/internal/class.h index 63fe84c6ab..784d508e20 100644 --- a/internal/class.h +++ b/internal/class.h @@ -33,7 +33,7 @@ struct rb_cvar_class_tbl_entry { https://github.com/ruby/ruby/blob/trunk/internal/class.h#L33 }; struct rb_classext_struct { - struct st_table *iv_tbl; + VALUE *iv_ptr; struct rb_id_table *const_tbl; struct rb_id_table *callable_m_tbl; struct rb_id_table *cc_tbl; /* ID -> [[ci, cc1], cc2, ...] */ @@ -75,9 +75,9 @@ typedef struct rb_classext_struct rb_classext_t; https://github.com/ruby/ruby/blob/trunk/internal/class.h#L75 #else # define RCLASS_EXT(c) (RCLASS(c)->ptr) #endif -#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) #define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) #define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) +#define RCLASS_IVPTR(c) (RCLASS_EXT(c)->iv_ptr) #define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl) #define RCLASS_CC_TBL(c) (RCLASS_EXT(c)->cc_tbl) #define RCLASS_CVC_TBL(c) (RCLASS_EXT(c)->cvc_tbl) diff --git a/internal/variable.h b/internal/variable.h index bb24f5129f..734884a5f6 100644 --- a/internal/variable.h +++ b/internal/variable.h @@ -24,7 +24,6 @@ void rb_gc_update_global_tbl(void); https://github.com/ruby/ruby/blob/trunk/internal/variable.h#L24 size_t rb_generic_ivar_memsize(VALUE); VALUE rb_search_class_path(VALUE); VALUE rb_attr_delete(VALUE, ID); -VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef); void rb_autoload_str(VALUE mod, ID id, VALUE file); VALUE rb_autoload_at_p(VALUE, ID, int); NORETURN(VALUE rb_mod_const_missing(VALUE,VALUE)); @@ -49,6 +48,7 @@ void rb_iv_tbl_copy(VALUE dst, VALUE src); https://github.com/ruby/ruby/blob/trunk/internal/variable.h#L48 RUBY_SYMBOL_EXPORT_END MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef); VALUE rb_gvar_get(ID); VALUE rb_gvar_set(ID, VALUE); VALUE rb_gvar_defined(ID); diff --git a/marshal.c b/marshal.c index 59edbfe53a..d956260d96 100644 --- a/marshal.c +++ b/marshal.c @@ -523,7 +523,7 @@ hash_each(VALUE key, VALUE value, VALUE v) https://github.com/ruby/ruby/blob/trunk/marshal.c#L523 #define SINGLETON_DUMP_UNABLE_P(klass) \ (rb_id_table_size(RCLASS_M_TBL(klass)) > 0 || \ - (RCLASS_IV_TBL(klass) && RCLASS_IV_TBL(klass)->num_entries > 1)) + rb_ivar_count(klass) > 1) static void w_extended(VALUE klass, struct dump_arg *arg, int check) diff --git a/object.c b/object.c index aae6cc45a4..5f8568e3b4 100644 --- a/object.c +++ b/object.c @@ -298,20 +298,22 @@ init_copy(VALUE dest, VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L298 rb_copy_generic_ivar(dest, obj); rb_gc_copy_finalizer(dest, obj); - rb_shape_t *shape_to_set = rb_shape_get_shape(obj); + if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) { + rb_shape_t *shape_to_set = rb_shape_get_shape(obj); - // If the object is frozen, the "dup"'d object will *not* be frozen, - // so we need to copy the frozen shape's parent to the new object. - if (rb_shape_frozen_shape_p(shape_to_set)) { - shape_to_set = rb_shape_get_shape_by_id(shape_to_set->parent_id); + // If the object is frozen, the "dup"'d object will *not* be frozen, + // so we need to (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/