@@ -1861,9 +1861,42 @@ static const rb_data_type_t id_to_obj_tbl_type = {
18611861 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
18621862};
18631863
1864+ #define RUBY_ATOMIC_VALUE_LOAD (x ) (VALUE)(RUBY_ATOMIC_PTR_LOAD(x))
1865+
1866+ static VALUE
1867+ class_object_id (VALUE klass )
1868+ {
1869+ VALUE id = RUBY_ATOMIC_VALUE_LOAD (RCLASS (klass )-> object_id );
1870+ if (!id ) {
1871+ unsigned int lock_lev = rb_gc_vm_lock ();
1872+ id = ULL2NUM (next_object_id );
1873+ next_object_id += OBJ_ID_INCREMENT ;
1874+ VALUE existing_id = RUBY_ATOMIC_VALUE_CAS (RCLASS (klass )-> object_id , 0 , id );
1875+ if (existing_id ) {
1876+ id = existing_id ;
1877+ }
1878+ else if (RB_UNLIKELY (id_to_obj_tbl )) {
1879+ st_insert (id_to_obj_tbl , id , klass );
1880+ }
1881+ rb_gc_vm_unlock (lock_lev );
1882+ }
1883+ return id ;
1884+ }
1885+
18641886static VALUE
18651887object_id (VALUE obj )
18661888{
1889+ switch (BUILTIN_TYPE (obj )) {
1890+ case T_CLASS :
1891+ case T_MODULE :
1892+ // With namespaces, classes and modules have different fields
1893+ // in different namespaces, so we cannot store the object id
1894+ // in fields.
1895+ return class_object_id (obj );
1896+ default :
1897+ break ;
1898+ }
1899+
18671900 VALUE id = Qfalse ;
18681901 unsigned int lock_lev ;
18691902
@@ -1896,8 +1929,19 @@ static void
18961929build_id_to_obj_i (VALUE obj , void * data )
18971930{
18981931 st_table * id_to_obj_tbl = (st_table * )data ;
1899- if (rb_shape_obj_has_id (obj )) {
1900- st_insert (id_to_obj_tbl , rb_obj_id (obj ), obj );
1932+
1933+ switch (BUILTIN_TYPE (obj )) {
1934+ case T_CLASS :
1935+ case T_MODULE :
1936+ if (RCLASS (obj )-> object_id ) {
1937+ st_insert (id_to_obj_tbl , RCLASS (obj )-> object_id , obj );
1938+ }
1939+ break ;
1940+ default :
1941+ if (rb_shape_obj_has_id (obj )) {
1942+ st_insert (id_to_obj_tbl , rb_obj_id (obj ), obj );
1943+ }
1944+ break ;
19011945 }
19021946}
19031947
@@ -1940,16 +1984,30 @@ object_id_to_ref(void *objspace_ptr, VALUE object_id)
19401984static inline void
19411985obj_free_object_id (VALUE obj )
19421986{
1987+ VALUE obj_id = 0 ;
19431988 if (RB_UNLIKELY (id_to_obj_tbl )) {
1944- if (rb_shape_obj_has_id (obj )) {
1945- VALUE obj_id = object_id (obj );
1946- RUBY_ASSERT (FIXNUM_P (obj_id ) || RB_TYPE_P (obj , T_BIGNUM ));
1989+ switch (BUILTIN_TYPE (obj )) {
1990+ case T_CLASS :
1991+ case T_MODULE :
1992+ if (RCLASS (obj )-> object_id ) {
1993+ obj_id = RCLASS (obj )-> object_id ;
1994+ }
1995+ break ;
1996+ default :
1997+ if (rb_shape_obj_has_id (obj )) {
1998+ obj_id = object_id (obj );
1999+ }
2000+ break ;
2001+ }
2002+ }
19472003
1948- if (!st_delete (id_to_obj_tbl , (st_data_t * )& obj_id , NULL )) {
1949- // If we're currently building the table then it's not a bug
1950- if (id_to_obj_tbl_built ) {
1951- rb_bug ("Object ID seen, but not in id_to_obj table: object_id=%llu object=%s" , NUM2ULL (obj_id ), rb_obj_info (obj ));
1952- }
2004+ if (RB_UNLIKELY (obj_id )) {
2005+ RUBY_ASSERT (FIXNUM_P (obj_id ) || RB_TYPE_P (obj , T_BIGNUM ));
2006+
2007+ if (!st_delete (id_to_obj_tbl , (st_data_t * )& obj_id , NULL )) {
2008+ // If we're currently building the table then it's not a bug
2009+ if (id_to_obj_tbl_built ) {
2010+ rb_bug ("Object ID seen, but not in id_to_obj table: object_id=%llu object=%s" , NUM2ULL (obj_id ), rb_obj_info (obj ));
19532011 }
19542012 }
19552013 }
0 commit comments