From 7db759d358906733801aca4c3b1f5cb26242e478 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 16 Dec 2013 19:54:22 +0100 Subject: [PATCH] Some more progress on my experiments here. Still waiting for the latest variant of cheney to build (or rather, the rust libstd changes it is based upon). But I want to checkpoint and go home. --- Makefile | 2 +- cheney-play.rs | 67 +++++++++++++++++++++++++++++++++++++++----------- sro-play.rs | 29 +++++++++++++--------- 3 files changed, 72 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index 1b05830eb633a..937a9af6e4b08 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ BUILD_DIR=./objdir-dbgopt RUSTC=$(BUILD_DIR)/x86_64-apple-darwin/stage2/bin/rustc cheney-test: cheney-play-debug cheney-play - ./cheney-play + RUST_LOG=cheney-play ./cheney-play sro-test: sro-play-debug sro-play ./sro-play-debug diff --git a/cheney-play.rs b/cheney-play.rs index 6e75ae8b2db74..c236049605eef 100644 --- a/cheney-play.rs +++ b/cheney-play.rs @@ -1,18 +1,18 @@ #[feature(managed_boxes)]; - +#[allow(dead_code)]; // reenable check after done with dev. #[allow(unused_imports)]; use std::cast; use std::mem; use std::ptr; -use std::rt::local_heap::{Box}; +use RawBox = std::unstable::raw::Box; use std::rt::global_heap; use std::unstable::intrinsics; use std::unstable::intrinsics::{TyDesc}; // Reminder: -// struct Box { refc: uint, desc: *TyDesc, links: Lnx, data: T } -// where -// struct Lnx { prev: *mut Box, next: *mut Box } +// struct Box { +// ref_count: uint, type_desc: *TyDesc, +// prev: *mut Box, next: *mut Box, data: T } /// A Span holds the span `[start, limit)` for contiguous area of memory. struct Span { @@ -22,12 +22,15 @@ struct Span { impl Span { fn new(start: *uint, limit: *uint) -> Span{ - Span{ start: start, limit: limit } + let ret = Span{ start: start, limit: limit }; + debug!("Span::new({}, {})", start, limit); + ret } fn tup(&self) -> (*uint, *uint) { (self.start, self.limit) } fn from((start, limit): (*uint, *uint)) -> Span { Span::new(start, limit) } fn size_bytes(&self) -> uint { (self.limit as uint) - (self.start as uint) } fn can_fit(&self, bytes: uint) -> bool { bytes <= self.size_bytes() } + fn would_exhaust(&self, bytes: uint) -> bool { ! self.can_fit(bytes) } unsafe fn shift_start(&mut self, bytes: uint) { assert!(self.can_fit(bytes)); assert!(bytes as int >= 0); @@ -62,11 +65,16 @@ impl Chunk { assert!(size >= mem::size_of::>()); assert!(size >= mem::size_of::>()); + let word_size = mem::size_of::(); + if 0 != size % word_size { + fail!("chunks must be multiples of machine words."); + } + unsafe { let chunk_mem = global_heap::malloc_raw(size); let start : *uint = cast::transmute(chunk_mem); assert!((size as int) >= 0); - let limit : *uint = ptr::offset(start, size as int); + let limit : *uint = ptr::offset(start, (size / word_size) as int); let block : *mut BigBlock = cast::transmute(start); (*block).next = ptr::null(); (*block).limit = limit; @@ -90,6 +98,18 @@ impl Chunk { let limit = (*b).limit; Span::new(start, limit) } + + unsafe fn free_all(&mut self) { + let mut ptr = self.span.start; + let mut next = self.next; + loop { + global_heap::free_raw(ptr); + match next { + None => break, + Some(p) => { ptr = (*p).span.start; next = (*p).next; } + } + } + } } /// A Block is a contiguous slice of memory within a Chunk. When @@ -158,18 +178,24 @@ impl Gc { } pub fn alloc(&mut self, arg:T) -> @T { - #[allow(unused_variable)]; - unsafe { let tydesc = intrinsics::get_tydesc::(); let obj = self.alloc_ty_instance(tydesc); - fail!("GC::alloc not yet implemented"); + let obj : *mut RawBox = cast::transmute(obj); + // artificially pump up ref-count so that cheney will manage this object. + (*obj).ref_count += 1; + (*obj).type_desc = tydesc; + (*obj).prev = ptr::mut_null(); + (*obj).next = ptr::mut_null(); + (*obj).data = arg; + let obj : @T = cast::transmute(obj); + return obj; } } unsafe fn alloc_ty_instance(&mut self, tydesc: *TyDesc) -> *uint { let total_size = global_heap::get_box_size((*tydesc).size, (*tydesc).align); - if self.avail.can_fit(total_size) { + if self.avail.would_exhaust(total_size) { // TODO: if total_size is large enough, consider // allocating a separate chunk for it rather than // immediately jumping into a Gc attempt. @@ -186,9 +212,11 @@ impl Gc { fn fill_remaining_space(&mut self) { // TODO: inject placeholder object with fixed-size header as // to spend O(1) effort rather than O(|remainingspace|). + let mut a = self.avail.start; + let lim = self.avail.limit; + println!("fill_remaining_space: a: {} lim: {} lim-a: {} bytes", + a, lim, (lim as uint) - (a as uint)); unsafe { - let mut a = self.avail.start; - let lim = self.avail.limit; while a < lim { { let a : *mut uint = cast::transmute(a); @@ -204,7 +232,7 @@ impl Gc { #[allow(unused_variable)]; let owned_objects_to_scan : ~[*()] = ~[]; - let pinned_shared_to_scan : ~[*Box] = ~[]; + let pinned_shared_to_scan : ~[*RawBox<()>] = ~[]; let scan_ptr : *uint; let to_ptr : *uint; let limit : *uint; @@ -272,3 +300,14 @@ fn main() { let i3 = gc.alloc::(3); println!("i3: {:?}", i3); } + +impl Drop for Gc { + fn drop(&mut self) { + unsafe { + self.normal_chunks.free_all(); + match self.large_objects.take() { + None => {}, Some(c) => c.free_all(), + } + } + } +} diff --git a/sro-play.rs b/sro-play.rs index 0790e4ff67b87..9795d55ece288 100644 --- a/sro-play.rs +++ b/sro-play.rs @@ -4,6 +4,7 @@ use std::cast; use std::libc; use std::local_data; +use std::os; use std::ptr; use std::rt::local_heap; use std::rt::local_heap::{MemoryRegion, Box}; @@ -161,23 +162,29 @@ extern "C" fn do_walk(mut regs: &mut Registers, mut ctxt: &mut ctxt, _:*()) { println!("got to do_walk"); } - fn traverse_local_heap_structure() { - Local::borrow(|task: &mut Task| { + traverse_local_heap_structure(); - struct MyLocalHeap { // XXX keep synced w/ local_heap::LocalHeap - memory_region: MemoryRegion, - poison_on_free: bool, - live_allocs: *mut Box, - } + fn traverse_local_heap_structure() { + let mut borrowed_task = Local::borrow(None::); + { + let task = borrowed_task.get(); + struct MyLocalHeap { // XXX keep synced w/ local_heap::LocalHeap + memory_region: MemoryRegion, + poison_on_free: bool, + live_allocs: *mut Box, + } - let hp : &MyLocalHeap = unsafe { cast::transmute(&task.heap) }; - println!("hp: {:?}", hp); - }); + let hp : &MyLocalHeap = unsafe { cast::transmute(&task.heap) }; + println!("hp: {:?}", hp); + } } } fn main() { println!("Hello world."); - let ctxt = ~ctxt { verbose: false, id: 100, info: () }; + let mut ctxt = ~ctxt { verbose: false, id: 100, info: () }; + if os::args().contains(&~"--verbose") { + ctxt.verbose = true; + } walk_managed(ctxt); }