Skip to content

Commit 5a24982

Browse files
authored
[mmtk-julia] Allow building Julia with variations of the binding (#57176)
This PR enables building the mmtk-julia binding with different configurations other than non-moving Immix. While it was already possible to do so when building from source, this should enable using the binaries generated via the latest version from BinaryBuilder (JuliaPackaging/Yggdrasil#10357). I have also decoupled MMTk from the code, such that it should be *an option* for a third-party heap. This should be set using `WITH_THIRD_PARTY_GC=mmtk` (in `Make.user` or as an environment variable). The different configurations of MMTk can be achieved by setting the variables below (set in `Make.user`, for example): | Variable | | | |---------------|--------------|---------------| | `MMTK_PLAN` | Immix | StickyImmix | | `MMTK_MOVING` | 0 | 1 | | `MMTK_BUILD` | release | debug | Note that the actual code to support building with moving and sticky immix will be added in future PRs. I've also added some preliminary documentation in `doc/gc.md` about building Julia with MMTk, including a link to the binding and an small FAQ on what to do if you break the build of Julia+MMTk.
1 parent c9156d4 commit 5a24982

File tree

9 files changed

+108
-35
lines changed

9 files changed

+108
-35
lines changed

Make.inc

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,6 @@ HAVE_SSP := 0
8080
WITH_GC_VERIFY := 0
8181
WITH_GC_DEBUG_ENV := 0
8282

83-
# Use stock if MMTK_PLAN hasn't been defined
84-
MMTK_PLAN ?= None
85-
8683
# Enable DTrace support
8784
WITH_DTRACE := 0
8885

@@ -841,29 +838,44 @@ JCXXFLAGS += -DGC_DEBUG_ENV
841838
JCFLAGS += -DGC_DEBUG_ENV
842839
endif
843840

844-
ifneq (${MMTK_PLAN},None)
845-
JCXXFLAGS += -DMMTK_GC
846-
JCFLAGS += -DMMTK_GC
847-
# Do a release build on the binding by default
848-
MMTK_BUILD ?= release
841+
# By default we use the stock GC
842+
WITH_THIRD_PARTY_GC ?= 0
843+
844+
# Convert to lowercase
845+
USE_THIRD_PARTY_GC := $(shell echo $(WITH_THIRD_PARTY_GC) | tr A-Z a-z)
846+
847+
# NB: When adding a new GC, make sure to add -DWITH_THIRD_PARTY_HEAP=<#NEW_GC>
848+
# to the variables JCFLAGS and JCXXFLAGS according to the mapping (MMTK=1, #NEW_GC=2)
849+
850+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
851+
JCXXFLAGS += -DWITH_THIRD_PARTY_HEAP=1
852+
JCFLAGS += -DWITH_THIRD_PARTY_HEAP=1
853+
854+
# Must specify a supported MMTk Plan: Immix or StickyImmix
849855
ifeq (${MMTK_PLAN},Immix)
850856
JCXXFLAGS += -DMMTK_PLAN_IMMIX
851857
JCFLAGS += -DMMTK_PLAN_IMMIX
858+
else ifeq (${MMTK_PLAN},StickyImmix)
859+
JCXXFLAGS += -DMMTK_PLAN_STICKYIMMIX
860+
JCFLAGS += -DMMTK_PLAN_STICKYIMMIX
852861
else
853-
$(error "Unsupported MMTk plan: $(MMTK_PLAN)")
862+
$(error "Unsupported MMTk plan: $(MMTK_PLAN). Supported plan(s): Immix or StickyImmix.")
854863
endif
855864

865+
# Do a release build on the binding by default
866+
MMTK_BUILD ?= release
867+
856868
# Location of mmtk-julia binding
857869
# (needed for api/*.h and .so file)
858870
MMTK_JULIA_DIR ?= $(BUILDROOT)/usr/lib/mmtk_julia
859-
860871
MMTK_DIR = ${MMTK_JULIA_DIR}/mmtk
861872
MMTK_API_INC = ${MMTK_DIR}/api
862-
863873
MMTK_LIB := -lmmtk_julia
864-
else
865-
MMTK_JULIA_INC :=
866-
MMTK_LIB :=
874+
875+
# Must specify a supported third-party GC or use the stock GC.
876+
# Supported third-party GCs: mmtk
877+
else ifneq (${USE_THIRD_PARTY_GC},0)
878+
$(error "Unsupported third-party GC: $(WITH_THIRD_PARTY_GC). Supported option(s): mmtk")
867879
endif
868880

869881
ifeq ($(WITH_DTRACE), 1)
@@ -966,19 +978,17 @@ ARCH := $(BUILD_OS)
966978
endif
967979
endif
968980

969-
# MMTk is only available on x86_64 Linux for now
970-
ifneq (${MMTK_PLAN},None)
971981

982+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
983+
# MMTk is only available on x86_64 Linux for now
972984
ifeq ($(OS),Linux)
973985
MMTK_LIB_NAME := libmmtk_julia.so
974986
else
975987
$(error "Unsupported OS for MMTk")
976988
endif
977-
978989
ifneq ($(ARCH),x86_64)
979990
$(error "Unsupported build architecture for MMTk")
980991
endif
981-
982992
endif
983993

984994
# Detect common pre-SSE2 JULIA_CPU_TARGET values known not to work (#7185)
@@ -1407,7 +1417,12 @@ CSL_NEXT_GLIBCXX_VERSION=GLIBCXX_3\.4\.34|GLIBCXX_3\.5\.|GLIBCXX_4\.
14071417
# Note: we explicitly _do not_ define `CSL` here, since it requires some more
14081418
# advanced techniques to decide whether it should be installed from a BB source
14091419
# or not. See `deps/csl.mk` for more detail.
1410-
BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP OPENSSL LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP LLD LIBTRACYCLIENT BOLT MMTK_JULIA
1420+
BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP OPENSSL LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP LLD LIBTRACYCLIENT BOLT
1421+
1422+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
1423+
BB_PROJECTS += MMTK_JULIA
1424+
endif
1425+
14111426
define SET_BB_DEFAULT
14121427
# First, check to see if BB is disabled on a global setting
14131428
ifeq ($$(USE_BINARYBUILDER),0)

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ endif
281281
endif
282282
endif
283283

284-
ifneq (${MMTK_PLAN},None)
284+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
285285
# Make sure we use the right version of $MMTK_PLAN, $MMTK_MOVING and $MMTK_BUILD
286286
# if we use the BinaryBuilder version of mmtk-julia
287287
ifeq ($(USE_BINARYBUILDER_MMTK_JULIA),1)
@@ -291,10 +291,10 @@ else ifeq (${MMTK_PLAN},StickyImmix)
291291
LIB_PATH_PLAN = sticky
292292
endif
293293

294-
ifeq ($(MMTK_MOVING), 0)
295-
LIB_PATH_MOVING := non_moving
296-
else
294+
ifeq ($(MMTK_MOVING), 1)
297295
LIB_PATH_MOVING := moving
296+
else
297+
LIB_PATH_MOVING := non_moving
298298
endif
299299

300300
JL_PRIVATE_LIBS-0 += $(LIB_PATH_PLAN)/$(LIB_PATH_MOVING)/$(MMTK_BUILD)/libmmtk_julia

deps/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ DEP_LIBS += libwhich
195195
endif
196196
endif
197197

198-
ifneq (${MMTK_PLAN},None)
198+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
199199
DEP_LIBS += mmtk_julia
200200
endif
201201

deps/mmtk_julia.mk

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
## MMTK ##
22

33
# Both MMTK_MOVING and MMTK_PLAN should be specified in the Make.user file.
4-
# At this point, since we only support non-moving this is always set to 0
5-
# FIXME: change it to `?:` when introducing moving plans
6-
MMTK_MOVING := 0
4+
# FIXME: By default we do a non-moving build. We should change the default to 1
5+
# once we support moving plans.
6+
MMTK_MOVING ?= 0
77
MMTK_VARS := MMTK_PLAN=$(MMTK_PLAN) MMTK_MOVING=$(MMTK_MOVING)
88

99
ifneq ($(USE_BINARYBUILDER_MMTK_JULIA),1)

doc/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ DevDocs = [
229229
"devdocs/aot.md",
230230
"devdocs/gc-sa.md",
231231
"devdocs/gc.md",
232+
"devdocs/gc-mmtk.md",
232233
"devdocs/jit.md",
233234
"devdocs/builtins.md",
234235
"devdocs/precompile_hang.md",

doc/src/devdocs/gc-mmtk.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Julia + MMTk
2+
3+
There has been quite a lot of effort to refactor the GC code inside Julia to support external GCs. The first step to enable using different GC algorithms for Julia was the design and implementation of a [GC interface](https://docs.google.com/document/d/1v0jtSrIpdEDNOxj5S9g1jPqSpuAkNWhr_T8ToFC9RLI/edit?usp=sharing). To drive that interface, we added support for building Julia with [MMTk](https://www.mmtk.io) (Memory Management Toolkit). Using Julia + MMTk enables testing different GC implementations, allowing developers to choose a specific implementation when building Julia from source. The connection between Julia and MMTk is done via a *binding*, which links the language runtime with MMTk core. The mmtk-julia binding is written in Rust and can be found in [this repository](https://github.com/mmtk/mmtk-julia).
4+
5+
> [!NOTE]
6+
> Using a different GC requires building Julia from source. It is not possible to switch implementations at runtime. To see what version of the GC is currently being used, run `versioninfo()` from the Julia REPL and it should show the version under `GC: ...`.
7+
8+
## Building Julia with MMTk
9+
10+
There are 3 different ways of building Julia with MMTk: building from source using a fixed release of the binding, checking out a custom version in the mmtk-julia [repository](https://github.com/mmtk/mmtk-julia) or using a precompiled binary from Julia's BinaryBuilder. The easiest way is to use the BinaryBuilder binary. First, to enable MMTk as a third-party GC, set the variable `WITH_THIRD_PARTY_GC` to `mmtk`. Then, for example, to use the Immix as the GC, simply set the variable `MMTK_PLAN=Immix` and build Julia as usual.
11+
12+
There are different configurations supported by the following variables, which can be set in a `Make.user` file or as an environment variable. Note that at this time, setting `MMTK_PLAN=StickyImmix` (to use a generational version of Immix) or `MMTK_MOVING=1` (to enable object movement) will likely cause segmentation faults or other build failures, since we have not added support for these configurations yet. Setting `MMTK_BUILD=debug` will force a debug build of the binding, which will print some logging information that can be used to find errors that are specific to MMTk.
13+
14+
| Variable | | |
15+
|---------------|--------------|---------------|
16+
| `MMTK_PLAN` | Immix | StickyImmix |
17+
| `MMTK_MOVING` | 0 | 1 |
18+
| `MMTK_BUILD` | release | debug |
19+
20+
Note that when setting only `MMTK_PLAN`, then the default is to do a non-moving, release build.
21+
22+
### Building mmtk-julia from source
23+
24+
It is also possible to build the binding from source. To do so, set the variable `USE_BINARYBUILDER_MMTK_JULIA=0` and the latest release version of the binding will be downloaded and built as part of building Julia. Note that this requires an installation of the rust toolchain.
25+
26+
It is also possible to build a custom version of binding by checking it out from the [git repository](https://github.com/mmtk/mmtk-julia) and setting a variable named `MMTK_JULIA_DIR` as the path that contains the binding.
27+
28+
For more information on building Julia with MMTk, please refer to the [README](https://github.com/mmtk/mmtk-julia/blob/master/README.md) file in the binding repo.
29+
30+
### I've got a build error when building Julia with MMTk, what should I do?
31+
32+
If you try to build Julia with MMTk and get an error it is likely due to a change to Julia that has not been yet propagated to the binding or to the code in Julia that is specific to MMTk. Some changes include:
33+
34+
(1) **Changing the memory layout of objects in Julia**. The binding relies on automatically generated Rust FFI bindings from Julia code. These files are generated using a crate named [`rust-bindgen`](https://github.com/rust-lang/rust-bindgen). To regenerate those files, check out the latest version of the `mmtk-julia` binding, set the variable `JULIA_PATH` to the path of the Julia version you are trying to build and run `make regen-bindgen-ffi` from the directory containing the binding. This should delete the current version of the FFI bindings and generate a new version based on the Julia code from `JULIA_PATH`.
35+
36+
(2) **Changing the root objects passed to the GC**. Julia passes a set of objects to the GC as roots in the function [gc_mark_roots](https://github.com/JuliaLang/julia/blob/fbe865657942da7d73cc02f76064f9ba9cdef56c/src/gc-stock.c#L2846). At the moment, this set needs to be consistent between both the Stock GC and MMTk (in the function [`jl_gc_scan_vm_specific_roots`](https://github.com/JuliaLang/julia/blob/fbe865657942da7d73cc02f76064f9ba9cdef56c/src/gc-mmtk.c#L496)).
37+
38+
(3) **Changing how objects are scanned**. MMTk uses the same strategy to find references in Julia objects as the stock GC (see [gc_mark_outrefs](https://github.com/JuliaLang/julia/blob/fbe865657942da7d73cc02f76064f9ba9cdef56c/src/gc-stock.c#L2227C19-L2227C34)). Changing the logic from this function should be reflected in the Rust code in the binding that [scan Julia objects](https://github.com/mmtk/mmtk-julia/blob/c9e046baf3a0d52fe75d6c8b28f6afd69b045d95/mmtk/src/julia_scanning.rs#L68).
39+
40+
If your case is not included in one of the alternatives above, please create an issue in the Julia repository tagging it with the `GC: MMTK` label.

src/Makefile

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ ifeq ($(USECLANG),1)
2929
FLAGS += -Wno-return-type-c-linkage -Wno-atomic-alignment
3030
endif
3131

32-
ifneq (${MMTK_PLAN},None)
32+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
3333
FLAGS += -I$(MMTK_API_INC)
3434
endif
3535

@@ -46,7 +46,7 @@ endif
4646

4747
# GC source code. It depends on which GC implementation to use.
4848
GC_SRCS := gc-common gc-stacks gc-alloc-profiler gc-heap-snapshot
49-
ifneq (${MMTK_PLAN},None)
49+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
5050
GC_SRCS += gc-mmtk
5151
else
5252
GC_SRCS += gc-stock gc-debug gc-pages gc-page-profiler
@@ -67,7 +67,7 @@ CG_LLVMLINK :=
6767
ifeq ($(JULIACODEGEN),LLVM)
6868
# Currently these files are used by both GCs. But we should make the list specific to stock, and MMTk should have its own implementation.
6969
GC_CODEGEN_SRCS := llvm-final-gc-lowering llvm-late-gc-lowering llvm-gc-invariant-verifier
70-
ifneq (${MMTK_PLAN},None)
70+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
7171
FLAGS += -I$(MMTK_API_INC)
7272
GC_CODEGEN_SRCS += llvm-late-gc-lowering-mmtk
7373
else
@@ -122,7 +122,7 @@ UV_HEADERS += uv.h
122122
UV_HEADERS += uv/*.h
123123
endif
124124
PUBLIC_HEADERS := $(BUILDDIR)/julia_version.h $(wildcard $(SRCDIR)/support/*.h) $(addprefix $(SRCDIR)/,work-stealing-queue.h gc-interface.h gc-tls-common.h julia.h julia_assert.h julia_threads.h julia_fasttls.h julia_locks.h julia_atomics.h jloptions.h)
125-
ifneq (${MMTK_PLAN},None)
125+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
126126
PUBLIC_HEADERS += $(addprefix $(SRCDIR)/,gc-tls-mmtk.h gc-wb-mmtk.h)
127127
else
128128
PUBLIC_HEADERS += $(addprefix $(SRCDIR)/,gc-tls-stock.h gc-wb-stock.h)
@@ -191,8 +191,14 @@ LIBJULIA_PATH_REL := libjulia
191191
endif
192192

193193
COMMON_LIBPATHS := -L$(build_libdir) -L$(build_shlibdir)
194-
RT_LIBS := $(WHOLE_ARCHIVE) $(LIBUV) $(WHOLE_ARCHIVE) $(LIBUTF8PROC) $(NO_WHOLE_ARCHIVE) $(LIBUNWIND) $(RT_LLVMLINK) $(OSLIBS) $(LIBTRACYCLIENT) $(LIBITTAPI) $(MMTK_LIB)
195-
CG_LIBS := $(LIBUNWIND) $(CG_LLVMLINK) $(OSLIBS) $(LIBTRACYCLIENT) $(LIBITTAPI) $(MMTK_LIB)
194+
RT_LIBS := $(WHOLE_ARCHIVE) $(LIBUV) $(WHOLE_ARCHIVE) $(LIBUTF8PROC) $(NO_WHOLE_ARCHIVE) $(LIBUNWIND) $(RT_LLVMLINK) $(OSLIBS) $(LIBTRACYCLIENT) $(LIBITTAPI)
195+
CG_LIBS := $(LIBUNWIND) $(CG_LLVMLINK) $(OSLIBS) $(LIBTRACYCLIENT) $(LIBITTAPI)
196+
197+
ifeq (${USE_THIRD_PARTY_GC},mmtk)
198+
RT_LIBS += $(MMTK_LIB)
199+
CG_LIBS += $(MMTK_LIB)
200+
endif
201+
196202
RT_DEBUG_LIBS := $(COMMON_LIBPATHS) $(WHOLE_ARCHIVE) $(BUILDDIR)/flisp/libflisp-debug.a $(WHOLE_ARCHIVE) $(BUILDDIR)/support/libsupport-debug.a -ljulia-debug $(RT_LIBS)
197203
CG_DEBUG_LIBS := $(COMMON_LIBPATHS) $(CG_LIBS) -ljulia-debug -ljulia-internal-debug
198204
RT_RELEASE_LIBS := $(COMMON_LIBPATHS) $(WHOLE_ARCHIVE) $(BUILDDIR)/flisp/libflisp.a $(WHOLE_ARCHIVE) $(BUILDDIR)/support/libsupport.a -ljulia $(RT_LIBS)

src/julia.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1251,11 +1251,17 @@ JL_DLLEXPORT JL_CONST_FUNC jl_gcframe_t **(jl_get_pgcstack)(void) JL_GLOBALLY_RO
12511251
STATIC_INLINE jl_value_t *jl_genericmemory_owner(jl_genericmemory_t *m JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
12521252

12531253
// write barriers
1254-
#ifndef MMTK_GC
1254+
1255+
#ifndef WITH_THIRD_PARTY_HEAP
12551256
#include "gc-wb-stock.h"
12561257
#else
1258+
// Pick the appropriate third-party implementation
1259+
#ifdef WITH_THIRD_PARTY_HEAP
1260+
#if WITH_THIRD_PARTY_HEAP == 1 // MMTk
12571261
#include "gc-wb-mmtk.h"
12581262
#endif
1263+
#endif
1264+
#endif
12591265

12601266
/*
12611267
how - allocation style

src/julia_threads.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44
#ifndef JL_THREADS_H
55
#define JL_THREADS_H
66

7-
#ifndef MMTK_GC
7+
#ifndef WITH_THIRD_PARTY_HEAP
88
#include "gc-tls-stock.h"
99
#else
10+
// Pick the appropriate third-party implementation
11+
#ifdef WITH_THIRD_PARTY_HEAP
12+
#if WITH_THIRD_PARTY_HEAP == 1 // MMTk
1013
#include "gc-tls-mmtk.h"
1114
#endif
15+
#endif
16+
#endif
1217
#include "gc-tls-common.h"
1318
#include "julia_atomics.h"
1419
#ifndef _OS_WINDOWS_

0 commit comments

Comments
 (0)