Use extconf to build external GC modules

Co-Authored-By: Peter Zhu <peter@peterzhu.ca>
This commit is contained in:
Matt Valentine-House 2024-11-22 12:32:16 +00:00
parent 92585898fb
commit d61933e503
Notes: git 2024-11-25 13:05:41 +00:00
8 changed files with 9523 additions and 14 deletions

View File

@ -97,14 +97,14 @@ jobs:
- run: $SETARCH make prepare-gems
if: ${{ matrix.test_task == 'test-bundled-gems' }}
- run: $SETARCH make
- name: Build shared GC
run: |
echo "RUBY_GC_LIBRARY=default" >> $GITHUB_ENV
make shared-gc SHARED_GC=default
if: ${{ matrix.shared_gc }}
- run: $SETARCH make
- run: |
$SETARCH make golf
case "${{ matrix.configure }}" in

View File

@ -721,7 +721,7 @@ install-prereq: $(CLEAR_INSTALLED_LIST) yes-fake sudo-precheck PHONY
clear-installed-list: PHONY
@> $(INSTALLED_LIST) set MAKE="$(MAKE)"
clean: clean-ext clean-enc clean-golf clean-docs clean-extout clean-local clean-platform clean-spec
clean: clean-ext clean-enc clean-golf clean-docs clean-extout clean-gc clean-local clean-platform clean-spec
clean-local:: clean-runnable
$(Q)$(RM) $(ALLOBJS) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
$(Q)$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) dmyenc.$(OBJEXT) $(ARCHFILE) .*.time
@ -751,11 +751,13 @@ clean-capi: PHONY
clean-platform: PHONY
clean-extout: PHONY
-$(Q)$(RMDIR) $(EXTOUT)/$(arch) $(RUBYCOMMONDIR) $(EXTOUT) 2> $(NULL) || $(NULLCMD)
clean-gc: PHONY
$(Q) $(RMALL) .gc
clean-docs: clean-rdoc clean-html clean-capi
clean-spec: PHONY
clean-rubyspec: clean-spec
distclean: distclean-ext distclean-enc distclean-golf distclean-docs distclean-extout distclean-local distclean-platform distclean-spec
distclean: distclean-ext distclean-enc distclean-golf distclean-docs distclean-extout distclean-gc distclean-local distclean-platform distclean-spec
distclean-local:: clean-local
$(Q)$(RM) $(MKFILES) yasmdata.rb *.inc $(PRELUDES) *.rbinc *.rbbin
$(Q)$(RM) config.cache config.status config.status.lineno
@ -768,6 +770,7 @@ distclean-html: clean-html
distclean-capi: clean-capi
distclean-docs: clean-docs
distclean-extout: clean-extout
distclean-gc: clean-gc
distclean-platform: clean-platform
distclean-spec: clean-spec
distclean-rubyspec: distclean-spec
@ -1948,9 +1951,11 @@ shared-gc: probes.h
echo "You must specify SHARED_GC with the GC to build"; \
exit 1; \
fi
$(ECHO) generating $(shared_gc_dir)librubygc.$(SHARED_GC).$(SOEXT)
$(Q) $(MAKEDIRS) $(shared_gc_dir)
$(Q) $(LDSHARED) -I$(srcdir)/include -I$(srcdir) -I$(arch_hdrdir) $(XDLDFLAGS) $(CFLAGS) $(CPPFLAGS) -DBUILDING_SHARED_GC -fPIC -o $(shared_gc_dir)librubygc.$(SHARED_GC).$(SOEXT) $(srcdir)/gc/$(SHARED_GC).c
$(Q) $(MAKEDIRS) $(shared_gc_dir) .gc/$(arch)/$(SHARED_GC)
$(Q) $(RUNRUBY) -C .gc/$(arch)/$(SHARED_GC) $(CURDIR)/$(srcdir)/gc/$(SHARED_GC)/$(EXTCONF)
$(Q) $(CHDIR) .gc/$(arch)/$(SHARED_GC) && \
$(MAKE) extout=../../../$(EXTOUT) BUILTRUBY=../../../miniruby$(EXEEXT) && \
$(CP) librubygc.$(SHARED_GC).$(DLEXT) $(shared_gc_dir)
help: PHONY
$(MESSAGE_BEGIN) \
@ -7272,7 +7277,7 @@ gc.$(OBJEXT): $(CCAN_DIR)/str/str.h
gc.$(OBJEXT): $(hdrdir)/ruby.h
gc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
gc.$(OBJEXT): $(hdrdir)/ruby/version.h
gc.$(OBJEXT): $(top_srcdir)/gc/default.c
gc.$(OBJEXT): $(top_srcdir)/gc/default/default.c
gc.$(OBJEXT): $(top_srcdir)/gc/gc.h
gc.$(OBJEXT): $(top_srcdir)/gc/gc_impl.h
gc.$(OBJEXT): $(top_srcdir)/internal/array.h

