From 76f64d415ab056d5e93026b6452dd068d65cef34 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 13 Mar 2026 08:27:58 +0300 Subject: [PATCH 1/3] Support optional use of bundled bdwgc instead of libgcroots To use bdwgc, pass `--with_libgcroots=bundled-bdwgc` to configure. --- Makefile.am | 3 + autogen.sh | 4 +- ci/release.sh | 3 + configure.ac | 20 ++++++- src/gcroots/gcroots.c | 132 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 158 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index e6c64aa6..38a5c8b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,9 @@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = doc m4 tools +if USE_BDWGC_BUNDLED +SUBDIRS += bdwgc +endif if USE_LIBGCROOTS_BUNDLED SUBDIRS += libgcroots endif diff --git a/autogen.sh b/autogen.sh index 1df89add..d3755cbe 100755 --- a/autogen.sh +++ b/autogen.sh @@ -3,5 +3,7 @@ set -eu ${AUTORECONF:-autoreconf} --force --install "$@" -cd libgcroots +cd bdwgc +./autogen.sh +cd ../libgcroots ./autogen.sh "$@" diff --git a/ci/release.sh b/ci/release.sh index 326a4bcf..2f5ff8eb 100755 --- a/ci/release.sh +++ b/ci/release.sh @@ -7,6 +7,9 @@ set -x rm -rf ~/source cp -a /source ~/source pushd ~/source +pushd bdwgc +./autogen.sh +popd pushd libgcroots ./autogen.sh popd diff --git a/configure.ac b/configure.ac index 4029c575..dd477d52 100644 --- a/configure.ac +++ b/configure.ac @@ -299,6 +299,17 @@ case "${with_libgcroots:=no}" in GCROOTS_CFLAGS='-I$(sscm_abs_top_srcdir)/src/gcroots' use_libgcroots="tiny substitution in src/gcroots" ;; + bundled-bdwgc) + # use src/gcroots/gcroots.[hc] but redirecting to bundled bdwgc + with_libgcroots=tiny_subst_bdwgc + GCROOTS_CFLAGS='-I$(sscm_abs_top_srcdir)/src/gcroots -I$(sscm_abs_top_srcdir)/bdwgc/include' + AC_DEFINE(SCM_WITH_BDWGC, 1, [Define to 1 to use bdwgc library.]) + use_libgcroots="based on bundled bdwgc" + + ac_configure_args="$ac_configure_args --disable-threads" + AC_CONFIG_SUBDIRS([bdwgc]) + GCROOTS_LIBS='$(sscm_abs_top_builddir)/bdwgc/libgc.la' + ;; *) AC_MSG_ERROR([invalid argument for --with-libgcroots.]) ;; @@ -307,10 +318,15 @@ esac AC_SUBST(GCROOTS_REQ) AC_SUBST(GCROOTS_LIBS) AC_SUBST(GCROOTS_CFLAGS) -AM_CONDITIONAL(USE_LIBGCROOTS, [test "x$with_libgcroots" != xtiny_subst]) +AM_CONDITIONAL(USE_BDWGC_BUNDLED, + [test "x$with_libgcroots" = xtiny_subst_bdwgc]) +AM_CONDITIONAL(USE_LIBGCROOTS, + [test "x$with_libgcroots" != xtiny_subst \ + -a "x$with_libgcroots" != xtiny_subst_bdwgc]) AM_CONDITIONAL(USE_LIBGCROOTS_BUNDLED, [test "x$with_libgcroots" = xno]) AM_CONDITIONAL(USE_LIBGCROOTS_TINY_SUBST, - [test "x$with_libgcroots" = xtiny_subst]) + [test "x$with_libgcroots" = xtiny_subst \ + -o "x$with_libgcroots" = xtiny_subst_bdwgc]) ######################################## diff --git a/src/gcroots/gcroots.c b/src/gcroots/gcroots.c index 4ad3e0c1..16c72b89 100644 --- a/src/gcroots/gcroots.c +++ b/src/gcroots/gcroots.c @@ -35,7 +35,11 @@ #include -#if HAVE_GETCONTEXT +#if SCM_WITH_BDWGC +#include +#include "gc/gc.h" +#include "gc/gc_mark.h" +#elif HAVE_GETCONTEXT #include #else #include @@ -52,14 +56,35 @@ File Local Type Definitions =======================================*/ struct _GCROOTS_context { +#if SCM_WITH_BDWGC + struct GC_stack_base sb; +#else void *stack_base; +#endif GCROOTS_mark_proc mark; +#if SCM_WITH_BDWGC + scm_bool is_protected; +#else scm_bool scan_entire_system_stack; +#endif }; +#if SCM_WITH_BDWGC +struct ready_stack_data_s { + GCROOTS_context *ctx; + GCROOTS_user_proc proc; + void *arg; +}; + +struct find_obj_data_s { + void *findee; +}; +#endif + /*======================================= Variable Definitions =======================================*/ +#if !SCM_WITH_BDWGC SCM_GLOBAL_VARS_BEGIN(static_gcroots); #define static static void *l_findee; @@ -69,12 +94,22 @@ SCM_GLOBAL_VARS_END(static_gcroots); #define l_findee SCM_GLOBAL_VAR(static_gcroots, l_findee) #define l_found SCM_GLOBAL_VAR(static_gcroots, l_found) SCM_DEFINE_STATIC_VARS(static_gcroots); +#endif /*======================================= File Local Function Declarations =======================================*/ +#if SCM_WITH_BDWGC +static void *GC_CALLBACK ready_stack_wrapper(struct GC_stack_base *sb, + void *cd); +static void GC_CALLBACK mark_internal(void **start, void **end, void *cd, + unsigned hint); +static void GC_CALLBACK find_obj(void **start, void **end, void *cd, + unsigned hint); +#else static void mark_internal(GCROOTS_context *ctx); static void find_obj(void *start, void *end, int is_certain, int is_aligned); +#endif /*======================================= Function Definitions @@ -90,13 +125,20 @@ GCROOTS_init(GCROOTS_context_alloc_proc allocator, GCROOTS_mark_proc marker, /* scan_entire_system_stack is not supported by this implementation */ SCM_ASSERT(!scan_entire_system_stack); +#if !SCM_WITH_BDWGC SCM_GLOBAL_VARS_INIT(static_gcroots); +#endif ctx = (*allocator)(sizeof(GCROOTS_context)); if (ctx) { ctx->mark = marker; +#if SCM_WITH_BDWGC + (void)scan_entire_system_stack; + ctx->is_protected = scm_false; +#else ctx->scan_entire_system_stack = scan_entire_system_stack; ctx->stack_base = NULL; +#endif } return ctx; @@ -115,12 +157,26 @@ GCROOTS_call_with_gc_ready_stack(GCROOTS_context *ctx, GCROOTS_user_proc proc, void *arg) { void *ret; +#if !SCM_WITH_BDWGC void *stack_top; /* approx */ volatile GCROOTS_user_proc anti_inline_proc; +#endif assert(ctx); assert(proc); +#if SCM_WITH_BDWGC + if (ctx->is_protected) { + ret = proc(arg); /* probably inlined */ + } else { + struct ready_stack_data_s data; + + data.ctx = ctx; + data.proc = proc; + data.arg = arg; + ret = GC_call_with_stack_base(ready_stack_wrapper, &data); + } +#else if (!ctx->stack_base) ctx->stack_base = &stack_top; @@ -129,22 +185,46 @@ GCROOTS_call_with_gc_ready_stack(GCROOTS_context *ctx, if (ctx->stack_base == &stack_top) ctx->stack_base = NULL; +#endif + + return ret; +} +#if SCM_WITH_BDWGC +static void *GC_CALLBACK +ready_stack_wrapper(struct GC_stack_base *sb, void *cd) +{ + void *ret; + struct ready_stack_data_s *pdata = (struct ready_stack_data_s *)cd; + GCROOTS_context *ctx = pdata->ctx; + + memcpy(&ctx->sb, sb, sizeof(*sb)); + ctx->is_protected = scm_true; + ret = (*pdata->proc)(pdata->arg); + ctx->is_protected = scm_false; return ret; } +#endif SCM_EXPORT void GCROOTS_mark(GCROOTS_context *ctx) { +#if !SCM_WITH_BDWGC #if HAVE_GETCONTEXT ucontext_t uctx; #else jmp_buf env; #endif void (*volatile anti_inline_mark_internal)(GCROOTS_context *); +#endif assert(ctx); +#if SCM_WITH_BDWGC + if (ctx->is_protected) { + GC_custom_push_regs_and_stack(mark_internal, ctx, &ctx->sb, NULL); + } +#else if (ctx->stack_base) { #if HAVE_GETCONTEXT getcontext(&uctx); @@ -154,8 +234,19 @@ GCROOTS_mark(GCROOTS_context *ctx) anti_inline_mark_internal = mark_internal; (*anti_inline_mark_internal)(ctx); } +#endif } +#if SCM_WITH_BDWGC +static void GC_CALLBACK +mark_internal(void **start, void **end, void *cd, unsigned hint) +{ + GCROOTS_context *ctx = (GCROOTS_context *)cd; + + (void)hint; + (*ctx->mark)(start, end, scm_false, scm_false); +} +#else static void mark_internal(GCROOTS_context *ctx) { @@ -163,25 +254,41 @@ mark_internal(GCROOTS_context *ctx) (*ctx->mark)(ctx->stack_base, &stack_top, scm_false, scm_false); } +#endif int GCROOTS_is_protected_context(GCROOTS_context *ctx) { assert(ctx); +#if SCM_WITH_BDWGC + return ctx->is_protected; +#else return (ctx->stack_base) ? scm_true : scm_false; +#endif } int GCROOTS_is_protected(GCROOTS_context *ctx, void *obj) { +#if SCM_WITH_BDWGC + struct find_obj_data_s data; +#else GCROOTS_context tmp_ctx; +#endif assert(ctx); + if (obj == NULL) /* not expected actually */ + return scm_true; if (!GCROOTS_is_protected_context(ctx)) return scm_false; +#if SCM_WITH_BDWGC + data.findee = obj; + GC_custom_push_regs_and_stack(find_obj, &data, &ctx->sb, NULL); + return data.findee == NULL; +#else tmp_ctx = *ctx; tmp_ctx.mark = find_obj; /* not actually a mark function */ l_findee = obj; @@ -189,8 +296,30 @@ GCROOTS_is_protected(GCROOTS_context *ctx, void *obj) GCROOTS_mark(&tmp_ctx); return l_found; +#endif } +#if SCM_WITH_BDWGC +static void GC_CALLBACK +find_obj(void **start, void **end, void *cd, unsigned hint) +{ + struct find_obj_data_s *pdata = (struct find_obj_data_s *)cd; + char *p = (char *)start; + char *lim = (char *)(end - 1); + void *findee = pdata->findee; + + (void)hint; + if (findee == NULL) + return; /* already found */ + + for (; p <= lim; p += ALIGNOF_VOID_P) { + if (*(void **)p == findee) { + pdata->findee = NULL; /* found */ + break; + } + } +} +#else static void find_obj(void *start, void *end, int is_certain, int is_aligned) { @@ -210,3 +339,4 @@ find_obj(void *start, void *end, int is_certain, int is_aligned) && SIZEOF_VOID_P != ALIGNOF_VOID_P && offset % SIZEOF_VOID_P); } +#endif From ef025020aa79c6519243c941700d331e2cb5683b Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 13 Mar 2026 19:47:33 +0300 Subject: [PATCH 2/3] Add bdwgc as a git submodule --- .gitmodules | 3 +++ bdwgc | 1 + 2 files changed, 4 insertions(+) create mode 160000 bdwgc diff --git a/.gitmodules b/.gitmodules index 20dcfa85..1b1aa895 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "libgcroots"] path = libgcroots url = https://github.com/uim/libgcroots.git +[submodule "bdwgc"] + path = bdwgc + url = https://github.com/bdwgc/bdwgc.git diff --git a/bdwgc b/bdwgc new file mode 160000 index 00000000..b93c6089 --- /dev/null +++ b/bdwgc @@ -0,0 +1 @@ +Subproject commit b93c608953e130aa31e750f653518aa1de930518 From 1dab17a01942e36b9c181ab9553dd2dca3abe45d Mon Sep 17 00:00:00 2001 From: Sutou Kouhei Date: Thu, 26 Mar 2026 16:07:41 +0900 Subject: [PATCH 3/3] Use system BDWGC 8.3.0 or later if possible If BDWGC 8.3.0 or later exists, we use it directly. --- .github/workflows/linux.yml | 39 ++++++++- .gitmodules | 3 - Makefile.am | 3 - autogen.sh | 4 +- bdwgc | 1 - ci/release.sh | 3 - configure.ac | 46 +++++------ sigscheme.pc.in | 2 +- src/Makefile.am | 10 +-- src/gcroots/gcroots.c | 132 +------------------------------ src/sigscheme.h | 5 -- src/storage-gc.c | 153 +++++++++++++++++++++++++++++++++++- 12 files changed, 214 insertions(+), 187 deletions(-) delete mode 160000 bdwgc diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 27f91f11..8531ce75 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -11,8 +11,15 @@ concurrency: group: ${{ github.head_ref || github.sha }}-${{ github.workflow }} cancel-in-progress: true jobs: - setup: - name: Setup + libgcroots: + name: libgcroots + strategy: + fail-fast: false + matrix: + libgcroots: + - no + - installed + - tiny-subst runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -25,9 +32,35 @@ jobs: - name: Generate configure run: | ./autogen.sh + - name: "BDWGC: Checkout" + if: matrix.libgcroots == 'installed' + uses: actions/checkout@v6 + with: + path: bdwgc + repository: bdwgc/bdwgc + - name: "BDWGC: Configure" + if: matrix.libgcroots == 'installed' + run: | + cmake \ + -S bdwgc \ + -B bdwgc.build \ + -G Ninja \ + -DCMAKE_INSTALL_PREFIX=/usr + - name: "BDWGC: Build" + if: matrix.libgcroots == 'installed' + run: | + cmake --build bdwgc.build + - name: "BDWGC: Install" + if: matrix.libgcroots == 'installed' + run: | + sudo cmake --install bdwgc.build - name: Configure run: | - ./configure --enable-maintainer-mode + ./configure \ + --enable-conf=uim \ + --enable-maintainer-mode \ + --prefix=/usr \ + --with-libgcroots=${{ matrix.libgcroots }} - name: Build run: | make -j$(nproc) diff --git a/.gitmodules b/.gitmodules index 1b1aa895..20dcfa85 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "libgcroots"] path = libgcroots url = https://github.com/uim/libgcroots.git -[submodule "bdwgc"] - path = bdwgc - url = https://github.com/bdwgc/bdwgc.git diff --git a/Makefile.am b/Makefile.am index 38a5c8b8..e6c64aa6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = doc m4 tools -if USE_BDWGC_BUNDLED -SUBDIRS += bdwgc -endif if USE_LIBGCROOTS_BUNDLED SUBDIRS += libgcroots endif diff --git a/autogen.sh b/autogen.sh index d3755cbe..1df89add 100755 --- a/autogen.sh +++ b/autogen.sh @@ -3,7 +3,5 @@ set -eu ${AUTORECONF:-autoreconf} --force --install "$@" -cd bdwgc -./autogen.sh -cd ../libgcroots +cd libgcroots ./autogen.sh "$@" diff --git a/bdwgc b/bdwgc deleted file mode 160000 index b93c6089..00000000 --- a/bdwgc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b93c608953e130aa31e750f653518aa1de930518 diff --git a/ci/release.sh b/ci/release.sh index 2f5ff8eb..326a4bcf 100755 --- a/ci/release.sh +++ b/ci/release.sh @@ -7,9 +7,6 @@ set -x rm -rf ~/source cp -a /source ~/source pushd ~/source -pushd bdwgc -./autogen.sh -popd pushd libgcroots ./autogen.sh popd diff --git a/configure.ac b/configure.ac index dd477d52..cc586592 100644 --- a/configure.ac +++ b/configure.ac @@ -267,10 +267,10 @@ AM_CONDITIONAL(WITH_MASTER_PKG, [test "x$with_master_pkg" != xno]) AC_ARG_WITH(libgcroots, AS_HELP_STRING([--with-libgcroots@<:@=WHICH@:>@], - [use alternative libgcroots instead of - package-bundled one. - WHICH=(installed|tiny-subst) - @<:@default=installed@:>@])) + [use system BDWGC or alternative libgcroots + instead of package-bundled libgcroots. + WHICH=(no|installed|tiny-subst) + @<:@default=no@:>@])) case "${with_libgcroots:=no}" in no) @@ -287,11 +287,16 @@ case "${with_libgcroots:=no}" in GCROOTS_REQ=gcroots ;; yes|installed) - PKG_CHECK_MODULES(GCROOTS, [gcroots >= 0.2.3], - [], - [AC_MSG_ERROR([installed libgcroots is not found.])]) - use_libgcroots="installed one" - GCROOTS_REQ=gcroots + PKG_CHECK_MODULES( + BDWGC, [bdw-gc >= 8.3.0], + [BDWGC_REQ=bdw-gc + AC_DEFINE(SCM_WITH_BDWGC, 1, [Define to 1 to use BDWGC.]) + use_libgcroots="installed BDWGC"], + [PKG_CHECK_MODULES( + GCROOTS, [gcroots >= 0.2.3], + [GCROOTS_REQ=gcroots + use_libgcroots="installed one"], + [AC_MSG_ERROR([neither BDWGC nor libgcroots was found.])])]) ;; tiny-subst) # use src/gcroots/gcroots.[hc] @@ -299,34 +304,21 @@ case "${with_libgcroots:=no}" in GCROOTS_CFLAGS='-I$(sscm_abs_top_srcdir)/src/gcroots' use_libgcroots="tiny substitution in src/gcroots" ;; - bundled-bdwgc) - # use src/gcroots/gcroots.[hc] but redirecting to bundled bdwgc - with_libgcroots=tiny_subst_bdwgc - GCROOTS_CFLAGS='-I$(sscm_abs_top_srcdir)/src/gcroots -I$(sscm_abs_top_srcdir)/bdwgc/include' - AC_DEFINE(SCM_WITH_BDWGC, 1, [Define to 1 to use bdwgc library.]) - use_libgcroots="based on bundled bdwgc" - - ac_configure_args="$ac_configure_args --disable-threads" - AC_CONFIG_SUBDIRS([bdwgc]) - GCROOTS_LIBS='$(sscm_abs_top_builddir)/bdwgc/libgc.la' - ;; *) AC_MSG_ERROR([invalid argument for --with-libgcroots.]) ;; esac +AC_SUBST(BDWGC_REQ) +AC_SUBST(BDWGC_LIBS) +AC_SUBST(BDWGC_CFLAGS) AC_SUBST(GCROOTS_REQ) AC_SUBST(GCROOTS_LIBS) AC_SUBST(GCROOTS_CFLAGS) -AM_CONDITIONAL(USE_BDWGC_BUNDLED, - [test "x$with_libgcroots" = xtiny_subst_bdwgc]) -AM_CONDITIONAL(USE_LIBGCROOTS, - [test "x$with_libgcroots" != xtiny_subst \ - -a "x$with_libgcroots" != xtiny_subst_bdwgc]) +AM_CONDITIONAL(USE_LIBGCROOTS, [test "x$with_libgcroots" != xtiny_subst]) AM_CONDITIONAL(USE_LIBGCROOTS_BUNDLED, [test "x$with_libgcroots" = xno]) AM_CONDITIONAL(USE_LIBGCROOTS_TINY_SUBST, - [test "x$with_libgcroots" = xtiny_subst \ - -o "x$with_libgcroots" = xtiny_subst_bdwgc]) + [test "x$with_libgcroots" = xtiny_subst]) ######################################## diff --git a/sigscheme.pc.in b/sigscheme.pc.in index 763fbd42..ae1ee4d4 100644 --- a/sigscheme.pc.in +++ b/sigscheme.pc.in @@ -67,6 +67,6 @@ sscm_debug=@use_debug@ Name: @PACKAGE_NAME@ Description: Scheme interpreter for embedded use Version: @VERSION@ -Requires: @GCROOTS_REQ@ +Requires.private: @BDWGC_REQ@ @GCROOTS_REQ@ Libs: -L${libdir} -lsscm Cflags: -I${includedir} diff --git a/src/Makefile.am b/src/Makefile.am index 4daf9fcf..3f979332 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -369,20 +369,20 @@ endif if USE_LIBSSCM libsscm_la_SOURCES = $(libsscm_sources) -libsscm_la_LIBADD = $(LIBOBJS) @GCROOTS_LIBS@ +libsscm_la_LIBADD = $(LIBOBJS) @BDWGC_LIBS@ @GCROOTS_LIBS@ libsscm_la_LDFLAGS = -version-info $(libsscm_version) # To take precedence over installed gcroots.h by the bundled # libgcroots/include/gcroots.h, @GCROOTS_CFLAGS@ must be placed here. -libsscm_la_CPPFLAGS = -I$(top_builddir)/include @GCROOTS_CFLAGS@ \ - -DSCM_COMPILING_LIBSSCM=1 +libsscm_la_CPPFLAGS = -I$(top_builddir)/include @BDWGC_CFLAGS@ \ + @GCROOTS_CFLAGS@ -DSCM_COMPILING_LIBSSCM=1 libsscm_la_CFLAGS = endif if USE_SHELL bin_PROGRAMS = sscm sscm_SOURCES = main.c -sscm_LDADD = libsscm.la @GCROOTS_LIBS@ -sscm_CPPFLAGS = -I$(top_builddir)/include @GCROOTS_CFLAGS@ +sscm_LDADD = libsscm.la @BDWGC_LIBS@ @GCROOTS_LIBS@ +sscm_CPPFLAGS = -I$(top_builddir)/include @BDWGC_CFLAGS@ @GCROOTS_CFLAGS@ sscm_CFLAGS = endif diff --git a/src/gcroots/gcroots.c b/src/gcroots/gcroots.c index 16c72b89..4ad3e0c1 100644 --- a/src/gcroots/gcroots.c +++ b/src/gcroots/gcroots.c @@ -35,11 +35,7 @@ #include -#if SCM_WITH_BDWGC -#include -#include "gc/gc.h" -#include "gc/gc_mark.h" -#elif HAVE_GETCONTEXT +#if HAVE_GETCONTEXT #include #else #include @@ -56,35 +52,14 @@ File Local Type Definitions =======================================*/ struct _GCROOTS_context { -#if SCM_WITH_BDWGC - struct GC_stack_base sb; -#else void *stack_base; -#endif GCROOTS_mark_proc mark; -#if SCM_WITH_BDWGC - scm_bool is_protected; -#else scm_bool scan_entire_system_stack; -#endif }; -#if SCM_WITH_BDWGC -struct ready_stack_data_s { - GCROOTS_context *ctx; - GCROOTS_user_proc proc; - void *arg; -}; - -struct find_obj_data_s { - void *findee; -}; -#endif - /*======================================= Variable Definitions =======================================*/ -#if !SCM_WITH_BDWGC SCM_GLOBAL_VARS_BEGIN(static_gcroots); #define static static void *l_findee; @@ -94,22 +69,12 @@ SCM_GLOBAL_VARS_END(static_gcroots); #define l_findee SCM_GLOBAL_VAR(static_gcroots, l_findee) #define l_found SCM_GLOBAL_VAR(static_gcroots, l_found) SCM_DEFINE_STATIC_VARS(static_gcroots); -#endif /*======================================= File Local Function Declarations =======================================*/ -#if SCM_WITH_BDWGC -static void *GC_CALLBACK ready_stack_wrapper(struct GC_stack_base *sb, - void *cd); -static void GC_CALLBACK mark_internal(void **start, void **end, void *cd, - unsigned hint); -static void GC_CALLBACK find_obj(void **start, void **end, void *cd, - unsigned hint); -#else static void mark_internal(GCROOTS_context *ctx); static void find_obj(void *start, void *end, int is_certain, int is_aligned); -#endif /*======================================= Function Definitions @@ -125,20 +90,13 @@ GCROOTS_init(GCROOTS_context_alloc_proc allocator, GCROOTS_mark_proc marker, /* scan_entire_system_stack is not supported by this implementation */ SCM_ASSERT(!scan_entire_system_stack); -#if !SCM_WITH_BDWGC SCM_GLOBAL_VARS_INIT(static_gcroots); -#endif ctx = (*allocator)(sizeof(GCROOTS_context)); if (ctx) { ctx->mark = marker; -#if SCM_WITH_BDWGC - (void)scan_entire_system_stack; - ctx->is_protected = scm_false; -#else ctx->scan_entire_system_stack = scan_entire_system_stack; ctx->stack_base = NULL; -#endif } return ctx; @@ -157,26 +115,12 @@ GCROOTS_call_with_gc_ready_stack(GCROOTS_context *ctx, GCROOTS_user_proc proc, void *arg) { void *ret; -#if !SCM_WITH_BDWGC void *stack_top; /* approx */ volatile GCROOTS_user_proc anti_inline_proc; -#endif assert(ctx); assert(proc); -#if SCM_WITH_BDWGC - if (ctx->is_protected) { - ret = proc(arg); /* probably inlined */ - } else { - struct ready_stack_data_s data; - - data.ctx = ctx; - data.proc = proc; - data.arg = arg; - ret = GC_call_with_stack_base(ready_stack_wrapper, &data); - } -#else if (!ctx->stack_base) ctx->stack_base = &stack_top; @@ -185,46 +129,22 @@ GCROOTS_call_with_gc_ready_stack(GCROOTS_context *ctx, if (ctx->stack_base == &stack_top) ctx->stack_base = NULL; -#endif - - return ret; -} -#if SCM_WITH_BDWGC -static void *GC_CALLBACK -ready_stack_wrapper(struct GC_stack_base *sb, void *cd) -{ - void *ret; - struct ready_stack_data_s *pdata = (struct ready_stack_data_s *)cd; - GCROOTS_context *ctx = pdata->ctx; - - memcpy(&ctx->sb, sb, sizeof(*sb)); - ctx->is_protected = scm_true; - ret = (*pdata->proc)(pdata->arg); - ctx->is_protected = scm_false; return ret; } -#endif SCM_EXPORT void GCROOTS_mark(GCROOTS_context *ctx) { -#if !SCM_WITH_BDWGC #if HAVE_GETCONTEXT ucontext_t uctx; #else jmp_buf env; #endif void (*volatile anti_inline_mark_internal)(GCROOTS_context *); -#endif assert(ctx); -#if SCM_WITH_BDWGC - if (ctx->is_protected) { - GC_custom_push_regs_and_stack(mark_internal, ctx, &ctx->sb, NULL); - } -#else if (ctx->stack_base) { #if HAVE_GETCONTEXT getcontext(&uctx); @@ -234,19 +154,8 @@ GCROOTS_mark(GCROOTS_context *ctx) anti_inline_mark_internal = mark_internal; (*anti_inline_mark_internal)(ctx); } -#endif } -#if SCM_WITH_BDWGC -static void GC_CALLBACK -mark_internal(void **start, void **end, void *cd, unsigned hint) -{ - GCROOTS_context *ctx = (GCROOTS_context *)cd; - - (void)hint; - (*ctx->mark)(start, end, scm_false, scm_false); -} -#else static void mark_internal(GCROOTS_context *ctx) { @@ -254,41 +163,25 @@ mark_internal(GCROOTS_context *ctx) (*ctx->mark)(ctx->stack_base, &stack_top, scm_false, scm_false); } -#endif int GCROOTS_is_protected_context(GCROOTS_context *ctx) { assert(ctx); -#if SCM_WITH_BDWGC - return ctx->is_protected; -#else return (ctx->stack_base) ? scm_true : scm_false; -#endif } int GCROOTS_is_protected(GCROOTS_context *ctx, void *obj) { -#if SCM_WITH_BDWGC - struct find_obj_data_s data; -#else GCROOTS_context tmp_ctx; -#endif assert(ctx); - if (obj == NULL) /* not expected actually */ - return scm_true; if (!GCROOTS_is_protected_context(ctx)) return scm_false; -#if SCM_WITH_BDWGC - data.findee = obj; - GC_custom_push_regs_and_stack(find_obj, &data, &ctx->sb, NULL); - return data.findee == NULL; -#else tmp_ctx = *ctx; tmp_ctx.mark = find_obj; /* not actually a mark function */ l_findee = obj; @@ -296,30 +189,8 @@ GCROOTS_is_protected(GCROOTS_context *ctx, void *obj) GCROOTS_mark(&tmp_ctx); return l_found; -#endif } -#if SCM_WITH_BDWGC -static void GC_CALLBACK -find_obj(void **start, void **end, void *cd, unsigned hint) -{ - struct find_obj_data_s *pdata = (struct find_obj_data_s *)cd; - char *p = (char *)start; - char *lim = (char *)(end - 1); - void *findee = pdata->findee; - - (void)hint; - if (findee == NULL) - return; /* already found */ - - for (; p <= lim; p += ALIGNOF_VOID_P) { - if (*(void **)p == findee) { - pdata->findee = NULL; /* found */ - break; - } - } -} -#else static void find_obj(void *start, void *end, int is_certain, int is_aligned) { @@ -339,4 +210,3 @@ find_obj(void *start, void *end, int is_certain, int is_aligned) && SIZEOF_VOID_P != ALIGNOF_VOID_P && offset % SIZEOF_VOID_P); } -#endif diff --git a/src/sigscheme.h b/src/sigscheme.h index a4acc264..08cc76d5 100644 --- a/src/sigscheme.h +++ b/src/sigscheme.h @@ -45,11 +45,6 @@ #include #include -#include -#if (GCROOTS_API_REVISION < 1) -#error "libgcroots that has API revision >= 1 is required" -#endif - #include "scmint.h" #include "global.h" #if SCM_USE_MULTIBYTE_CHAR diff --git a/src/storage-gc.c b/src/storage-gc.c index 04bbf9d6..f967bbd4 100644 --- a/src/storage-gc.c +++ b/src/storage-gc.c @@ -64,6 +64,13 @@ #include "sigscheme.h" #include "sigschemeinternal.h" +#ifdef SCM_WITH_BDWGC +#include +#include +#else +#include +#endif + /*======================================= File Local Macro Definitions =======================================*/ @@ -83,6 +90,22 @@ =======================================*/ typedef ScmCell *ScmObjHeap; +#ifdef SCM_WITH_BDWGC +typedef struct BDWGCContext_ { + struct GC_stack_base stack_base; + scm_bool is_protected; +} BDWGCContext; + +typedef struct BDWGCReadyStackData_ { + ScmGCGateFunc func; + void *arg; +} BDWGCReadyStackData; + +typedef struct BDWGCFindObjectData_ { + void *findee; +} BDWGCFindObjectData; +#endif + /*======================================= Variable Definitions =======================================*/ @@ -101,7 +124,11 @@ static ScmObj l_freelist; static ScmObj **l_protected_vars; static size_t l_protected_vars_size, l_n_empty_protected_vars; +#ifdef SCM_WITH_BDWGC +static BDWGCContext *l_bdwgc_ctx; +#else static GCROOTS_context *l_gcroots_ctx; +#endif #if SCM_DEBUG static size_t l_gcing; static scm_bool l_allocating; @@ -120,7 +147,11 @@ SCM_GLOBAL_VARS_END(static_gc); #define l_protected_vars_size SCM_GLOBAL_VAR(static_gc, l_protected_vars_size) #define l_n_empty_protected_vars \ SCM_GLOBAL_VAR(static_gc, l_n_empty_protected_vars) +#ifdef SCM_WITH_BDWGC +#define l_bdwgc_ctx SCM_GLOBAL_VAR(static_gc, l_bdwgc_ctx) +#else #define l_gcroots_ctx SCM_GLOBAL_VAR(static_gc, l_gcroots_ctx) +#endif #if SCM_DEBUG #define l_gcing SCM_GLOBAL_VAR(static_gc, l_gcing) #define l_allocating SCM_GLOBAL_VAR(static_gc, l_allocating) @@ -160,6 +191,17 @@ static void finalize_protected_var(void); static void scm_ensure_proper_freelist(ScmObj flst); /* FIXME */ #endif +/* BDWGC Related Functions */ +#ifdef SCM_WITH_BDWGC +static void *GC_CALLBACK bdwgc_ready_stack(struct GC_stack_base *base, + void *data); +static void GC_CALLBACK bdwgc_mark(void **start, void **end, + void *data, unsigned hint); +static void GC_CALLBACK bdwgc_find_object(void **start, void **end, + void *data, unsigned hint); +static int bdwgc_context_is_protected(BDWGCContext *ctx, void *obj); +#endif + /*======================================= Function Definitions =======================================*/ @@ -188,9 +230,14 @@ scm_init_gc(const ScmStorageConf *conf) l_allocating = scm_false; #endif +#ifdef SCM_WITH_BDWGC + l_bdwgc_ctx = scm_malloc(sizeof(BDWGCContext)); + l_bdwgc_ctx->is_protected = scm_false; +#else l_gcroots_ctx = GCROOTS_init(scm_malloc, (GCROOTS_mark_proc)gc_mark_locations, scm_false); +#endif initialize_heap(conf); } @@ -201,8 +248,14 @@ scm_fin_gc(void) finalize_heap(); finalize_protected_var(); +#ifdef SCM_WITH_BDWGC + free(l_bdwgc_ctx); + l_bdwgc_ctx = NULL; +#else GCROOTS_fin(l_gcroots_ctx); free(l_gcroots_ctx); + l_gcroots_ctx = NULL; +#endif SCM_GLOBAL_VARS_FIN(static_gc); } @@ -339,7 +392,13 @@ scm_gc_protectedp(ScmObj obj) #else SCM_CONSTANTP(obj) #endif - || GCROOTS_is_protected(l_gcroots_ctx, (void *)obj)) + || +#ifdef SCM_WITH_BDWGC + bdwgc_context_is_protected(l_bdwgc_ctx, (void *)obj) +#else + GCROOTS_is_protected(l_gcroots_ctx, (void *)obj) +#endif + ) return scm_true; /* referred from static variables */ @@ -373,13 +432,32 @@ scm_gc_protectedp(ScmObj obj) SCM_EXPORT void * scm_call_with_gc_ready_stack(ScmGCGateFunc func, void *arg) { +#ifdef SCM_WITH_BDWGC + assert(l_bdwgc_ctx); + assert(func); + + if (l_bdwgc_ctx->is_protected) { + return func(arg); + } else { + BDWGCReadyStackData data; + data.func = func; + data.arg = arg; + return GC_call_with_stack_base(bdwgc_ready_stack, &data); + } +#else return GCROOTS_call_with_gc_ready_stack(l_gcroots_ctx, func, arg); +#endif } SCM_EXPORT scm_bool scm_gc_protected_contextp(void) { - return GCROOTS_is_protected_context(l_gcroots_ctx); +#ifdef SCM_WITH_BDWGC + assert(l_bdwgc_ctx); + return l_bdwgc_ctx->is_protected; +#else + return GCROOTS_is_protected_context(l_gcroots_ctx); +#endif } /*=========================================================================== @@ -769,7 +847,17 @@ gc_mark(void) /* Mark stack and all machine-dependent contexts such as registers, * register windows (SPARC), register stack backing store (IA-64) etc. */ +#ifdef SCM_WITH_BDWGC + assert(l_bdwgc_ctx); + if (l_bdwgc_ctx->is_protected) { + GC_custom_push_regs_and_stack(bdwgc_mark, + NULL, + &(l_bdwgc_ctx->stack_base), + NULL); + } +#else GCROOTS_mark(l_gcroots_ctx); +#endif gc_mark_global_vars(); @@ -924,3 +1012,64 @@ gc_sweep(void) return sum_collected; } + +#ifdef SCM_WITH_BDWGC +static void *GC_CALLBACK +bdwgc_ready_stack(struct GC_stack_base *base, + void *data) +{ + void *result; + BDWGCReadyStackData *ready_stack_data = (BDWGCReadyStackData *)data; + + memcpy(&(l_bdwgc_ctx->stack_base), base, sizeof(*base)); + l_bdwgc_ctx->is_protected = scm_true; + result = (*ready_stack_data->func)(ready_stack_data->arg); + l_bdwgc_ctx->is_protected = scm_false; + return result; +} + +static void GC_CALLBACK +bdwgc_mark(void **start, void **end, void *data, unsigned hint) +{ + gc_mark_locations((ScmObj *)start, (ScmObj *)end, scm_false, scm_false); +} + +static void GC_CALLBACK +bdwgc_find_object(void **start, void **end, void *data, unsigned hint) +{ + BDWGCFindObjectData *find_object_data = (BDWGCFindObjectData *)data; + char *p = (char *)start; + char *lim = (char *)(end - 1); + void *findee = find_object_data->findee; + + if (findee == NULL) + return; /* already found */ + + for (; p <= lim; p += ALIGNOF_VOID_P) { + if (*(void **)p == findee) { + find_object_data->findee = NULL; /* found */ + break; + } + } +} + +static int +bdwgc_context_is_protected(BDWGCContext *ctx, void *obj) +{ + BDWGCFindObjectData data; + + assert(ctx); + if (obj == NULL) /* not expected actually */ + return scm_true; + + if (!ctx->is_protected) + return scm_false; + + data.findee = obj; + GC_custom_push_regs_and_stack(bdwgc_find_object, + &data, + &(ctx->stack_base), + NULL); + return data.findee == NULL; +} +#endif