aboutsummaryrefslogtreecommitdiffstats
path: root/internal
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2023-10-25 16:52:37 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2023-11-20 16:09:48 -0800
commit6fce8c79807e69cfe475b5291e892567c869fbcc (patch)
tree42419f2e00fea8e2d05674873dcbfccb511b83f4 /internal
parent7164715666cfbffd5540ee374eee2a5568342d2d (diff)
downloadruby-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.h39
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);