Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/cygwin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ jobs:
./configure --disable-install-doc
shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}

- name: Extract bundled gems
run: |
make ruby -j5
make extract-gems
shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}
# This fails with: tool/outdate-bundled-gems.rb:3:in 'Kernel#require': cannot load such file -- rubygems (LoadError)
#- name: Extract bundled gems
# run: |
# make ruby -j5
# make extract-gems
# shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}

- name: make all
timeout-minutes: 30
Expand Down
78 changes: 65 additions & 13 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,6 @@ typedef struct gc_function_map {
void (*config_set)(void *objspace_ptr, VALUE hash);
void (*stress_set)(void *objspace_ptr, VALUE flag);
VALUE (*stress_get)(void *objspace_ptr);
bool (*checking_shareable)(void *objspace_ptr);
// Object allocation
VALUE (*new_obj)(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size);
size_t (*obj_slot_size)(VALUE obj);
Expand Down Expand Up @@ -796,7 +795,6 @@ ruby_modular_gc_init(void)
load_modular_gc_func(config_get);
load_modular_gc_func(stress_set);
load_modular_gc_func(stress_get);
load_modular_gc_func(checking_shareable);
// Object allocation
load_modular_gc_func(new_obj);
load_modular_gc_func(obj_slot_size);
Expand Down Expand Up @@ -877,7 +875,6 @@ ruby_modular_gc_init(void)
# define rb_gc_impl_config_set rb_gc_functions.config_set
# define rb_gc_impl_stress_set rb_gc_functions.stress_set
# define rb_gc_impl_stress_get rb_gc_functions.stress_get
# define rb_gc_impl_checking_shareable rb_gc_functions.checking_shareable
// Object allocation
# define rb_gc_impl_new_obj rb_gc_functions.new_obj
# define rb_gc_impl_obj_slot_size rb_gc_functions.obj_slot_size
Expand Down Expand Up @@ -2808,19 +2805,12 @@ mark_m_tbl(void *objspace, struct rb_id_table *tbl)
}
}

bool
rb_gc_checking_shareable(void)
{
return rb_gc_impl_checking_shareable(rb_gc_get_objspace());
}


