@@ -178,10 +178,67 @@ rb_gc_vm_barrier(void)
178178 rb_vm_barrier ();
179179}
180180
181+ #if USE_SHARED_GC
182+ void *
183+ rb_gc_get_ractor_newobj_cache (void )
184+ {
185+ return GET_RACTOR ()-> newobj_cache ;
186+ }
187+
188+ void
189+ rb_gc_initialize_vm_context (struct rb_gc_vm_context * context )
190+ {
191+ rb_native_mutex_initialize (& context -> lock );
192+ context -> ec = GET_EC ();
193+ }
194+
195+ void
196+ rb_gc_worker_thread_set_vm_context (struct rb_gc_vm_context * context )
197+ {
198+ rb_native_mutex_lock (& context -> lock );
199+
200+ GC_ASSERT (rb_current_execution_context (false) == NULL );
201+
202+ #ifdef RB_THREAD_LOCAL_SPECIFIER
203+ # ifdef __APPLE__
204+ rb_current_ec_set (context -> ec );
205+ # else
206+ ruby_current_ec = context -> ec ;
207+ # endif
208+ #else
209+ native_tls_set (ruby_current_ec_key , context -> ec );
210+ #endif
211+ }
212+
213+ void
214+ rb_gc_worker_thread_unset_vm_context (struct rb_gc_vm_context * context )
215+ {
216+ rb_native_mutex_unlock (& context -> lock );
217+
218+ GC_ASSERT (rb_current_execution_context (true) == context -> ec );
219+
220+ #ifdef RB_THREAD_LOCAL_SPECIFIER
221+ # ifdef __APPLE__
222+ rb_current_ec_set (NULL );
223+ # else
224+ ruby_current_ec = NULL ;
225+ # endif
226+ #else
227+ native_tls_set (ruby_current_ec_key , NULL );
228+ #endif
229+ }
230+ #endif
231+
232+ bool
233+ rb_gc_event_hook_required_p (rb_event_flag_t event )
234+ {
235+ return ruby_vm_event_flags & event ;
236+ }
237+
181238void
182239rb_gc_event_hook (VALUE obj , rb_event_flag_t event )
183240{
184- if (LIKELY (!( ruby_vm_event_flags & event ))) return ;
241+ if (LIKELY (!rb_gc_event_hook_required_p ( event ))) return ;
185242
186243 rb_execution_context_t * ec = GET_EC ();
187244 if (!ec -> cfp ) return ;
@@ -195,6 +252,7 @@ rb_gc_get_objspace(void)
195252 return GET_VM ()-> gc .objspace ;
196253}
197254
255+
198256void
199257rb_gc_ractor_newobj_cache_foreach (void (* func )(void * cache , void * data ), void * data )
200258{
@@ -1167,11 +1225,6 @@ rb_gc_obj_free(void *objspace, VALUE obj)
11671225 break ;
11681226 }
11691227
1170- if (FL_TEST (obj , FL_EXIVAR )) {
1171- rb_free_generic_ivar ((VALUE )obj );
1172- FL_UNSET (obj , FL_EXIVAR );
1173- }
1174-
11751228 switch (BUILTIN_TYPE (obj )) {
11761229 case T_OBJECT :
11771230 if (rb_shape_obj_too_complex (obj )) {
@@ -1355,10 +1408,7 @@ rb_gc_obj_free(void *objspace, VALUE obj)
13551408 break ;
13561409
13571410 case T_SYMBOL :
1358- {
1359- rb_gc_free_dsymbol (obj );
1360- RB_DEBUG_COUNTER_INC (obj_symbol );
1361- }
1411+ RB_DEBUG_COUNTER_INC (obj_symbol );
13621412 break ;
13631413
13641414 case T_IMEMO :
@@ -2361,10 +2411,16 @@ rb_mark_locations(void *begin, void *end)
23612411 rb_stack_range_tmp [1 ] = end ;
23622412}
23632413
2414+ void
2415+ rb_gc_save_machine_context (void )
2416+ {
2417+ // no-op
2418+ }
2419+
23642420# if defined(__EMSCRIPTEN__ )
23652421
23662422static void
2367- mark_current_machine_context (rb_execution_context_t * ec )
2423+ mark_current_machine_context (const rb_execution_context_t * ec )
23682424{
23692425 emscripten_scan_stack (rb_mark_locations );
23702426 each_location_ptr (rb_stack_range_tmp [0 ], rb_stack_range_tmp [1 ], gc_mark_maybe_each_location , NULL );
@@ -2375,7 +2431,7 @@ mark_current_machine_context(rb_execution_context_t *ec)
23752431# else // use Asyncify version
23762432
23772433static void
2378- mark_current_machine_context (rb_execution_context_t * ec )
2434+ mark_current_machine_context (const rb_execution_context_t * ec )
23792435{
23802436 VALUE * stack_start , * stack_end ;
23812437 SET_STACK_END ;
@@ -2390,35 +2446,19 @@ mark_current_machine_context(rb_execution_context_t *ec)
23902446
23912447#else // !defined(__wasm__)
23922448
2393- static void
2394- mark_current_machine_context ( rb_execution_context_t * ec )
2449+ void
2450+ rb_gc_save_machine_context ( void )
23952451{
2396- union {
2397- rb_jmp_buf j ;
2398- VALUE v [sizeof (rb_jmp_buf ) / (sizeof (VALUE ))];
2399- } save_regs_gc_mark ;
2400- VALUE * stack_start , * stack_end ;
2401-
2402- FLUSH_REGISTER_WINDOWS ;
2403- memset (& save_regs_gc_mark , 0 , sizeof (save_regs_gc_mark ));
2404- /* This assumes that all registers are saved into the jmp_buf (and stack) */
2405- rb_setjmp (save_regs_gc_mark .j );
2452+ rb_thread_t * thread = GET_THREAD ();
24062453
2407- /* SET_STACK_END must be called in this function because
2408- * the stack frame of this function may contain
2409- * callee save registers and they should be marked. */
2410- SET_STACK_END ;
2411- GET_STACK_BOUNDS (stack_start , stack_end , 1 );
2454+ RB_VM_SAVE_MACHINE_CONTEXT (thread );
2455+ }
24122456
2413- void * data =
2414- #ifdef RUBY_ASAN_ENABLED
2415- ec ;
2416- #else
2417- NULL ;
2418- #endif
24192457
2420- each_location (save_regs_gc_mark .v , numberof (save_regs_gc_mark .v ), gc_mark_machine_stack_location_maybe , data );
2421- each_location_ptr (stack_start , stack_end , gc_mark_machine_stack_location_maybe , data );
2458+ static void
2459+ mark_current_machine_context (const rb_execution_context_t * ec )
2460+ {
2461+ rb_gc_mark_machine_context (ec );
24222462}
24232463#endif
24242464
@@ -2526,9 +2566,6 @@ rb_gc_mark_roots(void *objspace, const char **categoryp)
25262566 rb_vm_mark (vm );
25272567 if (vm -> self ) gc_mark_internal (vm -> self );
25282568
2529- MARK_CHECKPOINT ("machine_context" );
2530- mark_current_machine_context (ec );
2531-
25322569 MARK_CHECKPOINT ("end_proc" );
25332570 rb_mark_end_proc ();
25342571
@@ -2544,7 +2581,11 @@ rb_gc_mark_roots(void *objspace, const char **categoryp)
25442581 }
25452582#endif
25462583
2584+ MARK_CHECKPOINT ("machine_context" );
2585+ mark_current_machine_context (ec );
2586+
25472587 MARK_CHECKPOINT ("finish" );
2588+
25482589#undef MARK_CHECKPOINT
25492590}
25502591
@@ -2832,13 +2873,14 @@ const char *
28322873rb_gc_active_gc_name (void )
28332874{
28342875 const char * gc_name = rb_gc_impl_active_gc_name ();
2876+
28352877 const size_t len = strlen (gc_name );
28362878 if (len > RB_GC_MAX_NAME_LEN ) {
28372879 rb_bug ("GC should have a name no more than %d chars long. Currently: %zu (%s)" ,
28382880 RB_GC_MAX_NAME_LEN , len , gc_name );
28392881 }
2840- return gc_name ;
28412882
2883+ return gc_name ;
28422884}
28432885
28442886// TODO: rearchitect this function to work for a generic GC
@@ -2851,9 +2893,9 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max)
28512893/* GC */
28522894
28532895void *
2854- rb_gc_ractor_cache_alloc (void )
2896+ rb_gc_ractor_cache_alloc (rb_ractor_t * ractor )
28552897{
2856- return rb_gc_impl_ractor_cache_alloc (rb_gc_get_objspace ());
2898+ return rb_gc_impl_ractor_cache_alloc (rb_gc_get_objspace (), ractor );
28572899}
28582900
28592901void
@@ -3246,6 +3288,142 @@ update_superclasses(void *objspace, VALUE obj)
32463288extern rb_symbols_t ruby_global_symbols ;
32473289#define global_symbols ruby_global_symbols
32483290
3291+ #if USE_SHARED_GC
3292+ struct global_vm_table_foreach_data {
3293+ vm_table_foreach_callback_func callback ;
3294+ vm_table_update_callback_func update_callback ;
3295+ void * data ;
3296+ };
3297+
3298+ static int
3299+ vm_weak_table_foreach_key (st_data_t key , st_data_t value , st_data_t data , int error )
3300+ {
3301+ struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
3302+
3303+ return iter_data -> callback ((VALUE )key , iter_data -> data );
3304+ }
3305+
3306+ static int
3307+ vm_weak_table_foreach_update_key (st_data_t * key , st_data_t * value , st_data_t data , int existing )
3308+ {
3309+ struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
3310+
3311+ return iter_data -> update_callback ((VALUE * )key , iter_data -> data );
3312+ }
3313+
3314+ static int
3315+ vm_weak_table_str_sym_foreach (st_data_t key , st_data_t value , st_data_t data , int error )
3316+ {
3317+ struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
3318+
3319+ if (STATIC_SYM_P (value )) {
3320+ return ST_CONTINUE ;
3321+ }
3322+ else {
3323+ return iter_data -> callback ((VALUE )value , iter_data -> data );
3324+ }
3325+ }
3326+
3327+ static int
3328+ vm_weak_table_foreach_update_value (st_data_t * key , st_data_t * value , st_data_t data , int existing )
3329+ {
3330+ struct global_vm_table_foreach_data * iter_data = (struct global_vm_table_foreach_data * )data ;
3331+
3332+ return iter_data -> update_callback ((VALUE * )value , iter_data -> data );
3333+ }
3334+
3335+ static int
3336+ vm_weak_table_gen_ivar_foreach (st_data_t key , st_data_t value , st_data_t data , int error )
3337+ {
3338+ int retval = vm_weak_table_foreach_key (key , value , data , error );
3339+ if (retval == ST_DELETE ) {
3340+ FL_UNSET ((VALUE )key , FL_EXIVAR );
3341+ }
3342+ return retval ;
3343+ }
3344+
3345+ static int
3346+ vm_weak_table_frozen_strings_foreach (st_data_t key , st_data_t value , st_data_t data , int error )
3347+ {
3348+ GC_ASSERT (RB_TYPE_P ((VALUE )key , T_STRING ));
3349+
3350+ int retval = vm_weak_table_foreach_key (key , value , data , error );
3351+ if (retval == ST_DELETE ) {
3352+ FL_UNSET ((VALUE )key , RSTRING_FSTR );
3353+ }
3354+ return retval ;
3355+ }
3356+
3357+ struct st_table * rb_generic_ivtbl_get (void );
3358+
3359+ void
3360+ rb_gc_vm_weak_table_foreach (vm_table_foreach_callback_func callback ,
3361+ vm_table_update_callback_func update_callback ,
3362+ void * data ,
3363+ enum rb_gc_vm_weak_tables table )
3364+ {
3365+ rb_vm_t * vm = GET_VM ();
3366+
3367+ struct global_vm_table_foreach_data foreach_data = {
3368+ .callback = callback ,
3369+ .update_callback = update_callback ,
3370+ .data = data
3371+ };
3372+
3373+ switch (table ) {
3374+ case RB_GC_VM_CI_TABLE : {
3375+ st_foreach_with_replace (
3376+ vm -> ci_table ,
3377+ vm_weak_table_foreach_key ,
3378+ vm_weak_table_foreach_update_key ,
3379+ (st_data_t )& foreach_data
3380+ );
3381+ break ;
3382+ }
3383+ case RB_GC_VM_OVERLOADED_CME_TABLE : {
3384+ st_foreach_with_replace (
3385+ vm -> overloaded_cme_table ,
3386+ vm_weak_table_foreach_key ,
3387+ vm_weak_table_foreach_update_key ,
3388+ (st_data_t )& foreach_data
3389+ );
3390+ break ;
3391+ }
3392+ case RB_GC_VM_GLOBAL_SYMBOLS_TABLE : {
3393+ st_foreach_with_replace (
3394+ global_symbols .str_sym ,
3395+ vm_weak_table_str_sym_foreach ,
3396+ vm_weak_table_foreach_update_value ,
3397+ (st_data_t )& foreach_data
3398+ );
3399+ break ;
3400+ }
3401+ case RB_GC_VM_GENERIC_IV_TABLE : {
3402+ st_table * generic_iv_tbl = rb_generic_ivtbl_get ();
3403+ st_foreach_with_replace (
3404+ generic_iv_tbl ,
3405+ vm_weak_table_gen_ivar_foreach ,
3406+ vm_weak_table_foreach_update_key ,
3407+ (st_data_t )& foreach_data
3408+ );
3409+ break ;
3410+ }
3411+ case RB_GC_VM_FROZEN_STRINGS_TABLE : {
3412+ st_table * frozen_strings = GET_VM ()-> frozen_strings ;
3413+ st_foreach_with_replace (
3414+ frozen_strings ,
3415+ vm_weak_table_frozen_strings_foreach ,
3416+ vm_weak_table_foreach_update_key ,
3417+ (st_data_t )& foreach_data
3418+ );
3419+ break ;
3420+ }
3421+ default :
3422+ rb_bug ("rb_gc_vm_weak_table_foreach: unknown table %d" , table );
3423+ }
3424+ }
3425+ #endif
3426+
32493427void
32503428rb_gc_update_vm_references (void * objspace )
32513429{
@@ -3727,7 +3905,8 @@ rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE,
37273905 };
37283906
37293907 vm -> gc .mark_func_data = & mfd ;
3730- rb_gc_mark_roots (rb_gc_get_objspace (), & data .category );
3908+ rb_gc_save_machine_context ();
3909+ rb_gc_mark_roots (vm -> gc .objspace , & data .category );
37313910 vm -> gc .mark_func_data = prev_mfd ;
37323911}
37333912
@@ -4473,6 +4652,18 @@ rb_obj_info_dump_loc(VALUE obj, const char *file, int line, const char *func)
44734652 fprintf (stderr , "<OBJ_INFO:%s@%s:%d> %s\n" , func , file , line , rb_raw_obj_info (buff , 0x100 , obj ));
44744653}
44754654
4655+ void
4656+ rb_gc_before_fork (void )
4657+ {
4658+ rb_gc_impl_before_fork (rb_gc_get_objspace ());
4659+ }
4660+
4661+ void
4662+ rb_gc_after_fork (rb_pid_t pid )
4663+ {
4664+ rb_gc_impl_after_fork (rb_gc_get_objspace (), pid );
4665+ }
4666+
44764667/*
44774668 * Document-module: ObjectSpace
44784669 *
0 commit comments