@@ -1937,20 +1937,34 @@ 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+ fprintf (stderr , "lookup: %p\n" , obj );
1954+ st_lookup (obj_to_id_tbl , obj , & id );
19461955
19471956#if RUBY_DEBUG
19481957 if (!(FIXNUM_P (id ) || RB_TYPE_P (id , T_BIGNUM ))) {
19491958 rb_p (obj );
1950- rb_bug ("Object's shape includes object_id, but it's missing %s" , rb_obj_info (obj ));
1959+ rb_bug ("Object's shape includes external object_id, but it's missing in obj_to_id_tbl %s" , rb_obj_info (obj ));
19511960 }
19521961#endif
19531962
1963+ RB_GC_VM_UNLOCK (lock_lev );
1964+ }
1965+ break ;
1966+ }
1967+
19541968 return id ;
19551969}
19561970
@@ -1968,9 +1982,9 @@ object_id0(VALUE obj, bool shareable)
19681982
19691983 attr_index_t capacity = RSHAPE_CAPACITY (shape_id );
19701984 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 .
1985+ if (shareable && RB_TYPE_P ( obj , T_OBJECT ) && capacity && !free_capacity ) {
1986+ // If the object was shared and has no free capacity, we can't safely store the object_id inline.
1987+ // This is only a problem for T_OBJECT, given other types have external fields and can do RCU .
19741988 shape_id_t next_shape_id = rb_shape_transition_object_id_external (obj );
19751989 if (RB_UNLIKELY (!obj_to_id_tbl )) {
19761990 obj_to_id_tbl = st_init_numtable ();
@@ -4097,6 +4111,30 @@ vm_weak_table_id2ref_foreach_update(st_data_t *key, st_data_t *value, st_data_t
40974111 return ST_CONTINUE ;
40984112}
40994113
4114+ static int
4115+ vm_weak_table_obj2id_foreach (st_data_t key , st_data_t value , st_data_t data , int error )
4116+ {
4117+ struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
4118+
4119+ if (!iter_data -> weak_only && !FIXNUM_P ((VALUE )value )) {
4120+ iter_data -> callback ((VALUE )value , iter_data -> data );
4121+ }
4122+
4123+ return iter_data -> callback ((VALUE )key , iter_data -> data );
4124+ }
4125+
4126+ static int
4127+ vm_weak_table_obj2id_foreach_update (st_data_t * key , st_data_t * value , st_data_t data , int existing )
4128+ {
4129+ struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
4130+
4131+ if (!iter_data -> weak_only && !FIXNUM_P ((VALUE )* value )) {
4132+ iter_data -> update_callback ((VALUE * )value , iter_data -> data );
4133+ }
4134+
4135+ return iter_data -> update_callback ((VALUE * )key , iter_data -> data );
4136+ }
4137+
41004138static int
41014139vm_weak_table_gen_fields_foreach (st_data_t key , st_data_t value , st_data_t data )
41024140{
@@ -4240,8 +4278,8 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
42404278 if (obj_to_id_tbl ) {
42414279 st_foreach_with_replace (
42424280 obj_to_id_tbl ,
4243- vm_weak_table_foreach_weak_key ,
4244- vm_weak_table_foreach_update_weak_key ,
4281+ vm_weak_table_obj2id_foreach ,
4282+ vm_weak_table_obj2id_foreach_update ,
42454283 (st_data_t )& foreach_data
42464284 );
42474285 }
0 commit comments