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
15 changes: 12 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Using Cargo's workspace feature to build all the Rust code in
# into a single package.
# TODO(alan) notes about rust version requirements. Undecided yet.
# This is the root Cargo [workspace](https://doc.rust-lang.org/cargo/reference/workspaces.html)
# and the root package for all the rust code that are statically linked into ruby. Rust tooling
# limitations means all Rust code need to share a single archive library (staticlib) at the
# integration point with non-rust code. (See rustlang/rust#44322 and #104707 for a taste of
# the linking challenges.)
#
# Do not add required dependencies. This is a policy that helps downstream consumers and give
# us tight control over what we ship. All of the optional dependencies are used exclusively
# during development.
#
# Release builds avoid Cargo entirely because offline builds can fail even when none of the
# optional dependencies are built (rust-lang/cargo#10352).

[workspace]
members = ["zjit", "yjit", "jit"]
Expand Down
2 changes: 1 addition & 1 deletion bootstraptest/test_ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,7 @@ def hello = nil
}

# check experimental warning
assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor is experimental/, %q{
assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor API is experimental/, %q{
Warning[:experimental] = $VERBOSE = true
STDERR.reopen(STDOUT)
eval("Ractor.new{}.value", nil, "test_ractor.rb", 1)
Expand Down
6 changes: 2 additions & 4 deletions common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,8 @@ MAKE_LINK = $(MINIRUBY) -rfileutils -e "include FileUtils::Verbose" \

# For release builds
YJIT_RUSTC_ARGS = --crate-name=yjit \
--crate-type=staticlib \
$(JIT_RUST_FLAGS) \
--edition=2021 \
--cfg 'feature="stats_allocator"' \
-g \
-C lto=thin \
-C opt-level=3 \
Expand All @@ -279,9 +278,8 @@ YJIT_RUSTC_ARGS = --crate-name=yjit \
'$(top_srcdir)/yjit/src/lib.rs'

ZJIT_RUSTC_ARGS = --crate-name=zjit \
--crate-type=staticlib \
$(JIT_RUST_FLAGS) \
--edition=2024 \
--cfg 'feature="stats_allocator"' \
-g \
-C lto=thin \
-C opt-level=3 \
Expand Down
80 changes: 45 additions & 35 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3896,7 +3896,6 @@ AC_SUBST(INSTALL_STATIC_LIBRARY)

[begin]_group "JIT section" && {
AC_CHECK_PROG(RUSTC, [rustc], [rustc], [no]) dnl no ac_tool_prefix
AC_CHECK_TOOL(CARGO, [cargo], [no])

dnl check if rustc is recent enough to build YJIT (rustc >= 1.58.0)
JIT_RUSTC_OK=no
Expand Down Expand Up @@ -3963,11 +3962,7 @@ AC_ARG_ENABLE(zjit,
# 1.85.0 is the first stable version that supports the 2024 edition.
AS_IF([test "$RUSTC" != "no" && echo "#[cfg(target_arch = \"$JIT_TARGET_ARCH\")] fn main() {}" |
$RUSTC - --edition=2024 --emit asm=/dev/null 2>/dev/null],
AS_IF([test "$gnumake" = "yes" -a \( "$YJIT_SUPPORT" = "no" -o "$CARGO" != "no" \)], [
# When only building ZJIT, we don't need cargo; it's required for YJIT+ZJIT build.
# Assume that if rustc is new enough, then cargo is also.
# TODO(alan): Get rid of dependency on cargo in YJIT+ZJIT build. Cargo's offline mode
# still too unreliable: https://github.com/rust-lang/cargo/issues/10352
AS_IF([test "$gnumake" = "yes"], [
rb_zjit_build_possible=yes
])
)
Expand Down Expand Up @@ -4053,36 +4048,49 @@ AS_CASE(["${ZJIT_SUPPORT}"],
AC_DEFINE(USE_ZJIT, 0)
])

# if YJIT+ZJIT release build, or any build that requires Cargo
AS_IF([test x"$JIT_CARGO_SUPPORT" != "xno" -o \( x"$YJIT_SUPPORT" != "xno" -a x"$ZJIT_SUPPORT" != "xno" \)], [
AS_IF([test x"$CARGO" = "xno"],
AC_MSG_ERROR([this build configuration requires cargo. Installation instructions available at https://www.rust-lang.org/tools/install]))

YJIT_LIBS=
ZJIT_LIBS=

# There's more processing below to get the feature set for the
# top-level crate, so capture at this point for feature set of
# just the zjit crate.
ZJIT_TEST_FEATURES="${rb_cargo_features}"
JIT_RUST_FLAGS='--crate-type=staticlib --cfg feature=\"stats_allocator\"'
RLIB_DIR=
AS_CASE(["$JIT_CARGO_SUPPORT:$YJIT_SUPPORT:$ZJIT_SUPPORT"],
[no:yes:yes], [ # release build of YJIT+ZJIT
YJIT_LIBS=
ZJIT_LIBS=
JIT_RUST_FLAGS="--crate-type=rlib"
RLIB_DIR="target/release"
RUST_LIB="target/release/libruby.a"
],
[no:*], [],
[*], [ # JIT_CARGO_SUPPORT not "no" -- cargo required.
AC_CHECK_TOOL(CARGO, [cargo], [no])
AS_IF([test x"$CARGO" = "xno"],
AC_MSG_ERROR([this build configuration requires cargo. Installation instructions available at https://www.rust-lang.org/tools/install]))

YJIT_LIBS=
ZJIT_LIBS=

# There's more processing below to get the feature set for the
# top-level crate, so capture at this point for feature set of
# just the zjit crate.
ZJIT_TEST_FEATURES="${rb_cargo_features}"

AS_IF([test x"${YJIT_SUPPORT}" != x"no"], [
rb_cargo_features="$rb_cargo_features,yjit"
])
AS_IF([test x"${ZJIT_SUPPORT}" != x"no"], [
AC_SUBST(ZJIT_TEST_FEATURES)
rb_cargo_features="$rb_cargo_features,zjit"
])
# if YJIT and ZJIT release mode
AS_IF([test "${YJIT_SUPPORT}:${ZJIT_SUPPORT}" = "yes:yes"], [
JIT_CARGO_SUPPORT=release
])
CARGO_BUILD_ARGS="--profile ${JIT_CARGO_SUPPORT} --features ${rb_cargo_features}"
AS_IF([test "${JIT_CARGO_SUPPORT}" = "dev"], [
RUST_LIB="target/debug/libruby.a"
], [
RUST_LIB="target/${JIT_CARGO_SUPPORT}/libruby.a"
])
],

AS_IF([test x"${YJIT_SUPPORT}" != x"no"], [
rb_cargo_features="$rb_cargo_features,yjit"
])
AS_IF([test x"${ZJIT_SUPPORT}" != x"no"], [
AC_SUBST(ZJIT_TEST_FEATURES)
rb_cargo_features="$rb_cargo_features,zjit"
])
# if YJIT and ZJIT release mode
AS_IF([test "${YJIT_SUPPORT}:${ZJIT_SUPPORT}" = "yes:yes"], [
JIT_CARGO_SUPPORT=release
])
CARGO_BUILD_ARGS="--profile ${JIT_CARGO_SUPPORT} --features ${rb_cargo_features}"
AS_IF([test "${JIT_CARGO_SUPPORT}" = "dev"], [
RUST_LIB="target/debug/libruby.a"
], [
RUST_LIB="target/${JIT_CARGO_SUPPORT}/libruby.a"
])
])

# In case either we're linking rust code
Expand All @@ -4098,6 +4106,7 @@ AS_IF([test -n "$RUST_LIB"], [

dnl These variables end up in ::RbConfig::CONFIG
AC_SUBST(RUSTC)dnl Rust compiler command
AC_SUBST(JIT_RUST_FLAGS)dnl the common rustc flags for JIT crates such as zjit
AC_SUBST(CARGO)dnl Cargo command for Rust builds
AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles
AC_SUBST(YJIT_SUPPORT)dnl what flavor of YJIT the Ruby build includes
Expand All @@ -4108,6 +4117,7 @@ AC_SUBST(ZJIT_LIBS)dnl path to the .a library of ZJIT
AC_SUBST(ZJIT_OBJ)dnl for optionally building the C parts of ZJIT
AC_SUBST(JIT_OBJ)dnl for optionally building C glue code for Rust FFI
AC_SUBST(RUST_LIB)dnl path to the rust .a library that contains either or both JITs
AC_SUBST(RLIB_DIR)dnl subpath of build directory for .rlib files
AC_SUBST(JIT_CARGO_SUPPORT)dnl "no" or the cargo profile of the rust code
}

Expand Down
39 changes: 32 additions & 7 deletions defs/jit.mk
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# Make recipes that deal with the rust code of YJIT and ZJIT.

# Because of Cargo cache, if the actual binary is not changed from the
# previous build, the mtime is preserved as the cached file.
# This means the target is not updated actually, and it will need to
# rebuild at the next build.
RUST_LIB_TOUCH = touch $@

ifneq ($(JIT_CARGO_SUPPORT),no)

# Show Cargo progress when doing `make V=1`
CARGO_VERBOSE_0 = -q
CARGO_VERBOSE_1 =
CARGO_VERBOSE = $(CARGO_VERBOSE_$(V))

# Because of Cargo cache, if the actual binary is not changed from the
# previous build, the mtime is preserved as the cached file.
# This means the target is not updated actually, and it will need to
# rebuild at the next build.
RUST_LIB_TOUCH = touch $@

# NOTE: MACOSX_DEPLOYMENT_TARGET to match `rustc --print deployment-target` to avoid the warning below.
# ld: warning: object file (target/debug/libjit.a(<libcapstone object>)) was built for
# newer macOS version (15.2) than being linked (15.0)
Expand All @@ -30,7 +30,32 @@ $(RUST_LIB): $(srcdir)/ruby.rs
MACOSX_DEPLOYMENT_TARGET=11.0 \
$(CARGO) $(CARGO_VERBOSE) build --manifest-path '$(top_srcdir)/Cargo.toml' $(CARGO_BUILD_ARGS)
$(RUST_LIB_TOUCH)
endif
else ifneq ($(strip $(RLIB_DIR)),) # combo build

$(RUST_LIB): $(srcdir)/ruby.rs
$(ECHO) 'building $(@F)'
$(Q) $(RUSTC) --edition=2024 \
'-L$(@D)' \
--extern=yjit \
--extern=zjit \
--crate-type=staticlib \
--cfg 'feature="yjit"' \
--cfg 'feature="zjit"' \
'--out-dir=$(@D)' \
'$(top_srcdir)/ruby.rs'

# Absolute path to avoid VPATH ambiguity
JIT_RLIB = $(TOP_BUILD_DIR)/$(RLIB_DIR)/libjit.rlib
$(YJIT_RLIB): $(JIT_RLIB)
$(ZJIT_RLIB): $(JIT_RLIB)
$(JIT_RLIB):
$(ECHO) 'building $(@F)'
$(Q) $(RUSTC) --crate-name=jit \
--edition=2024 \
$(JIT_RUST_FLAGS) \
'--out-dir=$(@D)' \
'$(top_srcdir)/jit/src/lib.rs'
endif # ifneq ($(JIT_CARGO_SUPPORT),no)

RUST_LIB_SYMBOLS = $(RUST_LIB:.a=).symbols
$(RUST_LIBOBJ): $(RUST_LIB)
Expand Down
20 changes: 0 additions & 20 deletions ext/-test-/tracepoint/tracepoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,25 +86,6 @@ tracepoint_specify_normal_and_internal_events(VALUE self)
return Qnil; /* should not be reached */
}

int rb_objspace_internal_object_p(VALUE obj);

static void
on_newobj_event(VALUE tpval, void *data)
{
VALUE obj = rb_tracearg_object(rb_tracearg_from_tracepoint(tpval));
if (!rb_objspace_internal_object_p(obj)) rb_obj_id(obj);
}

static VALUE
add_object_id(RB_UNUSED_VAR(VALUE _))
{
VALUE tp = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, on_newobj_event, NULL);
rb_tracepoint_enable(tp);
rb_yield(Qnil);
rb_tracepoint_disable(tp);
return Qnil;
}

void Init_gc_hook(VALUE);

void
Expand All @@ -114,5 +95,4 @@ Init_tracepoint(void)
Init_gc_hook(tp_mBug);
rb_define_module_function(tp_mBug, "tracepoint_track_objspace_events", tracepoint_track_objspace_events, 0);
rb_define_module_function(tp_mBug, "tracepoint_specify_normal_and_internal_events", tracepoint_specify_normal_and_internal_events, 0);
rb_define_singleton_method(tp_mBug, "tracepoint_add_object_id", add_object_id, 0);
}
12 changes: 7 additions & 5 deletions gc/default/default.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ int ruby_rgengc_debug;
#endif

#ifndef GC_DEBUG_STRESS_TO_CLASS
# define GC_DEBUG_STRESS_TO_CLASS 1
# define GC_DEBUG_STRESS_TO_CLASS RUBY_DEBUG
#endif

typedef enum {
Expand Down Expand Up @@ -9428,6 +9428,7 @@ rb_gc_impl_after_fork(void *objspace_ptr, rb_pid_t pid)

VALUE rb_ident_hash_new_with_size(st_index_t size);

#if GC_DEBUG_STRESS_TO_CLASS
/*
* call-seq:
* GC.add_stress_to_class(class[, ...])
Expand Down Expand Up @@ -9477,6 +9478,7 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)

return Qnil;
}
#endif

void *
rb_gc_impl_objspace_alloc(void)
Expand Down Expand Up @@ -9582,10 +9584,10 @@ rb_gc_impl_init(void)
rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);
}

if (GC_DEBUG_STRESS_TO_CLASS) {
rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);
rb_define_singleton_method(rb_mGC, "remove_stress_to_class", rb_gcdebug_remove_stress_to_class, -1);
}
#if GC_DEBUG_STRESS_TO_CLASS
rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);
rb_define_singleton_method(rb_mGC, "remove_stress_to_class", rb_gcdebug_remove_stress_to_class, -1);
#endif

/* internal methods */
rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency_m, 0);
Expand Down
4 changes: 2 additions & 2 deletions ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ def self.new(*args, name: nil, &block)
b = block # TODO: builtin bug
raise ArgumentError, "must be called with a block" unless block
if __builtin_cexpr!("RBOOL(ruby_single_main_ractor)")
Kernel.warn("Ractor is experimental, and the behavior may change in future versions of Ruby! " \
"Also there are many implementation issues.", uplevel: 0, category: :experimental)
Kernel.warn("Ractor API is experimental and may change in future versions of Ruby.",
uplevel: 0, category: :experimental)
end
loc = caller_locations(1, 1).first
loc = "#{loc.path}:#{loc.lineno}"
Expand Down
2 changes: 2 additions & 0 deletions template/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ JIT_CARGO_SUPPORT=@JIT_CARGO_SUPPORT@
CARGO_TARGET_DIR=@abs_top_builddir@/target
CARGO_BUILD_ARGS=@CARGO_BUILD_ARGS@
ZJIT_TEST_FEATURES=@ZJIT_TEST_FEATURES@
JIT_RUST_FLAGS=@JIT_RUST_FLAGS@
RLIB_DIR=@RLIB_DIR@
RUST_LIB=@RUST_LIB@
RUST_LIBOBJ = $(RUST_LIB:.a=.@OBJEXT@)
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
Expand Down
18 changes: 0 additions & 18 deletions test/-ext-/tracepoint/test_tracepoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,24 +82,6 @@ def run(hook)
end
end

def test_tracepoint_add_object_id
Bug.tracepoint_add_object_id do
klass = Struct.new
2.times { klass.new }

klass = Struct.new(:a)
2.times { klass.new }

klass = Struct.new(:a, :b, :c)
2.times { klass.new }

2.times { Set.new } # To test T_DATA / TypedData RUBY_TYPED_EMBEDDABLE
2.times { Proc.new { } } # To test T_DATA / TypedData non embeddable

2.times { Object.new }
end
end

def test_teardown_with_active_GC_end_hook
assert_separately([], 'require("-test-/tracepoint"); Bug.after_gc_exit_hook = proc {}; GC.start')
end
Expand Down
4 changes: 2 additions & 2 deletions yjit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ rust-version = "1.58.0" # Minimally supported rust version
publish = false # Don't publish to crates.io

[dependencies]
# No required dependencies to simplify build process. TODO: Link to yet to be
# written rationale. Optional For development and testing purposes
# No required dependencies to simplify build process.
# Optional For development and testing purposes.
capstone = { version = "0.13.0", optional = true }
jit = { version = "0.1.0", path = "../jit" }

Expand Down
20 changes: 11 additions & 9 deletions yjit/yjit.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ YJIT_SRC_FILES = $(wildcard \
$(top_srcdir)/jit/src/lib.rs \
)

# Because of Cargo cache, if the actual binary is not changed from the
# previous build, the mtime is preserved as the cached file.
# This means the target is not updated actually, and it will need to
# rebuild at the next build.
YJIT_LIB_TOUCH = touch $@

# Absolute path to match RUST_LIB rules to avoid picking
# the "target" dir in the source directory through VPATH.
BUILD_YJIT_LIBS = $(TOP_BUILD_DIR)/$(YJIT_LIBS)
Expand All @@ -24,9 +18,17 @@ ifneq ($(strip $(YJIT_LIBS)),)
yjit-libs: $(BUILD_YJIT_LIBS)
$(BUILD_YJIT_LIBS): $(YJIT_SRC_FILES)
$(ECHO) 'building Rust YJIT (release mode)'
+$(Q) $(RUSTC) $(YJIT_RUSTC_ARGS)
$(YJIT_LIB_TOUCH)
endif
$(Q) $(RUSTC) $(YJIT_RUSTC_ARGS)
else ifneq ($(strip $(RLIB_DIR)),) # combo build
# Absolute path to avoid VPATH ambiguity
YJIT_RLIB = $(TOP_BUILD_DIR)/$(RLIB_DIR)/libyjit.rlib

$(YJIT_RLIB): $(YJIT_SRC_FILES)
$(ECHO) 'building $(@F)'
$(Q) $(RUSTC) '-L$(@D)' --extern=jit $(YJIT_RUSTC_ARGS)

$(RUST_LIB): $(YJIT_RLIB)
endif # ifneq ($(strip $(YJIT_LIBS)),)

ifneq ($(YJIT_SUPPORT),no)
$(RUST_LIB): $(YJIT_SRC_FILES)
Expand Down
Loading