static enum rb_id_table_iterator_result
mark_const_entry_i(VALUE value, void *objspace)
{
const rb_const_entry_t *ce = (const rb_const_entry_t *)value;

if (!rb_gc_impl_checking_shareable(objspace)) {
if (!rb_gc_checking_shareable()) {
gc_mark_internal(ce->value);
gc_mark_internal(ce->file); // TODO: ce->file should be shareable?
}
Expand Down Expand Up @@ -3085,7 +3075,7 @@ gc_mark_classext_module(rb_classext_t *ext, bool prime, VALUE box_value, void *a
}
mark_m_tbl(objspace, RCLASSEXT_M_TBL(ext));

if (!rb_gc_impl_checking_shareable(objspace)) {
if (!rb_gc_checking_shareable()) {
// unshareable
gc_mark_internal(RCLASSEXT_FIELDS_OBJ(ext));
}
Expand Down Expand Up @@ -3156,7 +3146,7 @@ rb_gc_mark_children(void *objspace, VALUE obj)
switch (BUILTIN_TYPE(obj)) {
case T_CLASS:
if (FL_TEST_RAW(obj, FL_SINGLETON) &&
!rb_gc_impl_checking_shareable(objspace)) {
!rb_gc_checking_shareable()) {
gc_mark_internal(RCLASS_ATTACHED_OBJECT(obj));
}
// Continue to the shared T_CLASS/T_MODULE
Expand Down Expand Up @@ -5441,6 +5431,68 @@ rb_gc_rp(VALUE obj)
rp(obj);
}

struct check_shareable_data {
VALUE parent;
long err_count;
};

static void
check_shareable_i(const VALUE child, void *ptr)
{
struct check_shareable_data *data = (struct check_shareable_data *)ptr;

if (!rb_gc_obj_shareable_p(child)) {
fprintf(stderr, "(a) ");
rb_gc_rp(data->parent);
fprintf(stderr, "(b) ");
rb_gc_rp(child);
fprintf(stderr, "check_shareable_i: shareable (a) -> unshareable (b)\n");

data->err_count++;
rb_bug("!! violate shareable constraint !!");
}
}

static bool gc_checking_shareable = false;

static void
gc_verify_shareable(void *objspace, VALUE obj, void *data)
{
// while gc_checking_shareable is true,
// other Ractors should not run the GC, until the flag is not local.
// TODO: remove VM locking if the flag is Ractor local

unsigned int lev = RB_GC_VM_LOCK();
{
gc_checking_shareable = true;
rb_objspace_reachable_objects_from(obj, check_shareable_i, (void *)data);
gc_checking_shareable = false;
}
RB_GC_VM_UNLOCK(lev);
}

// TODO: only one level (non-recursive)
void
rb_gc_verify_shareable(VALUE obj)
{
rb_objspace_t *objspace = rb_gc_get_objspace();
struct check_shareable_data data = {
.parent = obj,
.err_count = 0,
};
gc_verify_shareable(objspace, obj, &data);

if (data.err_count > 0) {
rb_bug("rb_gc_verify_shareable");
}
}

bool
rb_gc_checking_shareable(void)
{
return gc_checking_shareable;
}

/*
* Document-module: ObjectSpace
*
Expand Down
61 changes: 1 addition & 60 deletions gc/default/default.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,6 @@ typedef struct rb_objspace {
unsigned int during_minor_gc : 1;
unsigned int during_incremental_marking : 1;
unsigned int measure_gc : 1;
unsigned int check_shareable : 1;
} flags;

rb_event_flag_t hook_events;
Expand Down Expand Up @@ -1459,13 +1458,6 @@ RVALUE_WHITE_P(rb_objspace_t *objspace, VALUE obj)
return !RVALUE_MARKED(objspace, obj);
}

bool
rb_gc_impl_checking_shareable(void *objspace_ptr)
{
rb_objspace_t *objspace = objspace_ptr;
return objspace->flags.check_shareable;
}

bool
rb_gc_impl_gc_enabled_p(void *objspace_ptr)
{
Expand Down Expand Up @@ -4980,55 +4972,6 @@ check_children_i(const VALUE child, void *ptr)
}
}

static void
check_shareable_i(const VALUE child, void *ptr)
{
struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr;

if (!rb_gc_obj_shareable_p(child)) {
fprintf(stderr, "(a) ");
rb_gc_rp(data->parent);
fprintf(stderr, "(b) ");
rb_gc_rp(child);
fprintf(stderr, "check_shareable_i: shareable (a) -> unshareable (b)\n");

data->err_count++;
rb_bug("!! violate shareable constraint !!");
}
}

static void
gc_verify_shareable(rb_objspace_t *objspace, VALUE obj, void *data)
{
// while objspace->flags.check_shareable is true,
// other Ractors should not run the GC, until the flag is not local.
// TODO: remove VM locking if the flag is Ractor local

unsigned int lev = RB_GC_VM_LOCK();
{
objspace->flags.check_shareable = true;
rb_objspace_reachable_objects_from(obj, check_shareable_i, (void *)data);
objspace->flags.check_shareable = false;
}
RB_GC_VM_UNLOCK(lev);
}

// TODO: only one level (non-recursive)
void
rb_gc_verify_shareable(VALUE obj)
{
rb_objspace_t *objspace = rb_gc_get_objspace();
struct verify_internal_consistency_struct data = {
.parent = obj,
.err_count = 0,
};
gc_verify_shareable(objspace, obj, &data);

if (data.err_count > 0) {
rb_bug("rb_gc_verify_shareable");
}
}

static int
verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
struct verify_internal_consistency_struct *data)
Expand Down Expand Up @@ -5061,7 +5004,7 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
}

if (!is_marking(objspace) && rb_gc_obj_shareable_p(obj)) {
gc_verify_shareable(objspace, obj, data);
rb_gc_verify_shareable(obj);
}

if (is_incremental_marking(objspace)) {
Expand Down Expand Up @@ -6716,7 +6659,6 @@ gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_
gc_enter_count(event);
if (RB_UNLIKELY(during_gc != 0)) rb_bug("during_gc != 0");
if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace);
GC_ASSERT(!objspace->flags.check_shareable);

during_gc = TRUE;
RUBY_DEBUG_LOG("%s (%s)",gc_enter_event_cstr(event), gc_current_status(objspace));
Expand All @@ -6730,7 +6672,6 @@ static inline void
gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev)
{
GC_ASSERT(during_gc != 0);
GC_ASSERT(!objspace->flags.check_shareable);

rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_EXIT);

Expand Down
1 change: 1 addition & 0 deletions gc/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const char *rb_obj_info(VALUE obj);
size_t rb_obj_memsize_of(VALUE obj);
bool ruby_free_at_exit_p(void);
void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data);
void rb_gc_verify_shareable(VALUE);

MODULAR_GC_FN unsigned int rb_gc_vm_lock(const char *file, int line);
MODULAR_GC_FN void rb_gc_vm_unlock(unsigned int lev, const char *file, int line);
Expand Down
1 change: 0 additions & 1 deletion gc/gc_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ GC_IMPL_FN void rb_gc_impl_stress_set(void *objspace_ptr, VALUE flag);
GC_IMPL_FN VALUE rb_gc_impl_stress_get(void *objspace_ptr);
GC_IMPL_FN VALUE rb_gc_impl_config_get(void *objspace_ptr);
GC_IMPL_FN void rb_gc_impl_config_set(void *objspace_ptr, VALUE hash);
GC_IMPL_FN bool rb_gc_impl_checking_shareable(void *objspace_ptr);
// Object allocation
GC_IMPL_FN VALUE rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size);
GC_IMPL_FN size_t rb_gc_impl_obj_slot_size(VALUE obj);
Expand Down
6 changes: 0 additions & 6 deletions gc/mmtk/mmtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1260,12 +1260,6 @@ rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj)
rb_gc_impl_copy_finalizer(objspace_ptr, dest, obj);
}

bool
rb_gc_impl_checking_shareable(void *ptr)
{
return false;
}

// GC Identification

const char *
Expand Down