@@ -87,8 +87,8 @@ rb_id_table_init(struct rb_id_table *tbl, size_t s_capa)
8787 MEMZERO (tbl , struct rb_id_table , 1 );
8888 if (capa > 0 ) {
8989 capa = round_capa (capa );
90- tbl -> capa = (int )capa ;
9190 tbl -> items = ZALLOC_N (item_t , capa );
91+ tbl -> capa = (int )capa ;
9292 }
9393 return tbl ;
9494}
@@ -341,7 +341,7 @@ managed_id_table_free(void *data)
341341static size_t
342342managed_id_table_memsize (const void * data )
343343{
344- const struct rb_id_table * tbl = (const struct rb_id_table * )data ;
344+ const struct rb_id_table * tbl = (struct rb_id_table * )data ;
345345 return rb_id_table_memsize (tbl ) - sizeof (struct rb_id_table );
346346}
347347
@@ -373,8 +373,8 @@ rb_managed_id_table_new(size_t capa)
373373static enum rb_id_table_iterator_result
374374managed_id_table_dup_i (ID id , VALUE val , void * data )
375375{
376- struct rb_id_table * new_tbl = (struct rb_id_table * )data ;
377- rb_id_table_insert ( new_tbl , id , val );
376+ VALUE new_table = (VALUE )data ;
377+ rb_managed_id_table_insert ( new_table , id , val );
378378 return ID_TABLE_CONTINUE ;
379379}
380380
@@ -384,12 +384,9 @@ rb_managed_id_table_dup(VALUE old_table)
384384 RUBY_ASSERT (RB_TYPE_P (old_table , T_DATA ));
385385 RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (old_table ), & managed_id_table_type ));
386386
387- struct rb_id_table * new_tbl ;
388- VALUE obj = TypedData_Make_Struct (0 , struct rb_id_table , & managed_id_table_type , new_tbl );
389- struct rb_id_table * old_tbl = RTYPEDDATA_GET_DATA (old_table );
390- rb_id_table_init (new_tbl , old_tbl -> num + 1 );
391- rb_id_table_foreach (old_tbl , managed_id_table_dup_i , new_tbl );
392- return obj ;
387+ VALUE new_table = rb_managed_id_table_new (rb_managed_id_table_size (old_table ) + 1 );
388+ rb_managed_id_table_foreach (old_table , managed_id_table_dup_i , (void * )new_table );
389+ return new_table ;
393390}
394391
395392int
@@ -427,3 +424,126 @@ rb_managed_id_table_foreach(VALUE table, rb_id_table_foreach_func_t *func, void
427424
428425 rb_id_table_foreach (RTYPEDDATA_GET_DATA (table ), func , data );
429426}
427+
428+ static enum rb_id_table_iterator_result
429+ marked_id_table_mark_i (ID key , VALUE value , void * ref )
430+ {
431+ rb_gc_mark_movable (value );
432+ return ID_TABLE_CONTINUE ;
433+ }
434+
435+ static void
436+ marked_id_table_mark (void * data )
437+ {
438+ struct rb_id_table * tbl = (struct rb_id_table * )data ;
439+ rb_id_table_foreach (tbl , marked_id_table_mark_i , NULL );
440+ }
441+
442+ static enum rb_id_table_iterator_result
443+ marked_id_table_compact_check_i (VALUE value , void * data )
444+ {
445+ if (rb_gc_location (value ) != value ) {
446+ return ID_TABLE_REPLACE ;
447+ }
448+ return ID_TABLE_CONTINUE ;
449+ }
450+
451+ static enum rb_id_table_iterator_result
452+ marked_id_table_compact_replace_i (VALUE * value , void * data , int existing )
453+ {
454+ * value = rb_gc_location (* value );
455+ return ID_TABLE_CONTINUE ;
456+ }
457+
458+ static void
459+ marked_id_table_compact (void * data )
460+ {
461+ struct rb_id_table * tbl = (struct rb_id_table * )data ;
462+ rb_id_table_foreach_values_with_replace (tbl , marked_id_table_compact_check_i , marked_id_table_compact_replace_i , NULL );
463+ }
464+
465+ static const rb_data_type_t marked_id_table_type = {
466+ .wrap_struct_name = "VM/marked_id_table" ,
467+ .function = {
468+ .dmark = marked_id_table_mark ,
469+ .dfree = (RUBY_DATA_FUNC )managed_id_table_free ,
470+ .dsize = managed_id_table_memsize ,
471+ .dcompact = marked_id_table_compact ,
472+ },
473+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE ,
474+ };
475+
476+ VALUE
477+ rb_marked_id_table_new (size_t capa )
478+ {
479+ struct rb_id_table * tbl ;
480+ VALUE obj = TypedData_Make_Struct (0 , struct rb_id_table , & marked_id_table_type , tbl );
481+ rb_id_table_init (tbl , capa );
482+ return obj ;
483+ }
484+
485+ size_t
486+ rb_marked_id_table_size (VALUE table )
487+ {
488+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
489+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
490+
491+ return rb_id_table_size (RTYPEDDATA_GET_DATA (table ));
492+ }
493+
494+ static enum rb_id_table_iterator_result
495+ marked_id_table_dup_i (ID id , VALUE val , void * data )
496+ {
497+ VALUE new_table = (VALUE )data ;
498+ rb_marked_id_table_insert (new_table , id , val );
499+ return ID_TABLE_CONTINUE ;
500+ }
501+
502+ VALUE
503+ rb_marked_id_table_dup (VALUE old_table )
504+ {
505+ RUBY_ASSERT (RB_TYPE_P (old_table , T_DATA ));
506+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (old_table ), & marked_id_table_type ));
507+
508+ VALUE new_table = rb_marked_id_table_new (rb_marked_id_table_size (old_table ) + 1 );
509+ rb_marked_id_table_foreach (old_table , marked_id_table_dup_i , (void * )new_table );
510+ return new_table ;
511+ }
512+
513+ int
514+ rb_marked_id_table_lookup (VALUE table , ID id , VALUE * valp )
515+ {
516+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
517+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
518+
519+ return rb_id_table_lookup (RTYPEDDATA_GET_DATA (table ), id , valp );
520+ }
521+
522+ int
523+ rb_marked_id_table_insert (VALUE table , ID id , VALUE val )
524+ {
525+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
526+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
527+
528+ int retval = rb_id_table_insert (RTYPEDDATA_GET_DATA (table ), id , val );
529+ RB_OBJ_WRITTEN (table , Qundef , val );
530+ return retval ;
531+ }
532+
533+ int
534+ rb_marked_id_table_delete (VALUE table , ID id )
535+ {
536+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
537+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
538+
539+ return rb_id_table_delete (RTYPEDDATA_GET_DATA (table ), id );
540+ }
541+
542+ void
543+ rb_marked_id_table_foreach (VALUE table , rb_id_table_foreach_func_t * func , void * data )
544+ {
545+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
546+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
547+
548+ rb_id_table_foreach (RTYPEDDATA_GET_DATA (table ), func , data );
549+ }
0 commit comments