Skip to content

Commit

Permalink
YJIT: Make yjit_alloc_size available by default
Browse files Browse the repository at this point in the history
  • Loading branch information
k0kubun authored and jhawthorn committed Sep 14, 2023
1 parent 4e4770a commit 5d3b4ea
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 22 deletions.
7 changes: 0 additions & 7 deletions yjit/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions yjit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ crate-type = ["staticlib"]
# No required dependencies to simplify build process. TODO: Link to yet to be
# written rationale. Optional For development and testing purposes
capstone = { version = "0.10.0", optional = true }
stats_alloc = { version = "0.1.10", optional = true }

[features]
# NOTE: Development builds select a set of these via configure.ac
# For debugging, `make V=1` shows exact cargo invocation.
disasm = ["capstone"]
stats = ["stats_alloc"]
stats = []

[profile.dev]
opt-level = 0
Expand Down
49 changes: 36 additions & 13 deletions yjit/src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,51 @@

#![allow(dead_code)] // Counters are only used with the stats features

use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;

use crate::codegen::CodegenGlobals;
use crate::cruby::*;
use crate::options::*;
use crate::yjit::yjit_enabled_p;

// stats_alloc is a middleware to instrument global allocations in Rust.
#[cfg(feature="stats")]
/// A middleware to count Rust-allocated bytes as yjit_alloc_size.
#[global_allocator]
static GLOBAL_ALLOCATOR: &stats_alloc::StatsAlloc<std::alloc::System> = &stats_alloc::INSTRUMENTED_SYSTEM;
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)
}
}

// YJIT exit counts for each instruction type
const VM_INSTRUCTION_SIZE_USIZE:usize = VM_INSTRUCTION_SIZE as usize;
const VM_INSTRUCTION_SIZE_USIZE: usize = VM_INSTRUCTION_SIZE as usize;
static mut EXIT_OP_COUNT: [u64; VM_INSTRUCTION_SIZE_USIZE] = [0; VM_INSTRUCTION_SIZE_USIZE];

/// Global state needed for collecting backtraces of exits
Expand Down Expand Up @@ -481,8 +512,7 @@ fn rb_yjit_gen_stats_dict() -> VALUE {
hash_aset_usize!(hash, "code_region_size", cb.mapped_region_size());

// Rust global allocations in bytes
#[cfg(feature="stats")]
hash_aset_usize!(hash, "yjit_alloc_size", global_allocation_size());
hash_aset_usize!(hash, "yjit_alloc_size", GLOBAL_ALLOCATOR.alloc_size.load(Ordering::SeqCst));

// VM instructions count
hash_aset_usize!(hash, "vm_insns_count", rb_vm_insns_count as usize);
Expand Down Expand Up @@ -695,13 +725,6 @@ pub extern "C" fn rb_yjit_count_side_exit_op(exit_pc: *const VALUE) -> *const VA
return exit_pc;
}

// Get the size of global allocations in Rust.
#[cfg(feature="stats")]
fn global_allocation_size() -> usize {
let stats = GLOBAL_ALLOCATOR.stats();
stats.bytes_allocated.saturating_sub(stats.bytes_deallocated)
}

/// Measure the time taken by func() and add that to yjit_compile_time.
pub fn with_compile_time<F, R>(func: F) -> R where F: FnOnce() -> R {
let start = Instant::now();
Expand Down

0 comments on commit 5d3b4ea

Please sign in to comment.