1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
use std::collections::HashSet;
use std::ffi::CString;
use std::sync::atomic::AtomicBool;
use std::sync::Mutex;
use std::thread::JoinHandle;
use mmtk::util::ObjectReference;
use mmtk::MMTK;
use crate::abi;
use crate::abi::RubyBindingOptions;
use crate::pinning_registry::PinningRegistry;
use crate::weak_proc::WeakProcessor;
use crate::Ruby;
pub struct RubyBindingFast {
pub suffix_size: usize,
}
impl Default for RubyBindingFast {
fn default() -> Self {
Self::new()
}
}
impl RubyBindingFast {
pub const fn new() -> Self {
Self { suffix_size: 0 }
}
}
pub struct RubyConfiguration {
pub gc_enabled: AtomicBool,
}
impl Default for RubyConfiguration {
fn default() -> Self {
Self::new()
}
}
impl RubyConfiguration {
pub const fn new() -> Self {
Self {
// Mimic the old behavior when the gc_enabled flag was in mmtk-core.
// We may refactor it so that it is false by default.
gc_enabled: AtomicBool::new(true),
}
}
}
pub struct RubyBinding {
pub mmtk: &'static MMTK<Ruby>,
pub options: RubyBindingOptions,
pub upcalls: *const abi::RubyUpcalls,
pub plan_name: Mutex<Option<CString>>,
pub weak_proc: WeakProcessor,
pub pinning_registry: PinningRegistry,
pub gc_thread_join_handles: Mutex<Vec<JoinHandle<()>>>,
pub wb_unprotected_objects: Mutex<HashSet<ObjectReference>>,
}
unsafe impl Sync for RubyBinding {}
unsafe impl Send for RubyBinding {}
impl RubyBinding {
pub fn new(
mmtk: &'static MMTK<Ruby>,
binding_options: &RubyBindingOptions,
upcalls: *const abi::RubyUpcalls,
) -> Self {
unsafe {
crate::BINDING_FAST.suffix_size = binding_options.suffix_size;
}
Self {
mmtk,
options: binding_options.clone(),
upcalls,
plan_name: Mutex::new(None),
weak_proc: WeakProcessor::new(),
pinning_registry: PinningRegistry::new(),
gc_thread_join_handles: Default::default(),
wb_unprotected_objects: Default::default(),
}
}
pub fn upcalls(&self) -> &'static abi::RubyUpcalls {
unsafe { &*self.upcalls as &'static abi::RubyUpcalls }
}
pub fn get_plan_name_c(&self) -> *const libc::c_char {
let mut plan_name = self.plan_name.lock().unwrap();
if plan_name.is_none() {
let name_string = format!("{:?}", *self.mmtk.get_options().plan);
let c_string = CString::new(name_string)
.unwrap_or_else(|e| panic!("Failed converting plan name to CString: {e}"));
*plan_name = Some(c_string);
}
plan_name.as_deref().unwrap().as_ptr()
}
pub fn join_all_gc_threads(&self) {
let handles = {
let mut guard = self.gc_thread_join_handles.lock().unwrap();
std::mem::take(&mut *guard)
};
debug!("Joining GC threads...");
let total = handles.len();
let mut joined = 0;
for handle in handles {
handle.join().unwrap();
joined += 1;
debug!("{joined}/{total} GC threads joined.");
}
}
pub fn register_wb_unprotected_object(&self, object: ObjectReference) {
debug!("Registering WB-unprotected object: {object}");
let mut objects = self.wb_unprotected_objects.lock().unwrap();
objects.insert(object);
}
pub fn object_wb_unprotected_p(&self, object: ObjectReference) -> bool {
let objects = self.wb_unprotected_objects.lock().unwrap();
objects.contains(&object)
}
}
|