Skip to content

Commit 551be82

Browse files
Place all non-default GC API behind USE_SHARED_GC
So that it doesn't get included in the generated binaries for builds that don't support loading shared GC modules Co-Authored-By: Peter Zhu <[email protected]>
1 parent d61933e commit 551be82

File tree

12 files changed

+294
-9491
lines changed

12 files changed

+294
-9491
lines changed

gc.c

Lines changed: 235 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
181238
void
182239
rb_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+
198256
void
199257
rb_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

23662422
static 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

23772433
static 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 *
28322873
rb_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

28532895
void *
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

28592901
void
@@ -3246,6 +3288,142 @@ update_superclasses(void *objspace, VALUE obj)
32463288
extern 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+
32493427
void
32503428
rb_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

Comments
 (0)