@@ -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
@@ -427,3 +427,142 @@ rb_managed_id_table_foreach(VALUE table, rb_id_table_foreach_func_t *func, void
427427
428428 rb_id_table_foreach (RTYPEDDATA_GET_DATA (table ), func , data );
429429}
430+
431+ static enum rb_id_table_iterator_result
432+ marked_id_table_mark_i (ID key , VALUE value , void * ref )
433+ {
434+ rb_gc_mark_movable (value );
435+ return ID_TABLE_CONTINUE ;
436+ }
437+
438+ static void
439+ marked_id_table_mark (void * data )
440+ {
441+ struct rb_id_table * tbl = (struct rb_id_table * )data ;
442+ rb_id_table_foreach (tbl , marked_id_table_mark_i , NULL );
443+ }
444+
445+ static enum rb_id_table_iterator_result
446+ marked_id_table_compact_check_i (VALUE value , void * data )
447+ {
448+ if (rb_gc_location (value ) != value ) {
449+ return ID_TABLE_REPLACE ;
450+ }
451+ return ID_TABLE_CONTINUE ;
452+ }
453+
454+ static enum rb_id_table_iterator_result
455+ marked_id_table_compact_replace_i (VALUE * value , void * data , int existing )
456+ {
457+ * value = rb_gc_location (* value );
458+ return ID_TABLE_CONTINUE ;
459+ }
460+
461+ static void
462+ marked_id_table_compact (void * data )
463+ {
464+ struct rb_id_table * tbl = (struct rb_id_table * )data ;
465+ rb_id_table_foreach_values_with_replace (tbl , marked_id_table_compact_check_i , marked_id_table_compact_replace_i , NULL );
466+ }
467+
468+ static const rb_data_type_t marked_id_table_type = {
469+ .wrap_struct_name = "VM/marked_id_table" ,
470+ .function = {
471+ .dmark = marked_id_table_mark ,
472+ .dfree = (RUBY_DATA_FUNC )managed_id_table_free ,
473+ .dsize = managed_id_table_memsize ,
474+ .dcompact = marked_id_table_compact ,
475+ },
476+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE ,
477+ };
478+
479+ VALUE
480+ rb_marked_id_table_new (size_t capa )
481+ {
482+ struct rb_id_table * tbl ;
483+ VALUE obj = TypedData_Make_Struct (0 , struct rb_id_table , & marked_id_table_type , tbl );
484+ rb_id_table_init (tbl , capa );
485+ return obj ;
486+ }
487+
488+ struct marked_id_table_dup_args {
489+ struct rb_id_table * tbl ;
490+ VALUE owner ;
491+ };
492+
493+ static enum rb_id_table_iterator_result
494+ marked_id_table_dup_i (ID id , VALUE val , void * data )
495+ {
496+ struct marked_id_table_dup_args * args = (struct marked_id_table_dup_args * )data ;
497+
498+ rb_id_table_insert (args -> tbl , id , val );
499+ RB_OBJ_WRITTEN (args -> owner , Qundef , val );
500+ return ID_TABLE_CONTINUE ;
501+ }
502+
503+ size_t
504+ rb_marked_id_table_size (VALUE table )
505+ {
506+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
507+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
508+
509+ return rb_id_table_size (RTYPEDDATA_GET_DATA (table ));
510+ }
511+
512+ VALUE
513+ rb_marked_id_table_dup (VALUE old_table )
514+ {
515+ RUBY_ASSERT (RB_TYPE_P (old_table , T_DATA ));
516+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (old_table ), & marked_id_table_type ));
517+
518+ struct rb_id_table * new_tbl ;
519+ VALUE obj = TypedData_Make_Struct (0 , struct rb_id_table , & marked_id_table_type , new_tbl );
520+ struct rb_id_table * old_tbl = RTYPEDDATA_GET_DATA (old_table );
521+
522+ struct marked_id_table_dup_args args = {
523+ .tbl = new_tbl ,
524+ .owner = obj ,
525+ };
526+
527+ rb_id_table_init (new_tbl , old_tbl -> num + 1 );
528+ rb_id_table_foreach (old_tbl , marked_id_table_dup_i , (void * )& args );
529+ return obj ;
530+ }
531+
532+ int
533+ rb_marked_id_table_lookup (VALUE table , ID id , VALUE * valp )
534+ {
535+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
536+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
537+
538+ return rb_id_table_lookup (RTYPEDDATA_GET_DATA (table ), id , valp );
539+ }
540+
541+ int
542+ rb_marked_id_table_insert (VALUE table , ID id , VALUE val )
543+ {
544+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
545+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
546+
547+ int retval = rb_id_table_insert (RTYPEDDATA_GET_DATA (table ), id , val );
548+ RB_OBJ_WRITTEN (table , Qundef , val );
549+ return retval ;
550+ }
551+
552+ int
553+ rb_marked_id_table_delete (VALUE table , ID id )
554+ {
555+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
556+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
557+
558+ return rb_id_table_delete (RTYPEDDATA_GET_DATA (table ), id );
559+ }
560+
561+ void
562+ rb_marked_id_table_foreach (VALUE table , rb_id_table_foreach_func_t * func , void * data )
563+ {
564+ RUBY_ASSERT (RB_TYPE_P (table , T_DATA ));
565+ RUBY_ASSERT (rb_typeddata_inherited_p (RTYPEDDATA_TYPE (table ), & marked_id_table_type ));
566+
567+ rb_id_table_foreach (RTYPEDDATA_GET_DATA (table ), func , data );
568+ }
0 commit comments