binary trees

This commit is contained in:
playX18 2025-02-09 21:05:13 +07:00
parent 1c9d620627
commit d84b1968d5
16 changed files with 521 additions and 139 deletions

285
Cargo.lock generated
View file

@ -11,6 +11,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
version = "0.6.18"
@ -107,6 +113,12 @@ dependencies = [
"git2",
]
[[package]]
name = "bumpalo"
version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "bytemuck"
version = "1.21.0"
@ -133,6 +145,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.12"
@ -150,6 +168,33 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "ciborium"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "clap"
version = "4.5.28"
@ -202,6 +247,42 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "criterion"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"is-terminal",
"itertools 0.10.5",
"num-traits",
"once_cell",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools 0.10.5",
]
[[package]]
name = "crossbeam"
version = "0.8.4"
@ -258,6 +339,12 @@ version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
[[package]]
name = "delegate"
version = "0.12.0"
@ -390,6 +477,16 @@ dependencies = [
"url",
]
[[package]]
name = "half"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
"cfg-if",
"crunchy",
]
[[package]]
name = "heck"
version = "0.5.0"
@ -570,6 +667,15 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.12.1"
@ -579,6 +685,12 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "jobserver"
version = "0.1.32"
@ -588,6 +700,16 @@ dependencies = [
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -678,7 +800,7 @@ dependencies = [
"enum-map",
"env_logger",
"is-terminal",
"itertools",
"itertools 0.12.1",
"lazy_static",
"libc",
"log",
@ -806,6 +928,12 @@ version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "oorandom"
version = "11.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
[[package]]
name = "parking_lot"
version = "0.12.3"
@ -841,6 +969,34 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "plotters"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
[[package]]
name = "plotters-svg"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
dependencies = [
"plotters-backend",
]
[[package]]
name = "portable-atomic"
version = "1.10.0"
@ -1008,6 +1164,21 @@ version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -1040,6 +1211,18 @@ dependencies = [
"syn 2.0.98",
]
[[package]]
name = "serde_json"
version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
@ -1155,6 +1338,16 @@ dependencies = [
"zerovec",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "unicode-ident"
version = "1.0.16"
@ -1210,9 +1403,12 @@ dependencies = [
"bytemuck",
"cfg-if",
"clap",
"criterion",
"easy-bitfield",
"env_logger",
"errno",
"libc",
"log",
"mmtk",
"parking_lot",
"rand",
@ -1228,6 +1424,16 @@ dependencies = [
"syn 2.0.98",
]
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.13.3+wasi-0.2.2"
@ -1237,6 +1443,74 @@ dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn 2.0.98",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.98",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
dependencies = [
"unicode-ident",
]
[[package]]
name = "web-sys"
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -1253,6 +1527,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View file

@ -2,3 +2,6 @@
members = ["vmkit", "vmkit-proc"]
default-members = ["vmkit"]
resolver = "2"
[workspace.example]
members = ["examples/*"]

View file

@ -9,8 +9,10 @@ bytemuck = "1.21.0"
cfg-if = "1.0.0"
clap = { version = "4.5.28", features = ["derive"] }
easy-bitfield = "0.1.0"
env_logger = "0.11.6"
errno = "0.3.10"
libc = "0.2.169"
log = "0.4.25"
mmtk = { git = "https://github.com/mmtk/mmtk-core" }
parking_lot = "0.12.3"
rand = "0.9.0"
@ -31,3 +33,10 @@ full-precise = []
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["everything"] }
[dev-dependencies]
criterion = "0.5.1"
[[bench]]
name = "binarytrees"
harness = false

View file

View file

@ -17,7 +17,7 @@ pub trait VirtualMachine: Sized + 'static + Send + Sync {
type Slot: SlotExtra;
const MAX_ALIGNMENT: usize = 16;
const MIN_ALIGNMENT: usize = 16;
const MIN_ALIGNMENT: usize = 8;
/// Does this VM use conservative tracing? If `true` then VM can
/// query VO-bit (valid-object bit) to check if an object is live

View file

@ -1,42 +1,72 @@
use easy_bitfield::{FromBitfield, ToBitfield};
use mmtk::{util::options::PlanSelector, vm::slot::SimpleSlot, AllocationSemantics, MMTKBuilder};
use std::mem::offset_of;
use std::sync::OnceLock;
use vmkit::{
mm::{traits::ToSlot, MemoryManager},
object_model::metadata::{GCMetadata, Metadata, Trace},
mm::{traits::Trace, MemoryManager},
object_model::{
metadata::{GCMetadata, TraceCallback},
object::VMKitObject,
},
threading::{GCBlockAdapter, Thread, ThreadContext},
VMKit, VirtualMachine,
};
struct TestContext;
const CONSERVATIVE_TRACE_NODE: bool = false;
impl ThreadContext<VM> for TestContext {
#[repr(C)]
struct Node {
left: VMKitObject,
right: VMKitObject,
i: usize,
j: usize,
}
static METADATA: GCMetadata<BenchVM> = GCMetadata {
trace: TraceCallback::TraceObject(|object, tracer| unsafe {
let node = object.as_address().as_mut_ref::<Node>();
node.left.trace_object(tracer);
node.right.trace_object(tracer);
}),
instance_size: size_of::<Node>(),
compute_size: None,
alignment: 16,
};
struct BenchVM {
vmkit: VMKit<Self>,
}
static VM: OnceLock<BenchVM> = OnceLock::new();
struct ThreadBenchContext;
impl ThreadContext<BenchVM> for ThreadBenchContext {
fn new(_: bool) -> Self {
Self
}
fn save_thread_state(&self) {}
fn scan_roots(&self, _factory: impl mmtk::vm::RootsWorkFactory<<VM as VirtualMachine>::Slot>) {}
fn scan_roots(
&self,
_factory: impl mmtk::vm::RootsWorkFactory<<BenchVM as VirtualMachine>::Slot>,
) {
}
fn scan_conservative_roots(
&self,
croots: &mut vmkit::mm::conservative_roots::ConservativeRoots,
_croots: &mut vmkit::mm::conservative_roots::ConservativeRoots,
) {
let _ = croots;
}
fn new(_collector_context: bool) -> Self {
Self
}
}
static VM_STORAGE: OnceLock<VM> = OnceLock::new();
impl VirtualMachine for VM {
const MAX_ALIGNMENT: usize = 16;
const MIN_ALIGNMENT: usize = 16;
type ThreadContext = TestContext;
type BlockAdapterList = (GCBlockAdapter, ());
type Metadata = &'static GCMetadata<VM>;
type Slot = SimpleSlot;
impl VirtualMachine for BenchVM {
type BlockAdapterList = (GCBlockAdapter, ());
type Metadata = &'static GCMetadata<Self>;
type Slot = SimpleSlot;
type ThreadContext = ThreadBenchContext;
fn get() -> &'static Self {
VM_STORAGE.get().unwrap()
VM.get().unwrap()
}
fn vmkit(&self) -> &VMKit<Self> {
@ -45,7 +75,16 @@ impl VirtualMachine for VM {
fn prepare_for_roots_re_scanning() {}
fn notify_initial_thread_scan_complete(_partial_scan: bool, _tls: mmtk::util::VMWorkerThread) {}
fn notify_initial_thread_scan_complete(partial_scan: bool, tls: mmtk::util::VMWorkerThread) {
let _ = partial_scan;
let _ = tls;
}
fn forward_weak_refs(
_worker: &mut mmtk::scheduler::GCWorker<vmkit::mm::MemoryManager<Self>>,
_tracer_context: impl mmtk::vm::ObjectTracerContext<vmkit::mm::MemoryManager<Self>>,
) {
}
fn scan_roots_in_mutator_thread(
_tls: mmtk::util::VMWorkerThread,
@ -63,105 +102,138 @@ impl VirtualMachine for VM {
>,
) {
}
fn forward_weak_refs(
_worker: &mut mmtk::scheduler::GCWorker<vmkit::mm::MemoryManager<Self>>,
_tracer_context: impl mmtk::vm::ObjectTracerContext<vmkit::mm::MemoryManager<Self>>,
) {
todo!()
}
}
struct VM {
vmkit: VMKit<Self>,
fn make_node(
thread: &Thread<BenchVM>,
left: VMKitObject,
right: VMKitObject,
i: usize,
j: usize,
) -> VMKitObject {
let node = MemoryManager::allocate(
thread,
size_of::<Node>(),
16,
&METADATA,
AllocationSemantics::Default,
);
unsafe {
node.set_field_object_no_write_barrier::<BenchVM, false>(offset_of!(Node, left), left);
node.set_field_object_no_write_barrier::<BenchVM, false>(offset_of!(Node, right), right);
node.set_field_usize::<BenchVM>(offset_of!(Node, i), i);
node.set_field_usize::<BenchVM>(offset_of!(Node, j), j);
}
node
}
static METADATA: GCMetadata<VM> = GCMetadata {
instance_size: 48,
compute_size: None,
trace: Trace::TraceObject(|object, _tracer| {
println!("tracing {}", object.as_address());
}),
alignment: 16,
};
struct FooMeta;
impl Metadata<VM> for FooMeta {
const METADATA_BIT_SIZE: usize = 56;
fn gc_metadata(&self) -> &'static GCMetadata<VM> {
&METADATA
}
fn is_object(&self) -> bool {
false
}
fn from_object_reference(_reference: mmtk::util::ObjectReference) -> Self {
unreachable!()
}
fn to_object_reference(&self) -> Option<mmtk::util::ObjectReference> {
unreachable!()
}
fn tree_size(i: usize) -> usize {
(1 << (i + 1)) - 1
}
impl ToSlot<SimpleSlot> for FooMeta {
fn to_slot(&self) -> Option<SimpleSlot> {
None
}
fn num_iters(stretch_tree_depth: usize, i: usize) -> usize {
4 + tree_size(stretch_tree_depth) / tree_size(i)
}
impl FromBitfield<u64> for FooMeta {
fn from_bitfield(_bitfield: u64) -> Self {
FooMeta
fn populate(thread: &Thread<BenchVM>, depth: usize, this_node: VMKitObject) {
let mut depth = depth;
if depth <= 0 {
return;
}
fn from_i64(_value: i64) -> Self {
FooMeta
}
depth -= 1;
this_node.set_field_object::<BenchVM, false>(
offset_of!(Node, left),
make_node(thread, VMKitObject::NULL, VMKitObject::NULL, 0, 0),
);
let left = this_node.get_field_object::<BenchVM, false>(offset_of!(Node, left));
this_node.set_field_object::<BenchVM, false>(
offset_of!(Node, right),
make_node(thread, VMKitObject::NULL, VMKitObject::NULL, 0, 0),
);
populate(
thread,
depth,
this_node.get_field_object::<BenchVM, false>(offset_of!(Node, left)),
);
populate(
thread,
depth,
this_node.get_field_object::<BenchVM, false>(offset_of!(Node, right)),
);
}
impl ToBitfield<u64> for FooMeta {
fn to_bitfield(self) -> u64 {
0
fn make_tree(thread: &Thread<BenchVM>, depth: usize) -> VMKitObject {
if depth <= 0 {
return make_node(thread, VMKitObject::NULL, VMKitObject::NULL, 0, 0);
}
fn one() -> Self {
FooMeta
}
fn zero() -> Self {
FooMeta
}
let left = make_tree(thread, depth - 1);
let right = make_tree(thread, depth - 1);
make_node(thread, left, right, 0, 0)
}
extern "C-unwind" fn handler(signum: libc::c_int) {
println!("signal {signum}");
println!("backtrace:\n{}", std::backtrace::Backtrace::force_capture());
std::process::exit(1);
fn time_construction(thread: &Thread<BenchVM>, stretch_tree_depth: usize, depth: usize) {
let i_num_iters = num_iters(stretch_tree_depth, depth);
println!("creating {} trees of depth {}", i_num_iters, depth);
let start = std::time::Instant::now();
let mut i = 0;
while i < i_num_iters {
let temp_tree = make_node(thread, VMKitObject::NULL, VMKitObject::NULL, 0, 0);
populate(thread, depth, temp_tree);
i += 1;
}
let finish = std::time::Instant::now();
println!("\tTop down construction took: {:04}ms", finish.duration_since(start).as_micros() as f64 / 1000.0);
let duration = start.elapsed();
println!("time_construction: {:?}", duration);
}
fn main() {
unsafe {
libc::signal(libc::SIGSEGV, handler as usize);
}
env_logger::init();
let mut options = MMTKBuilder::new();
options.options.plan.set(PlanSelector::StickyImmix);
options.options.gc_trigger.set(mmtk::util::options::GCTriggerSelector::DynamicHeapSize(64*1024*1024, 8*1024*1024*1024));
let vm = BenchVM {
vmkit: VMKit::new(options)
};
let mut mmtk = MMTKBuilder::new();
mmtk.options.plan.set(PlanSelector::Immix);
mmtk.options.threads.set(1);
VM_STORAGE.get_or_init(|| VM {
vmkit: VMKit::new(mmtk),
});
VM.set(vm).unwrap_or_else(|_| panic!("Failed to set VM"));
Thread::<VM>::main(TestContext, || {
let tls = Thread::<VM>::current();
let my_obj = MemoryManager::allocate(tls, 48, 16, &METADATA, AllocationSemantics::Default);
Thread::<BenchVM>::main(ThreadBenchContext, || {
let tls= Thread::<BenchVM>::current();
println!("Allocated object at {}", my_obj.as_address());
let depth = std::env::var("DEPTH").unwrap_or("18".to_string()).parse::<usize>().unwrap();
let long_lived_tree_depth = depth;
MemoryManager::<VM>::request_gc();
let stretch_tree_depth = depth + 1;
println!("stretching memory with tree of depth: {}", stretch_tree_depth);
let start = std::time::Instant::now();
make_tree(tls, stretch_tree_depth as _);
println!("creating long-lived tree of depth: {}", long_lived_tree_depth);
let long_lived_tree = make_node(tls, VMKitObject::NULL, VMKitObject::NULL, 0, 0);
populate(tls, long_lived_tree_depth as _, long_lived_tree);
let mut d = 4;
while d <= depth {
time_construction(tls, stretch_tree_depth, d);
d += 2;
}
let finish = std::time::Instant::now();
println!("total execution time: {:04}ms", finish.duration_since(start).as_micros() as f64 / 1000.0);
println!("object {} at {:p}", my_obj.as_address(), &my_obj);
});
}

View file

@ -73,11 +73,12 @@ impl<VM: VirtualMachine> MemoryManager<VM> {
#[inline]
pub extern "C-unwind" fn allocate(
thread: &Thread<VM>,
size: usize,
mut size: usize,
alignment: usize,
metadata: VM::Metadata,
mut semantics: AllocationSemantics,
) -> VMKitObject {
size += size_of::<HeapObjectHeader<VM>>();
if semantics == AllocationSemantics::Default
&& size >= thread.max_non_los_default_alloc_bytes()
{
@ -103,7 +104,6 @@ impl<VM: VirtualMachine> MemoryManager<VM> {
});
let object = VMKitObject::from_address(object_start + OBJECT_REF_OFFSET);
Self::set_vo_bit(object);
Self::refill_tlab(thread);
return object;
}

View file

@ -10,6 +10,7 @@ pub struct VMKitActivePlan<VM: VirtualMachine>(PhantomData<VM>);
impl<VM: VirtualMachine> ActivePlan<MemoryManager<VM>> for VMKitActivePlan<VM> {
fn is_mutator(tls: mmtk::util::VMThread) -> bool {
let x = Thread::<VM>::from_vm_thread(tls);
Thread::<VM>::from_vm_thread(tls).active_mutator_context()
}

View file

@ -34,7 +34,7 @@ fn is_address_maybe_unmapped(addr: Address, size: usize) -> bool {
}
pub fn aslr_vm_layout(mmtk_options: &mut Options) -> VMLayout {
let mut vm_layout = VMLayout::default();
/*let mut vm_layout = VMLayout::default();
let options = &*OPTIONS;
if options.compressed_pointers {
@ -89,7 +89,9 @@ pub fn aslr_vm_layout(mmtk_options: &mut Options) -> VMLayout {
options.max_heap_size,
));
vm_layout
vm_layout*/
VMLayout::default()
}

View file

@ -3,7 +3,7 @@ use std::marker::PhantomData;
use crate::{
mm::MemoryManager,
object_model::{
metadata::{Metadata, Trace},
metadata::{Metadata, TraceCallback},
object::VMKitObject,
},
options::OPTIONS,
@ -57,11 +57,11 @@ impl<VM: VirtualMachine> Scanning<MemoryManager<VM>> for VMKitScanning<VM> {
let gc_metadata = metadata.gc_metadata();
let trace = &gc_metadata.trace;
match trace {
Trace::ScanSlots(fun) => {
TraceCallback::ScanSlots(fun) => {
fun(object, slot_visitor);
}
Trace::None => (),
Trace::TraceObject(_) => {
TraceCallback::None => (),
TraceCallback::TraceObject(_) => {
unreachable!("TraceObject is not supported for scanning");
}
}
@ -77,7 +77,7 @@ impl<VM: VirtualMachine> Scanning<MemoryManager<VM>> for VMKitScanning<VM> {
let gc_metadata = metadata.gc_metadata();
let trace = &gc_metadata.trace;
match trace {
Trace::ScanSlots(fun) => {
TraceCallback::ScanSlots(fun) => {
// wrap object tracer in a trait that implements SlotVisitor
// but actually traces the object directly.
let mut visitor = TraceSlotVisitor::<VM, OT> {
@ -86,8 +86,8 @@ impl<VM: VirtualMachine> Scanning<MemoryManager<VM>> for VMKitScanning<VM> {
};
fun(object, &mut visitor);
}
Trace::None => (),
Trace::TraceObject(fun) => {
TraceCallback::None => (),
TraceCallback::TraceObject(fun) => {
fun(object, object_tracer);
}
}
@ -123,7 +123,7 @@ impl<VM: VirtualMachine> Scanning<MemoryManager<VM>> for VMKitScanning<VM> {
) -> bool {
let object = VMKitObject::from(object);
let metadata = object.header::<VM>().metadata();
matches!(metadata.gc_metadata().trace, Trace::ScanSlots(_))
matches!(metadata.gc_metadata().trace, TraceCallback::ScanSlots(_))
&& (!metadata.is_object() || metadata.to_slot().is_some())
}

View file

@ -18,9 +18,9 @@ impl TLAB {
let aligned_size = raw_align_up(size, alignment);
let result = self.cursor.align_up(alignment);
if result + aligned_size > self.limit {
return Address::ZERO;
} else {
self.cursor = result.add(aligned_size);
return result;
}

View file

@ -24,15 +24,15 @@ pub trait ToSlot<SL: Slot> {
}
pub trait Trace {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer);
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer);
}
pub trait Scan<SL: Slot> {
fn scan_object(&self, visitor: &mut impl SlotVisitor<SL>);
fn scan_object(&self, visitor: &mut dyn SlotVisitor<SL>);
}
impl Trace for VMKitObject {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
if self.is_null() {
return;
}
@ -45,7 +45,7 @@ impl Trace for VMKitObject {
}
impl<T: Trace, VM: VirtualMachine> Trace for InternalPointer<T, VM> {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
#[cfg(feature = "cooperative")]
{
assert!(
@ -72,7 +72,7 @@ impl<T: Trace, VM: VirtualMachine> Trace for InternalPointer<T, VM> {
}
impl<SL: Slot + SlotExtra> Scan<SL> for VMKitObject {
fn scan_object(&self, visitor: &mut impl SlotVisitor<SL>) {
fn scan_object(&self, visitor: &mut dyn SlotVisitor<SL>) {
if let Some(slot) = self.to_slot() {
visitor.visit_slot(slot);
}
@ -167,7 +167,7 @@ macro_rules! impl_prim {
}
impl<SL: Slot> Scan<SL> for $t {
fn scan_object(&self, visitor: &mut impl SlotVisitor<SL>) {
fn scan_object(&self, visitor: &mut dyn SlotVisitor<SL>) {
let _ = visitor;
}
}
@ -179,7 +179,7 @@ macro_rules! impl_prim {
}
impl Trace for $t {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
let _ = tracer;
}
}
@ -210,7 +210,7 @@ impl<T: SupportsEnqueuing, U: SupportsEnqueuing> SupportsEnqueuing for Result<T,
}
impl<T: Trace> Trace for Option<T> {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
if let Some(value) = self {
value.trace_object(tracer);
}
@ -218,7 +218,7 @@ impl<T: Trace> Trace for Option<T> {
}
impl<T: Trace> Trace for Vec<T> {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
for value in self {
value.trace_object(tracer);
}
@ -226,7 +226,7 @@ impl<T: Trace> Trace for Vec<T> {
}
impl<T: Trace, const N: usize> Trace for [T; N] {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
for value in self {
value.trace_object(tracer);
}
@ -234,13 +234,13 @@ impl<T: Trace, const N: usize> Trace for [T; N] {
}
impl<T: Trace> Trace for Box<T> {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
(**self).trace_object(tracer);
}
}
impl<SL: Slot, T: Scan<SL>> Scan<SL> for Vec<T> {
fn scan_object(&self, visitor: &mut impl SlotVisitor<SL>) {
fn scan_object(&self, visitor: &mut dyn SlotVisitor<SL>) {
for value in self {
value.scan_object(visitor);
}
@ -248,7 +248,7 @@ impl<SL: Slot, T: Scan<SL>> Scan<SL> for Vec<T> {
}
impl<SL: Slot, T: Scan<SL>, const N: usize> Scan<SL> for [T; N] {
fn scan_object(&self, visitor: &mut impl SlotVisitor<SL>) {
fn scan_object(&self, visitor: &mut dyn SlotVisitor<SL>) {
for value in self {
value.scan_object(visitor);
}
@ -260,7 +260,7 @@ impl<T, VM: VirtualMachine> SupportsEnqueuing for FatInternalPointer<T, VM> {
}
impl<T, VM: VirtualMachine, SL: Slot + SlotExtra> Scan<SL> for FatInternalPointer<T, VM> {
fn scan_object(&self, visitor: &mut impl SlotVisitor<SL>) {
fn scan_object(&self, visitor: &mut dyn SlotVisitor<SL>) {
visitor.visit_slot(self.object().to_slot().expect("never fails"));
}
}
@ -272,14 +272,14 @@ impl<T, VM: VirtualMachine, SL: Slot + SlotExtra> ToSlot<SL> for FatInternalPoin
}
impl<T, VM: VirtualMachine> Trace for FatInternalPointer<T, VM> {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
self.object().trace_object(tracer);
}
}
impl Trace for VMKitNarrow {
fn trace_object(&mut self, tracer: &mut impl ObjectTracer) {
fn trace_object(&mut self, tracer: &mut dyn ObjectTracer) {
let mut object = self.to_object();
object.trace_object(tracer);
*self = VMKitNarrow::encode(object);
@ -287,7 +287,7 @@ impl Trace for VMKitNarrow {
}
impl<SL: SlotExtra> Scan<SL> for VMKitNarrow {
fn scan_object(&self, visitor: &mut impl SlotVisitor<SL>) {
fn scan_object(&self, visitor: &mut dyn SlotVisitor<SL>) {
let slot = SL::from_narrow(self);
visitor.visit_slot(slot);
}

View file

@ -132,6 +132,7 @@ impl<VM: VirtualMachine> ObjectModel<MemoryManager<VM>> for VMKitObjectModel<VM>
}
impl<VM: VirtualMachine> VMKitObjectModel<VM> {
fn move_object(from_obj: VMKitObject, mut to: MoveTarget, num_bytes: usize) -> VMKitObject {
log::trace!("move_object: from_obj: {}, to: {}", from_obj.as_address(), to);
let mut copy_bytes = num_bytes;
let mut obj_ref_offset = OBJECT_REF_OFFSET;
let hash_state = from_obj.header::<VM>().hash_state();

View file

@ -10,14 +10,14 @@ use super::object::VMKitObject;
#[repr(C)]
pub struct GCMetadata<VM: VirtualMachine> {
pub trace: Trace<VM>,
pub trace: TraceCallback<VM>,
pub instance_size: usize,
pub compute_size: Option<fn(VMKitObject) -> usize>,
pub alignment: usize,
}
#[derive(Debug)]
pub enum Trace<VM: VirtualMachine> {
pub enum TraceCallback<VM: VirtualMachine> {
ScanSlots(fn(VMKitObject, &mut dyn SlotVisitor<VM::Slot>)),
TraceObject(fn(VMKitObject, &mut dyn ObjectTracer)),
None,

View file

@ -1,3 +1,5 @@
use std::fmt;
use crate::mm::traits::SlotExtra;
use crate::threading::Thread;
use crate::{mm::MemoryManager, VirtualMachine};
@ -514,6 +516,15 @@ pub enum MoveTarget {
ToObject(VMKitObject),
}
impl fmt::Display for MoveTarget {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MoveTarget::ToAddress(addr) => write!(f, "ToAddress({})", addr),
MoveTarget::ToObject(obj) => write!(f, "ToObject({})", obj.as_address()),
}
}
}
/// Narrow pointer to an object. This is used when pointer compression
/// is enabled.
#[repr(transparent)]

View file

@ -12,7 +12,7 @@ pub struct Options {
#[clap(long, default_value_t = 1024)]
pub interior_pointer_max_bytes: usize,
#[clap(long, default_value_t = true)]
#[clap(long, default_value_t = false)]
pub aslr: bool,
#[clap(long, default_value_t = true)]