1010 */
1111#include "id.h"
1212#include "id_table.h" /* for struct rb_id_table */
13+ #include "internal/object.h" /* for rb_class_allocate_instance */
1314#include "internal/namespace.h" /* for rb_current_namespace */
1415#include "internal/serial.h" /* for rb_serial_t */
1516#include "internal/static_assert.h"
@@ -79,7 +80,7 @@ struct rb_cvar_class_tbl_entry {
7980struct rb_classext_struct {
8081 const rb_namespace_t * ns ;
8182 VALUE super ;
82- VALUE * fields ; // Fields are either ivar or other internal properties stored inline
83+ VALUE fields_obj ; // Fields are either ivar or other internal properties stored inline
8384 struct rb_id_table * m_tbl ;
8485 struct rb_id_table * const_tbl ;
8586 struct rb_id_table * callable_m_tbl ;
@@ -176,7 +177,8 @@ static inline rb_classext_t * RCLASS_EXT_WRITABLE(VALUE obj);
176177
177178#define RCLASSEXT_NS (ext ) (ext->ns)
178179#define RCLASSEXT_SUPER (ext ) (ext->super)
179- #define RCLASSEXT_FIELDS (ext ) (ext->fields)
180+ #define RCLASSEXT_FIELDS (ext ) (ext->fields_obj ? ROBJECT_FIELDS(ext->fields_obj) : NULL)
181+ #define RCLASSEXT_FIELDS_OBJ (ext ) (ext->fields_obj)
180182#define RCLASSEXT_M_TBL (ext ) (ext->m_tbl)
181183#define RCLASSEXT_CONST_TBL (ext ) (ext->const_tbl)
182184#define RCLASSEXT_CALLABLE_M_TBL (ext ) (ext->callable_m_tbl)
@@ -209,7 +211,7 @@ static inline void RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE
209211#define RCLASS_PRIME_NS (c ) (RCLASS_EXT_PRIME(c)->ns)
210212// To invalidate CC by inserting&invalidating method entry into tables containing the target cme
211213// See clear_method_cache_by_id_in_class()
212- #define RCLASS_PRIME_FIELDS (c ) (RCLASS_EXT_PRIME(c)->fields )
214+ #define RCLASS_PRIME_FIELDS_OBJ (c ) (RCLASS_EXT_PRIME(c)->fields_obj )
213215#define RCLASS_PRIME_M_TBL (c ) (RCLASS_EXT_PRIME(c)->m_tbl)
214216#define RCLASS_PRIME_CONST_TBL (c ) (RCLASS_EXT_PRIME(c)->const_tbl)
215217#define RCLASS_PRIME_CALLABLE_M_TBL (c ) (RCLASS_EXT_PRIME(c)->callable_m_tbl)
@@ -531,6 +533,24 @@ RCLASS_WRITE_SUPER(VALUE klass, VALUE super)
531533 RB_OBJ_WRITE (klass , & RCLASSEXT_SUPER (RCLASS_EXT_WRITABLE (klass )), super );
532534}
533535
536+ static inline VALUE
537+ RCLASS_FIELDS_OBJ (VALUE obj )
538+ {
539+ RUBY_ASSERT (RB_TYPE_P (obj , RUBY_T_CLASS ) || RB_TYPE_P (obj , RUBY_T_MODULE ));
540+ return RCLASSEXT_FIELDS_OBJ (RCLASS_EXT_READABLE (obj ));
541+ }
542+
543+ static inline VALUE
544+ RCLASS_ENSURE_FIELDS_OBJ (VALUE obj )
545+ {
546+ RUBY_ASSERT (RB_TYPE_P (obj , RUBY_T_CLASS ) || RB_TYPE_P (obj , RUBY_T_MODULE ));
547+ rb_classext_t * ext = RCLASS_EXT_READABLE (obj );
548+ if (!ext -> fields_obj ) {
549+ RB_OBJ_WRITE (obj , & ext -> fields_obj , rb_class_allocate_instance (rb_singleton_class (obj )));
550+ }
551+ return ext -> fields_obj ;
552+ }
553+
534554static inline st_table *
535555RCLASS_FIELDS_HASH (VALUE obj )
536556{
@@ -547,20 +567,41 @@ RCLASS_WRITABLE_FIELDS_HASH(VALUE obj)
547567 return (st_table * )RCLASSEXT_FIELDS (RCLASS_EXT_WRITABLE (obj ));
548568}
549569
570+ static inline VALUE
571+ RCLASS_WRITABLE_FIELDS_OBJ (VALUE obj )
572+ {
573+ RUBY_ASSERT (RB_TYPE_P (obj , RUBY_T_CLASS ) || RB_TYPE_P (obj , RUBY_T_MODULE ));
574+ return RCLASSEXT_FIELDS_OBJ (RCLASS_EXT_WRITABLE (obj ));
575+ }
576+
577+ static inline void
578+ RCLASSEXT_SET_FIELDS_HASH (VALUE obj , rb_classext_t * ext , const st_table * tbl )
579+ {
580+ RUBY_ASSERT (RB_TYPE_P (obj , RUBY_T_CLASS ) || RB_TYPE_P (obj , RUBY_T_MODULE ));
581+ RUBY_ASSERT (rb_shape_obj_too_complex_p (obj ));
582+
583+ if (!ext -> fields_obj ) {
584+ // FIXME: We can trigger GC here and `*tbl` may not be marked
585+ RB_OBJ_WRITE (obj , & ext -> fields_obj , rb_class_allocate_instance (rb_singleton_class (obj )));
586+ }
587+ ROBJECT_SET_FIELDS_HASH (ext -> fields_obj , tbl );
588+ }
589+
550590static inline void
551591RCLASS_SET_FIELDS_HASH (VALUE obj , const st_table * tbl )
552592{
553593 RUBY_ASSERT (RB_TYPE_P (obj , RUBY_T_CLASS ) || RB_TYPE_P (obj , RUBY_T_MODULE ));
554594 RUBY_ASSERT (rb_shape_obj_too_complex_p (obj ));
555- RCLASSEXT_FIELDS (RCLASS_EXT_PRIME (obj )) = (VALUE * )tbl ;
595+
596+ RCLASSEXT_SET_FIELDS_HASH (obj , RCLASS_EXT_PRIME (obj ), tbl );
556597}
557598
558599static inline void
559600RCLASS_WRITE_FIELDS_HASH (VALUE obj , const st_table * tbl )
560601{
561602 RUBY_ASSERT (RB_TYPE_P (obj , RUBY_T_CLASS ) || RB_TYPE_P (obj , RUBY_T_MODULE ));
562603 RUBY_ASSERT (rb_shape_obj_too_complex_p (obj ));
563- RCLASSEXT_FIELDS ( RCLASS_EXT_WRITABLE (obj )) = ( VALUE * ) tbl ;
604+ RCLASSEXT_SET_FIELDS_HASH ( obj , RCLASS_EXT_WRITABLE (obj ), tbl ) ;
564605}
565606
566607static inline uint32_t
0 commit comments