summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common.mk2
-rw-r--r--yjit/Cargo.toml1
-rw-r--r--yjit/src/stats.rs43
-rw-r--r--yjit/src/virtualmem.rs5
-rw-r--r--yjit/yjit.mk1
-rw-r--r--zjit/Cargo.toml1
-rw-r--r--zjit/src/options.rs10
-rw-r--r--zjit/src/state.rs2
-rw-r--r--zjit/src/stats.rs7
-rw-r--r--zjit/src/virtualmem.rs11
-rw-r--r--zjit/zjit.mk1
11 files changed, 40 insertions, 44 deletions
diff --git a/common.mk b/common.mk
index 5cc7886796..ef7eb6ab58 100644
--- a/common.mk
+++ b/common.mk
@@ -266,6 +266,7 @@ MAKE_LINK = $(MINIRUBY) -rfileutils -e "include FileUtils::Verbose" \
YJIT_RUSTC_ARGS = --crate-name=yjit \
--crate-type=staticlib \
--edition=2021 \
+ --cfg 'feature="stats_allocator"' \
-g \
-C lto=thin \
-C opt-level=3 \
@@ -276,6 +277,7 @@ YJIT_RUSTC_ARGS = --crate-name=yjit \
ZJIT_RUSTC_ARGS = --crate-name=zjit \
--crate-type=staticlib \
--edition=2024 \
+ --cfg 'feature="stats_allocator"' \
-g \
-C lto=thin \
-C opt-level=3 \
diff --git a/yjit/Cargo.toml b/yjit/Cargo.toml
index af9c18c0dc..e2f1d84ffd 100644
--- a/yjit/Cargo.toml
+++ b/yjit/Cargo.toml
@@ -25,3 +25,4 @@ disasm = ["capstone"]
# from cfg!(debug_assertions) so that we can see disasm of the code
# that would run in the release mode.
runtime_checks = []
+stats_allocator = []
diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs
index ea6130973d..09971c5b3a 100644
--- a/yjit/src/stats.rs
+++ b/yjit/src/stats.rs
@@ -1,9 +1,8 @@
//! Everything related to the collection of runtime stats in YJIT
//! See the --yjit-stats command-line option
-use std::alloc::{GlobalAlloc, Layout, System};
use std::ptr::addr_of_mut;
-use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::atomic::Ordering;
use std::time::Instant;
use std::collections::HashMap;
@@ -12,6 +11,10 @@ use crate::cruby::*;
use crate::options::*;
use crate::yjit::{yjit_enabled_p, YJIT_INIT_TIME};
+#[cfg(feature = "stats_allocator")]
+#[path = "../../jit/src/lib.rs"]
+mod jit;
+
/// Running total of how many ISeqs are in the system.
#[no_mangle]
pub static mut rb_yjit_live_iseq_count: u64 = 0;
@@ -20,43 +23,9 @@ pub static mut rb_yjit_live_iseq_count: u64 = 0;
#[no_mangle]
pub static mut rb_yjit_iseq_alloc_count: u64 = 0;
-/// A middleware to count Rust-allocated bytes as yjit_alloc_size.
-#[global_allocator]
-static GLOBAL_ALLOCATOR: StatsAlloc = StatsAlloc { alloc_size: AtomicUsize::new(0) };
-
-pub struct StatsAlloc {
- alloc_size: AtomicUsize,
-}
-
-unsafe impl GlobalAlloc for StatsAlloc {
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- self.alloc_size.fetch_add(layout.size(), Ordering::SeqCst);
- System.alloc(layout)
- }
-
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- self.alloc_size.fetch_sub(layout.size(), Ordering::SeqCst);
- System.dealloc(ptr, layout)
- }
-
- unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
- self.alloc_size.fetch_add(layout.size(), Ordering::SeqCst);
- System.alloc_zeroed(layout)
- }
-
- unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- if new_size > layout.size() {
- self.alloc_size.fetch_add(new_size - layout.size(), Ordering::SeqCst);
- } else if new_size < layout.size() {
- self.alloc_size.fetch_sub(layout.size() - new_size, Ordering::SeqCst);
- }
- System.realloc(ptr, layout, new_size)
- }
-}
-
/// The number of bytes YJIT has allocated on the Rust heap.
pub fn yjit_alloc_size() -> usize {
- GLOBAL_ALLOCATOR.alloc_size.load(Ordering::SeqCst)
+ jit::GLOBAL_ALLOCATOR.alloc_size.load(Ordering::SeqCst)
}
/// Mapping of C function / ISEQ name to integer indices
diff --git a/yjit/src/virtualmem.rs b/yjit/src/virtualmem.rs
index aa6d21f210..97409c796c 100644
--- a/yjit/src/virtualmem.rs
+++ b/yjit/src/virtualmem.rs
@@ -7,6 +7,9 @@ use std::{cell::RefCell, ptr::NonNull};
use crate::{backend::ir::Target, stats::yjit_alloc_size, utils::IntoUsize};
+#[cfg(test)]
+use crate::options::get_option;
+
#[cfg(not(test))]
pub type VirtualMem = VirtualMemory<sys::SystemAllocator>;
@@ -411,7 +414,7 @@ pub mod tests {
PAGE_SIZE.try_into().unwrap(),
NonNull::new(mem_start as *mut u8).unwrap(),
mem_size,
- 128 * 1024 * 1024,
+ get_option!(mem_size),
)
}
diff --git a/yjit/yjit.mk b/yjit/yjit.mk
index 6b22a15960..cf68edb297 100644
--- a/yjit/yjit.mk
+++ b/yjit/yjit.mk
@@ -6,6 +6,7 @@ YJIT_SRC_FILES = $(wildcard \
$(top_srcdir)/yjit/src/*/*.rs \
$(top_srcdir)/yjit/src/*/*/*.rs \
$(top_srcdir)/yjit/src/*/*/*/*.rs \
+ $(top_srcdir)/jit/src/lib.rs \
)
# Because of Cargo cache, if the actual binary is not changed from the
diff --git a/zjit/Cargo.toml b/zjit/Cargo.toml
index 617cd11916..c97c845a6e 100644
--- a/zjit/Cargo.toml
+++ b/zjit/Cargo.toml
@@ -20,3 +20,4 @@ insta = "1.43.1"
# Support --yjit-dump-disasm and RubyVM::YJIT.disasm using libcapstone.
disasm = ["capstone"]
runtime_checks = []
+stats_allocator = []
diff --git a/zjit/src/options.rs b/zjit/src/options.rs
index dbb6ee8ebb..2a9b2e7d27 100644
--- a/zjit/src/options.rs
+++ b/zjit/src/options.rs
@@ -35,6 +35,10 @@ pub struct Options {
/// Note that the command line argument is expressed in MiB and not bytes.
pub exec_mem_bytes: usize,
+ /// Hard limit of ZJIT's total memory usage.
+ /// Note that the command line argument is expressed in MiB and not bytes.
+ pub mem_bytes: usize,
+
/// Number of times YARV instructions should be profiled.
pub num_profiles: u8,
@@ -79,6 +83,7 @@ impl Default for Options {
fn default() -> Self {
Options {
exec_mem_bytes: 64 * 1024 * 1024,
+ mem_bytes: 128 * 1024 * 1024,
num_profiles: DEFAULT_NUM_PROFILES,
stats: false,
print_stats: false,
@@ -100,9 +105,8 @@ impl Default for Options {
/// Note that --help allows only 80 chars per line, including indentation, and it also puts the
/// description in a separate line if the option name is too long. 80-char limit --> | (any character beyond this `|` column fails the test)
pub const ZJIT_OPTIONS: &[(&str, &str)] = &[
- // TODO: Hide --zjit-exec-mem-size from ZJIT_OPTIONS once we add --zjit-mem-size (Shopify/ruby#686)
- ("--zjit-exec-mem-size=num",
- "Size of executable memory block in MiB (default: 64)."),
+ ("--zjit-mem-size=num",
+ "Max amount of memory that ZJIT can use (in MiB)."),
("--zjit-call-threshold=num",
"Number of calls to trigger JIT (default: 2)."),
("--zjit-num-profiles=num",
diff --git a/zjit/src/state.rs b/zjit/src/state.rs
index 02bba3b7a3..da97829e43 100644
--- a/zjit/src/state.rs
+++ b/zjit/src/state.rs
@@ -85,7 +85,7 @@ impl ZJITState {
page_size,
NonNull::new(virt_block).unwrap(),
exec_mem_bytes,
- exec_mem_bytes, // TODO: change this to --zjit-mem-size (Shopify/ruby#686)
+ get_option!(mem_bytes)
);
let mem_block = Rc::new(RefCell::new(mem_block));
diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs
index d1a6d584b9..98ddc20226 100644
--- a/zjit/src/stats.rs
+++ b/zjit/src/stats.rs
@@ -1,6 +1,11 @@
//! Counters and associated methods for events when ZJIT is run.
use std::time::Instant;
+use std::sync::atomic::Ordering;
+
+#[cfg(feature = "stats_allocator")]
+#[path = "../../jit/src/lib.rs"]
+mod jit;
use crate::{cruby::*, hir::ParseError, options::get_option, state::{zjit_enabled_p, ZJITState}};
@@ -353,5 +358,5 @@ pub fn with_time_stat<F, R>(counter: Counter, func: F) -> R where F: FnOnce() ->
/// The number of bytes ZJIT has allocated on the Rust heap.
pub fn zjit_alloc_size() -> usize {
- 0 // TODO: report the actual memory usage to support --zjit-mem-size (Shopify/ruby#686)
+ jit::GLOBAL_ALLOCATOR.alloc_size.load(Ordering::SeqCst)
}
diff --git a/zjit/src/virtualmem.rs b/zjit/src/virtualmem.rs
index 42ce525fde..11de4e08af 100644
--- a/zjit/src/virtualmem.rs
+++ b/zjit/src/virtualmem.rs
@@ -7,6 +7,9 @@ use std::ptr::NonNull;
use crate::stats::zjit_alloc_size;
+#[cfg(test)]
+use crate::options::get_option;
+
#[cfg(not(test))]
pub type VirtualMem = VirtualMemory<sys::SystemAllocator>;
@@ -369,6 +372,12 @@ pub mod tests {
// Fictional architecture where each page is 4 bytes long
const PAGE_SIZE: usize = 4;
fn new_dummy_virt_mem() -> VirtualMemory<TestingAllocator> {
+ unsafe {
+ if crate::options::OPTIONS.is_none() {
+ crate::options::OPTIONS = Some(crate::options::Options::default());
+ }
+ }
+
let mem_size = PAGE_SIZE * 10;
let alloc = TestingAllocator::new(mem_size);
let mem_start: *const u8 = alloc.mem_start();
@@ -378,7 +387,7 @@ pub mod tests {
PAGE_SIZE.try_into().unwrap(),
NonNull::new(mem_start as *mut u8).unwrap(),
mem_size,
- 128 * 1024 * 1024,
+ get_option!(mem_bytes),
)
}
diff --git a/zjit/zjit.mk b/zjit/zjit.mk
index be989bdecd..f0bf1b0da5 100644
--- a/zjit/zjit.mk
+++ b/zjit/zjit.mk
@@ -9,6 +9,7 @@ ZJIT_SRC_FILES = $(wildcard \
$(top_srcdir)/zjit/src/*/*.rs \
$(top_srcdir)/zjit/src/*/*/*.rs \
$(top_srcdir)/zjit/src/*/*/*/*.rs \
+ $(top_srcdir)/jit/src/lib.rs \
)
$(RUST_LIB): $(ZJIT_SRC_FILES)