@@ -2015,49 +2015,39 @@ object_id_to_ref(void *objspace_ptr, VALUE object_id)
20152015static inline void
20162016obj_free_object_id (VALUE obj )
20172017{
2018- if (RB_BUILTIN_TYPE (obj ) == T_IMEMO ) {
2019- return ;
2020- }
2021-
2022- #if RUBY_DEBUG
2023- switch (BUILTIN_TYPE (obj )) {
2024- case T_CLASS :
2025- case T_MODULE :
2026- break ;
2027- default :
2028- if (rb_shape_obj_has_id (obj )) {
2029- VALUE id = object_id_get (obj , RBASIC_SHAPE_ID (obj )); // Crash if missing
2030- if (!(FIXNUM_P (id ) || RB_TYPE_P (id , T_BIGNUM ))) {
2031- rb_p (obj );
2032- rb_bug ("Corrupted object_id" );
2033- }
2034- }
2035- break ;
2036- }
2037- #endif
2038-
20392018 VALUE obj_id = 0 ;
20402019 if (RB_UNLIKELY (id2ref_tbl )) {
20412020 switch (BUILTIN_TYPE (obj )) {
20422021 case T_CLASS :
20432022 case T_MODULE :
20442023 obj_id = RCLASS (obj )-> object_id ;
20452024 break ;
2046- default : {
2025+ case T_IMEMO :
2026+ if (!IMEMO_TYPE_P (obj , imemo_fields )) {
2027+ return ;
2028+ }
2029+ // fallthrough
2030+ case T_OBJECT :
2031+ {
20472032 shape_id_t shape_id = RBASIC_SHAPE_ID (obj );
20482033 if (rb_shape_has_object_id (shape_id )) {
20492034 obj_id = object_id_get (obj , shape_id );
20502035 }
20512036 break ;
20522037 }
2038+ default :
2039+ // For generic_fields, the T_IMEMO/fields is responsible for freeing the id.
2040+ return ;
20532041 }
20542042
20552043 if (RB_UNLIKELY (obj_id )) {
20562044 RUBY_ASSERT (FIXNUM_P (obj_id ) || RB_TYPE_P (obj_id , T_BIGNUM ));
20572045
20582046 if (!st_delete (id2ref_tbl , (st_data_t * )& obj_id , NULL )) {
2059- // If we're currently building the table then it's not a bug
2060- if (id2ref_tbl_built ) {
2047+ // If we're currently building the table then it's not a bug.
2048+ // The the object is a T_IMEMO/fields, then it's possible the actual object
2049+ // has been garbage collected already.
2050+ if (id2ref_tbl_built && !RB_TYPE_P (obj , T_IMEMO )) {
20612051 rb_bug ("Object ID seen, but not in _id2ref table: object_id=%llu object=%s" , NUM2ULL (obj_id ), rb_obj_info (obj ));
20622052 }
20632053 }
@@ -2071,7 +2061,7 @@ rb_gc_obj_free_vm_weak_references(VALUE obj)
20712061 obj_free_object_id (obj );
20722062
20732063 if (rb_obj_exivar_p (obj )) {
2074- rb_free_generic_ivar (( VALUE ) obj );
2064+ rb_free_generic_ivar (obj );
20752065 }
20762066
20772067 switch (BUILTIN_TYPE (obj )) {
@@ -2316,10 +2306,6 @@ rb_obj_memsize_of(VALUE obj)
23162306 return 0 ;
23172307 }
23182308
2319- if (rb_obj_exivar_p (obj )) {
2320- size += rb_generic_ivar_memsize (obj );
2321- }
2322-
23232309 switch (BUILTIN_TYPE (obj )) {
23242310 case T_OBJECT :
23252311 if (rb_shape_obj_too_complex_p (obj )) {
@@ -3935,38 +3921,6 @@ vm_weak_table_foreach_update_weak_value(st_data_t *key, st_data_t *value, st_dat
39353921 return iter_data -> update_callback ((VALUE * )value , iter_data -> data );
39363922}
39373923
3938- static void
3939- free_gen_fields_tbl (VALUE obj , struct gen_fields_tbl * fields_tbl )
3940- {
3941- if (UNLIKELY (rb_shape_obj_too_complex_p (obj ))) {
3942- st_free_table (fields_tbl -> as .complex .table );
3943- }
3944-
3945- xfree (fields_tbl );
3946- }
3947-
3948- static int
3949- vm_weak_table_gen_fields_foreach_too_complex_i (st_data_t _key , st_data_t value , st_data_t data , int error )
3950- {
3951- struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
3952-
3953- GC_ASSERT (!iter_data -> weak_only );
3954-
3955- if (SPECIAL_CONST_P ((VALUE )value )) return ST_CONTINUE ;
3956-
3957- return iter_data -> callback ((VALUE )value , iter_data -> data );
3958- }
3959-
3960- static int
3961- vm_weak_table_gen_fields_foreach_too_complex_replace_i (st_data_t * _key , st_data_t * value , st_data_t data , int existing )
3962- {
3963- struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
3964-
3965- GC_ASSERT (!iter_data -> weak_only );
3966-
3967- return iter_data -> update_callback ((VALUE * )value , iter_data -> data );
3968- }
3969-
39703924struct st_table * rb_generic_fields_tbl_get (void );
39713925
39723926static int
@@ -4003,60 +3957,50 @@ vm_weak_table_gen_fields_foreach(st_data_t key, st_data_t value, st_data_t data)
40033957
40043958 int ret = iter_data -> callback ((VALUE )key , iter_data -> data );
40053959
3960+ VALUE new_value = (VALUE )value ;
3961+ VALUE new_key = (VALUE )key ;
3962+
40063963 switch (ret ) {
40073964 case ST_CONTINUE :
40083965 break ;
40093966
40103967 case ST_DELETE :
4011- free_gen_fields_tbl ((VALUE )key , (struct gen_fields_tbl * )value );
40123968 RBASIC_SET_SHAPE_ID ((VALUE )key , ROOT_SHAPE_ID );
40133969 return ST_DELETE ;
40143970
40153971 case ST_REPLACE : {
4016- VALUE new_key = (VALUE )key ;
40173972 ret = iter_data -> update_callback (& new_key , iter_data -> data );
4018- if (key != new_key ) ret = ST_DELETE ;
4019- DURING_GC_COULD_MALLOC_REGION_START ();
4020- {
4021- st_insert (rb_generic_fields_tbl_get (), (st_data_t )new_key , value );
3973+ if (key != new_key ) {
3974+ ret = ST_DELETE ;
40223975 }
4023- DURING_GC_COULD_MALLOC_REGION_END ();
4024- key = (st_data_t )new_key ;
40253976 break ;
40263977 }
40273978
40283979 default :
4029- return ret ;
3980+ rb_bug ( "vm_weak_table_gen_fields_foreach: return value %d not supported" , ret ) ;
40303981 }
40313982
40323983 if (!iter_data -> weak_only ) {
4033- struct gen_fields_tbl * fields_tbl = (struct gen_fields_tbl * )value ;
3984+ int ivar_ret = iter_data -> callback (new_value , iter_data -> data );
3985+ switch (ivar_ret ) {
3986+ case ST_CONTINUE :
3987+ break ;
40343988
4035- if (rb_shape_obj_too_complex_p ((VALUE )key )) {
4036- st_foreach_with_replace (
4037- fields_tbl -> as .complex .table ,
4038- vm_weak_table_gen_fields_foreach_too_complex_i ,
4039- vm_weak_table_gen_fields_foreach_too_complex_replace_i ,
4040- data
4041- );
3989+ case ST_REPLACE :
3990+ iter_data -> update_callback (& new_value , iter_data -> data );
3991+ break ;
3992+
3993+ default :
3994+ rb_bug ("vm_weak_table_gen_fields_foreach: return value %d not supported" , ivar_ret );
40423995 }
4043- else {
4044- uint32_t fields_count = RSHAPE_LEN (RBASIC_SHAPE_ID ((VALUE )key ));
4045- for (uint32_t i = 0 ; i < fields_count ; i ++ ) {
4046- if (SPECIAL_CONST_P (fields_tbl -> as .shape .fields [i ])) continue ;
3996+ }
40473997
4048- int ivar_ret = iter_data -> callback (fields_tbl -> as .shape .fields [i ], iter_data -> data );
4049- switch (ivar_ret ) {
4050- case ST_CONTINUE :
4051- break ;
4052- case ST_REPLACE :
4053- iter_data -> update_callback (& fields_tbl -> as .shape .fields [i ], iter_data -> data );
4054- break ;
4055- default :
4056- rb_bug ("vm_weak_table_gen_fields_foreach: return value %d not supported" , ivar_ret );
4057- }
4058- }
3998+ if (key != new_key || value != new_value ) {
3999+ DURING_GC_COULD_MALLOC_REGION_START ();
4000+ {
4001+ st_insert (rb_generic_fields_tbl_get (), (st_data_t )new_key , new_value );
40594002 }
4003+ DURING_GC_COULD_MALLOC_REGION_END ();
40604004 }
40614005
40624006 return ret ;
0 commit comments