57
gc.c
View File

@ -566,7 +566,7 @@ rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val)
static const char *obj_type_name(VALUE obj);
#define RB_AMALGAMATED_DEFAULT_GC
#include "gc/default.c"
#include "gc/default/default.c"
static int external_gc_loaded = FALSE;
@ -580,7 +580,7 @@ typedef struct gc_function_map {
void *(*objspace_alloc)(void);
void (*objspace_init)(void *objspace_ptr);
void (*objspace_free)(void *objspace_ptr);
void *(*ractor_cache_alloc)(void *objspace_ptr);
void *(*ractor_cache_alloc)(void *objspace_ptr, void *ractor);
void (*ractor_cache_free)(void *objspace_ptr, void *cache);
void (*set_params)(void *objspace_ptr);
void (*init)(void);
@ -635,6 +635,9 @@ typedef struct gc_function_map {
// Object ID
VALUE (*object_id)(void *objspace_ptr, VALUE obj);
VALUE (*object_id_to_ref)(void *objspace_ptr, VALUE object_id);
// Forking
void (*before_fork)(void *objspace_ptr);
void (*after_fork)(void *objspace_ptr, rb_pid_t pid);
// Statistics
void (*set_measure_total_time)(void *objspace_ptr, VALUE flag);
bool (*get_measure_total_time)(void *objspace_ptr);
@ -683,7 +686,7 @@ ruby_external_gc_init(void)
}
}
size_t gc_so_path_size = strlen(SHARED_GC_DIR "librubygc." SOEXT) + strlen(gc_so_file) + 1;
size_t gc_so_path_size = strlen(SHARED_GC_DIR "librubygc." DLEXT) + strlen(gc_so_file) + 1;
gc_so_path = alloca(gc_so_path_size);
{
size_t gc_so_path_idx = 0;
@ -693,7 +696,7 @@ ruby_external_gc_init(void)
GC_SO_PATH_APPEND(SHARED_GC_DIR);
GC_SO_PATH_APPEND("librubygc.");
GC_SO_PATH_APPEND(gc_so_file);
GC_SO_PATH_APPEND(SOEXT);
GC_SO_PATH_APPEND(DLEXT);
GC_ASSERT(gc_so_path_idx == gc_so_path_size - 1);
#undef GC_SO_PATH_APPEND
}
@ -781,6 +784,9 @@ ruby_external_gc_init(void)
// Object ID
load_external_gc_func(object_id);
load_external_gc_func(object_id_to_ref);
// Forking
load_external_gc_func(before_fork);
load_external_gc_func(after_fork);
// Statistics
load_external_gc_func(set_measure_total_time);
load_external_gc_func(get_measure_total_time);
@ -862,6 +868,9 @@ ruby_external_gc_init(void)
// Object ID
# define rb_gc_impl_object_id rb_gc_functions.object_id
# define rb_gc_impl_object_id_to_ref rb_gc_functions.object_id_to_ref
// Forking
# define rb_gc_impl_before_fork rb_gc_functions.before_fork
# define rb_gc_impl_after_fork rb_gc_functions.after_fork
// Statistics
# define rb_gc_impl_set_measure_total_time rb_gc_functions.set_measure_total_time
# define rb_gc_impl_get_measure_total_time rb_gc_functions.get_measure_total_time
@ -915,7 +924,7 @@ newobj_of(rb_ractor_t *cr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v
{
VALUE obj = rb_gc_impl_new_obj(rb_gc_get_objspace(), cr->newobj_cache, klass, flags, v1, v2, v3, wb_protected, size);
if (UNLIKELY(ruby_vm_event_flags & RUBY_INTERNAL_EVENT_NEWOBJ)) {
if (UNLIKELY(rb_gc_event_hook_required_p(RUBY_INTERNAL_EVENT_NEWOBJ))) {
unsigned int lev;
RB_VM_LOCK_ENTER_CR_LEV(cr, &lev);
{
@ -1104,6 +1113,44 @@ rb_data_free(void *objspace, VALUE obj)
return true;
}
void
rb_gc_obj_free_vm_weak_references(VALUE obj)
{
if (FL_TEST(obj, FL_EXIVAR)) {
rb_free_generic_ivar((VALUE)obj);
FL_UNSET(obj, FL_EXIVAR);
}
switch (BUILTIN_TYPE(obj)) {
case T_STRING:
if (FL_TEST(obj, RSTRING_FSTR)) {
st_data_t fstr = (st_data_t)obj;
st_delete(rb_vm_fstring_table(), &fstr, NULL);
RB_DEBUG_COUNTER_INC(obj_str_fstr);
FL_UNSET(obj, RSTRING_FSTR);
}
break;
case T_SYMBOL:
rb_gc_free_dsymbol(obj);
break;
case T_IMEMO:
switch (imemo_type(obj)) {
case imemo_callinfo:
rb_vm_ci_free((const struct rb_callinfo *)obj);
break;
case imemo_ment:
rb_free_method_entry_vm_weak_references((const rb_method_entry_t *)obj);
break;
default:
break;
}
break;
default:
break;
}
}
bool
rb_gc_obj_free(void *objspace, VALUE obj)
{

9438
gc/default/default.c Normal file

File diff suppressed because it is too large Load Diff

5
gc/default/extconf.rb Normal file
View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
require_relative "../extconf_base"
create_gc_makefile("default")

13
gc/extconf_base.rb Normal file
View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
require "mkmf"
srcdir = File.join(__dir__, "..")
$CFLAGS << " -I#{srcdir}"
$CFLAGS << " -DBUILDING_SHARED_GC"
$CFLAGS << " -fPIC"
def create_gc_makefile(name)
create_makefile("librubygc.#{name}")
end

View File

@ -29,6 +29,7 @@ size_t rb_size_mul_or_raise(size_t x, size_t y, VALUE exc);
void rb_gc_run_obj_finalizer(VALUE objid, long count, VALUE (*callback)(long i, void *data), void *data);
void rb_gc_set_pending_interrupt(void);
void rb_gc_unset_pending_interrupt(void);
void rb_gc_obj_free_vm_weak_references(VALUE obj);
bool rb_gc_obj_free(void *objspace, VALUE obj);
void rb_gc_mark_roots(void *objspace, const char **categoryp);
void rb_gc_ractor_newobj_cache_foreach(void (*func)(void *cache, void *data), void *data);

View File

@ -28,7 +28,7 @@
GC_IMPL_FN void *rb_gc_impl_objspace_alloc(void);
GC_IMPL_FN void rb_gc_impl_objspace_init(void *objspace_ptr);
GC_IMPL_FN void rb_gc_impl_objspace_free(void *objspace_ptr);
GC_IMPL_FN void *rb_gc_impl_ractor_cache_alloc(void *objspace_ptr);
GC_IMPL_FN void *rb_gc_impl_ractor_cache_alloc(void *objspace_ptr, void *ractor);
GC_IMPL_FN void rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache);
GC_IMPL_FN void rb_gc_impl_set_params(void *objspace_ptr);
GC_IMPL_FN void rb_gc_impl_init(void);