@@ -1937,20 +1937,33 @@ object_id_get(VALUE obj, shape_id_t shape_id)
19371937 else {
19381938 id = rb_obj_field_get (obj , rb_shape_object_id_inline (shape_id ));
19391939 }
1940+
1941+ #if RUBY_DEBUG
1942+ if (!(FIXNUM_P (id ) || RB_TYPE_P (id , T_BIGNUM ))) {
1943+ rb_p (obj );
1944+ rb_bug ("Object's shape includes object_id, but it's missing %s" , rb_obj_info (obj ));
1945+ }
1946+ #endif
1947+
19401948 break ;
19411949 case SHAPE_EXTERNAL_OBJ_ID :
1942- RUBY_ASSERT ( obj_to_id_tbl );
1943- st_lookup ( obj_to_id_tbl , obj , & id );
1944- break ;
1945- }
1950+ {
1951+ RUBY_ASSERT ( obj_to_id_tbl );
1952+ unsigned int lock_lev = RB_GC_VM_LOCK () ;
1953+ st_lookup ( obj_to_id_tbl , obj , & id );
19461954
19471955#if RUBY_DEBUG
19481956 if (!(FIXNUM_P (id ) || RB_TYPE_P (id , T_BIGNUM ))) {
19491957 rb_p (obj );
1950- rb_bug ("Object's shape includes object_id, but it's missing %s" , rb_obj_info (obj ));
1958+ rb_bug ("Object's shape includes external object_id, but it's missing in obj_to_id_tbl %s" , rb_obj_info (obj ));
19511959 }
19521960#endif
19531961
1962+ RB_GC_VM_UNLOCK (lock_lev );
1963+ }
1964+ break ;
1965+ }
1966+
19541967 return id ;
19551968}
19561969
@@ -1968,9 +1981,9 @@ object_id0(VALUE obj, bool shareable)
19681981
19691982 attr_index_t capacity = RSHAPE_CAPACITY (shape_id );
19701983 attr_index_t free_capacity = capacity - RSHAPE_LEN (shape_id );
1971- if (shareable && capacity && !free_capacity ) {
1972- // The object is shared and has no free capacity, we can't
1973- // safely store the object_id inline .
1984+ if (shareable && RB_TYPE_P ( obj , T_OBJECT ) && capacity && !free_capacity ) {
1985+ // If the object was shared and has no free capacity, we can't safely store the object_id inline.
1986+ // This is only a problem for T_OBJECT, given other types have external fields and can do RCU .
19741987 shape_id_t next_shape_id = rb_shape_transition_object_id_external (obj );
19751988 if (RB_UNLIKELY (!obj_to_id_tbl )) {
19761989 obj_to_id_tbl = st_init_numtable ();
@@ -4097,6 +4110,30 @@ vm_weak_table_id2ref_foreach_update(st_data_t *key, st_data_t *value, st_data_t
40974110 return ST_CONTINUE ;
40984111}
40994112
4113+ static int
4114+ vm_weak_table_obj2id_foreach (st_data_t key , st_data_t value , st_data_t data , int error )
4115+ {
4116+ struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
4117+
4118+ if (!iter_data -> weak_only && !FIXNUM_P ((VALUE )value )) {
4119+ iter_data -> callback ((VALUE )value , iter_data -> data );
4120+ }
4121+
4122+ return iter_data -> callback ((VALUE )key , iter_data -> data );
4123+ }
4124+
4125+ static int
4126+ vm_weak_table_obj2id_foreach_update (st_data_t * key , st_data_t * value , st_data_t data , int existing )
4127+ {
4128+ struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
4129+
4130+ if (!iter_data -> weak_only && !FIXNUM_P ((VALUE )* value )) {
4131+ iter_data -> update_callback ((VALUE * )value , iter_data -> data );
4132+ }
4133+
4134+ return iter_data -> update_callback ((VALUE * )key , iter_data -> data );
4135+ }
4136+
41004137static int
41014138vm_weak_table_gen_fields_foreach (st_data_t key , st_data_t value , st_data_t data )
41024139{
@@ -4240,8 +4277,8 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
42404277 if (obj_to_id_tbl ) {
42414278 st_foreach_with_replace (
42424279 obj_to_id_tbl ,
4243- vm_weak_table_foreach_weak_key ,
4244- vm_weak_table_foreach_update_weak_key ,
4280+ vm_weak_table_obj2id_foreach ,
4281+ vm_weak_table_obj2id_foreach_update ,
42454282 (st_data_t )& foreach_data
42464283 );
42474284 }
0 commit comments