diff options
author | Aaron Patterson <tenderlove@ruby-lang.org> | 2023-10-25 16:52:37 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2023-11-20 16:09:48 -0800 |
commit | 6fce8c79807e69cfe475b5291e892567c869fbcc (patch) | |
tree | 42419f2e00fea8e2d05674873dcbfccb511b83f4 /internal | |
parent | 7164715666cfbffd5540ee374eee2a5568342d2d (diff) | |
download | ruby-6fce8c79807e69cfe475b5291e892567c869fbcc.tar.gz |
Don't try compacting ivars on Classes that are "too complex"
Too complex classes use a hash table to store ivs, and should always pin
their IVs. We shouldn't touch those classes in compaction.
Diffstat (limited to 'internal')
-rw-r--r-- | internal/class.h | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/internal/class.h b/internal/class.h index b055f07317..324e7b3219 100644 --- a/internal/class.h +++ b/internal/class.h @@ -19,6 +19,7 @@ #include "shape.h" #include "ruby_assert.h" #include "vm_core.h" +#include "vm_sync.h" #include "method.h" /* for rb_cref_t */ #ifdef RCLASS_SUPER @@ -111,6 +112,44 @@ struct RClass_and_rb_classext_t { #define RCLASS_SUPERCLASSES_INCLUDE_SELF FL_USER2 #define RICLASS_ORIGIN_SHARED_MTBL FL_USER3 +static inline st_table * +RCLASS_IV_HASH(VALUE obj) +{ + RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE)); + RUBY_ASSERT(rb_shape_obj_too_complex(obj)); + return (st_table *)RCLASS_IVPTR(obj); +} + +static inline void +RCLASS_SET_IV_HASH(VALUE obj, const st_table *tbl) +{ + RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE)); + RUBY_ASSERT(rb_shape_obj_too_complex(obj)); + RCLASS_IVPTR(obj) = (VALUE *)tbl; +} + +static inline uint32_t +RCLASS_IV_COUNT(VALUE obj) +{ + RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE)); + if (rb_shape_obj_too_complex(obj)) { + uint32_t count; + + // "Too complex" classes could have their IV hash mutated in + // parallel, so lets lock around getting the hash size. + RB_VM_LOCK_ENTER(); + { + count = (uint32_t)rb_st_table_size(RCLASS_IV_HASH(obj)); + } + RB_VM_LOCK_LEAVE(); + + return count; + } + else { + return rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(obj))->next_iv_index; + } +} + /* class.c */ void rb_class_subclass_add(VALUE super, VALUE klass); void rb_class_remove_from_super_subclasses(VALUE); |