@@ -1861,9 +1861,40 @@ static const rb_data_type_t id_to_obj_tbl_type = {
1861
1861
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
1862
1862
};
1863
1863
1864
+ static VALUE
1865
+ class_object_id (VALUE klass )
1866
+ {
1867
+ VALUE id = RCLASS (klass )-> object_id ;
1868
+ if (!id ) {
1869
+ unsigned int lock_lev = rb_gc_vm_lock ();
1870
+ id = ULL2NUM (next_object_id );
1871
+ next_object_id += OBJ_ID_INCREMENT ;
1872
+ VALUE existing_id = RUBY_ATOMIC_VALUE_CAS (RCLASS (klass )-> object_id , 0 , id );
1873
+ if (existing_id ) {
1874
+ id = existing_id ;
1875
+ }
1876
+ else if (RB_UNLIKELY (id_to_obj_tbl )) {
1877
+ st_insert (id_to_obj_tbl , id , klass );
1878
+ }
1879
+ rb_gc_vm_unlock (lock_lev );
1880
+ }
1881
+ return id ;
1882
+ }
1883
+
1864
1884
static VALUE
1865
1885
object_id (VALUE obj )
1866
1886
{
1887
+ switch (BUILTIN_TYPE (obj )) {
1888
+ case T_CLASS :
1889
+ case T_MODULE :
1890
+ // With namespaces, classes and modules have different fields
1891
+ // in different namespaces, so we cannot store the object id
1892
+ // in fields.
1893
+ return class_object_id (obj );
1894
+ default :
1895
+ break ;
1896
+ }
1897
+
1867
1898
VALUE id = Qfalse ;
1868
1899
unsigned int lock_lev ;
1869
1900
@@ -1896,8 +1927,19 @@ static void
1896
1927
build_id_to_obj_i (VALUE obj , void * data )
1897
1928
{
1898
1929
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 );
1930
+
1931
+ switch (BUILTIN_TYPE (obj )) {
1932
+ case T_CLASS :
1933
+ case T_MODULE :
1934
+ if (RCLASS (obj )-> object_id ) {
1935
+ st_insert (id_to_obj_tbl , RCLASS (obj )-> object_id , obj );
1936
+ }
1937
+ break ;
1938
+ default :
1939
+ if (rb_shape_obj_has_id (obj )) {
1940
+ st_insert (id_to_obj_tbl , rb_obj_id (obj ), obj );
1941
+ }
1942
+ break ;
1901
1943
}
1902
1944
}
1903
1945
@@ -1940,16 +1982,30 @@ object_id_to_ref(void *objspace_ptr, VALUE object_id)
1940
1982
static inline void
1941
1983
obj_free_object_id (VALUE obj )
1942
1984
{
1985
+ VALUE obj_id = 0 ;
1943
1986
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 ));
1987
+ switch (BUILTIN_TYPE (obj )) {
1988
+ case T_CLASS :
1989
+ case T_MODULE :
1990
+ if (RCLASS (obj )-> object_id ) {
1991
+ obj_id = RCLASS (obj )-> object_id ;
1992
+ }
1993
+ break ;
1994
+ default :
1995
+ if (rb_shape_obj_has_id (obj )) {
1996
+ obj_id = object_id (obj );
1997
+ }
1998
+ break ;
1999
+ }
2000
+ }
1947
2001
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
- }
2002
+ if (RB_UNLIKELY (obj_id )) {
2003
+ RUBY_ASSERT (FIXNUM_P (obj_id ) || RB_TYPE_P (obj , T_BIGNUM ));
2004
+
2005
+ if (!st_delete (id_to_obj_tbl , (st_data_t * )& obj_id , NULL )) {
2006
+ // If we're currently building the table then it's not a bug
2007
+ if (id_to_obj_tbl_built ) {
2008
+ rb_bug ("Object ID seen, but not in id_to_obj table: object_id=%llu object=%s" , NUM2ULL (obj_id ), rb_obj_info (obj ));
1953
2009
}
1954
2010
}
1955
2011
}
0 commit comments