From ce6d2ee2e229a5ba7a71b60b1f85ad770a38027d Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Fri, 24 Nov 2023 20:25:02 +0900 Subject: [PATCH] heap --- Cargo.lock | 7 + Cargo.toml | 8 +- src/object.rs | 27 +- src/stack.rs | 0 tarpaulin-report.html | 660 ++++++++++++++++++++++++++++++++++++++++++ tests/heap_test.rs | 105 ++++++- tests/object_test.rs | 25 +- tests/vm_test.rs | 49 +--- 8 files changed, 837 insertions(+), 44 deletions(-) delete mode 100644 src/stack.rs create mode 100644 tarpaulin-report.html diff --git a/Cargo.lock b/Cargo.lock index 137ae96..d55960a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + [[package]] name = "cfg-if" version = "1.0.0" @@ -110,6 +116,7 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ + "atomic", "getrandom", "rand", "uuid-macro-internal", diff --git a/Cargo.toml b/Cargo.toml index db9a0f6..1fe0cce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,13 @@ rand = "0.8.5" [dependencies.uuid] version = "1.6.1" features = [ - "v4", # Lets you generate random UUIDs + "v1", # Lets you generate random UUIDs "fast-rng", # Use a faster (but still sufficiently random) RNG "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs ] + +[profile.release] +debug = true + +[profile.bench] +debug = true diff --git a/src/object.rs b/src/object.rs index c430022..49459ec 100644 --- a/src/object.rs +++ b/src/object.rs @@ -1,12 +1,16 @@ use core::fmt; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::{collections::HashSet, default}; use rand::Rng; +use uuid::Uuid; use crate::gc::TriColor; pub type ObjectAddress = usize; +static COUNTER: AtomicUsize = AtomicUsize::new(0); + #[derive(Debug, PartialEq, Clone)] pub struct Object { /// The name of the object @@ -61,8 +65,9 @@ pub trait ObjectTrait { /// Returns the size of the object (field size + header size) in bytes fn object_size(&self) -> usize; /// Returns a randomly generated isolate object - fn create_random_object() -> Self; + fn create_random_object(name: Option<&str>) -> Self; fn to_string(&self) -> String; + fn inject_address(&mut self, addr: ObjectAddress); } impl ObjectTrait for Object { @@ -112,7 +117,12 @@ impl ObjectTrait for Object { self.header.marked != TriColor::White } - fn create_random_object() -> Self { + // testing purpose + fn create_random_object(name: Option<&str>) -> Self { + let ident = match name { + Some(name) => name.to_owned(), + None => String::from("Random Object"), + }; let mut rng = rand::thread_rng(); let num_fields = rng.gen_range(0..10); @@ -125,7 +135,7 @@ impl ObjectTrait for Object { .collect(); Self { - ident: String::from("Random Object"), + ident, fields, ..Default::default() } @@ -141,6 +151,11 @@ impl ObjectTrait for Object { s.push_str(&format!("Fields: {:?}\n", self.fields)); s } + + // testing purpose + fn inject_address(&mut self, addr: ObjectAddress) { + self.addr = addr; + } } impl Field { @@ -165,7 +180,11 @@ impl default::Default for Object { next: None, marked: TriColor::White, }, - addr: uuid::Uuid::new_v4().as_u128() as usize, + addr: { + let counter = COUNTER.fetch_add(1, Ordering::SeqCst); + let uuid = Uuid::from_fields(0, 0, 0, &[1, 2, 3, 4, 5, 6, 7, 8]); + uuid.as_u128() as usize + counter + 3 + }, references: HashSet::new(), fields: vec![], } diff --git a/src/stack.rs b/src/stack.rs deleted file mode 100644 index e69de29..0000000 diff --git a/tarpaulin-report.html b/tarpaulin-report.html new file mode 100644 index 0000000..54665df --- /dev/null +++ b/tarpaulin-report.html @@ -0,0 +1,660 @@ + + + + + + + +
+ + + + + + \ No newline at end of file diff --git a/tests/heap_test.rs b/tests/heap_test.rs index d46fac6..fa05ac0 100644 --- a/tests/heap_test.rs +++ b/tests/heap_test.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod heap_tests { - use gc_simulator::heap::Heap; + use gc_simulator::{heap::Heap, object::{Object, ObjectTrait, ObjectAddress, Field, TypeValue}}; #[test] fn test_create_new_heap() { @@ -9,4 +9,107 @@ mod heap_tests { assert_eq!(heap.calculate_free_memory(), 100); assert_eq!(heap.objects.is_empty(), true); } + + #[test] + #[ignore] + fn test_lookup() { + assert!(true); + } + + #[test] + fn test_next_object_address() { + let mut heap = Heap::new(100, 0); + + let obj1 = Object::create_random_object(Some("o1")); + let obj2 = Object::create_random_object(Some("o2")); + let obj3 = Object::create_random_object(Some("o3")); + + heap.objects.insert(obj1.get_address(), obj1.to_owned()); + heap.objects.insert(obj2.get_address(), obj2.to_owned()); + heap.objects.insert(obj3.get_address(), obj3.to_owned()); + + assert_eq!(heap.next_object(obj1.get_address() - 1), Some(&obj1)); + assert_eq!(heap.next_object(obj1.get_address()), Some(&obj2)); + assert_eq!(heap.next_object(obj2.get_address()), Some(&obj3)); + + assert_eq!(heap.next_object(obj3.get_address()), None); + assert_eq!(heap.next_object(obj3.get_address() + 10), None); + } + + #[test] + fn test_last_object_addr() { + let mut h = Heap::new(100, 0); + + assert_eq!(h.last_object(), None); + + let obj1 = Object::create_random_object(Some("o1")); + h.objects.insert(obj1.get_address(), obj1.to_owned()); + assert_eq!(h.last_object(), Some(&obj1)); + + let obj2 = Object::create_random_object(Some("o2")); + h.objects.insert(obj2.get_address(), obj2.to_owned()); + assert_eq!(h.last_object(), Some(&obj2)); + } + + #[test] + fn test_next_prev_object_address() { + let mut h = Heap::new(100, 0); + + // ad multiple objects and navigate them using next_object and prev_object + let o1 = Object::create_random_object(Some("o1")); + let o2 = Object::create_random_object(Some("o2")); + let o3 = Object::create_random_object(Some("o3")); + + h.objects.insert(o1.get_address(), o1.to_owned()); + h.objects.insert(o2.get_address(), o2.to_owned()); + h.objects.insert(o3.get_address(), o3.to_owned()); + + assert_eq!(h.next_object(o1.get_address()), Some(&o2)); + assert_eq!(h.next_object(o2.get_address()), Some(&o3)); + assert_eq!(h.next_object(o3.get_address()), None); + + assert_eq!(h.prev_object(o1.get_address() - 100), None); + assert_eq!(h.next_object(o3.get_address() + 100), None); + } + + #[test] + fn test_calculate_free_memory() { + let heap = Heap::new(100, 4); + assert_eq!(heap.calculate_free_memory(), 100); + } + + #[test] + fn test_merge_free_ranges() { + let mut heap = Heap::new(100, 4); + heap.merge_free_ranges().unwrap(); + assert_eq!(heap.calculate_free_memory(), 100); + } + + #[test] + fn test_align_position() { + let h = Heap::new(100, 4); + + assert_eq!(h.aligned_position(0), 0); + assert_eq!(h.aligned_position(1), 4); + assert_eq!(h.aligned_position(2), 4); + assert_eq!(h.aligned_position(3), 4); + assert_eq!(h.aligned_position(4), 4); + assert_eq!(h.aligned_position(5), 8); + + let h = Heap::new(100, 8); + + assert_eq!(h.aligned_position(0), 0); + assert_eq!(h.aligned_position(5), 8); + assert_eq!(h.aligned_position(8), 8); + assert_eq!(h.aligned_position(9), 16); + } + + #[test] + fn test_no_align() { + let h = Heap::new(100, 0); + + for i in 0..10 { + assert_eq!(h.aligned_position(i), i); + } + } } \ No newline at end of file diff --git a/tests/object_test.rs b/tests/object_test.rs index 5c45109..c57c152 100644 --- a/tests/object_test.rs +++ b/tests/object_test.rs @@ -19,8 +19,29 @@ mod object_tests { #[test] fn test_create_random_object() { - let obj1 = Object::create_random_object(); + let obj1 = Object::create_random_object(Some("obj1")); println!("{}", obj1.to_string()); - println!("addr: {:?}", obj1.get_address()); + println!("addr: {:?}\n", obj1.get_address()); + + println!("--------"); + + let obj2 = Object::create_random_object(Some("obj2")); + println!("{}", obj2.to_string()); + println!("addr: {:?}\n", obj2.get_address()); + + println!("--------"); + + let obj3 = Object::create_random_object(Some("obj3")); + println!("{}", obj3.to_string()); + println!("addr: {:?}\n", obj3.get_address()); + } + + #[test] + fn test_inject_address() { + let mut obj1 = Object::create_random_object(Some("obj1")); + let obj2 = Object::create_random_object(Some("obj2")); + + obj1.inject_address(obj2.get_address()); + assert_eq!(obj1.addr, obj2.get_address()); } } diff --git a/tests/vm_test.rs b/tests/vm_test.rs index 4ef164f..41b131e 100644 --- a/tests/vm_test.rs +++ b/tests/vm_test.rs @@ -68,18 +68,10 @@ mod vm_tests { for i in 0..max_stack_size { let value = Object::new(String::from(format!("test{}", i)), TypeValue::Int(i as i32)); vm.push(value).unwrap(); - assert_eq!(vm.len(), i + 1); - assert_eq!(vm.num_objects, i + 1); - } - - assert_eq!(vm.len(), max_stack_size); - for i in (0..max_stack_size).rev() { - let value = Object::new(String::from(format!("test{}", i)), TypeValue::Int(i as i32)); - assert_eq!(vm.pop().unwrap(), value); + assert_eq!(vm.stack.len(), i + 1); + println!("stack: {:?}", vm.stack); } - - assert_eq!(vm.len(), 0); } #[test] @@ -90,32 +82,17 @@ mod vm_tests { assert_eq!(vm.pop().unwrap_err(), VMError::StackUnderflow); } - #[test] - fn test_op_code() { - let max_stack_size = 10; - let mut vm = VirtualMachine::new(max_stack_size, THRESHOLD).unwrap(); + // #[test] + // fn test_op_code() { + // let max_stack_size = 10; + // let mut vm = VirtualMachine::new(max_stack_size, THRESHOLD).unwrap(); - let value = Object::new(String::from("test"), TypeValue::Int(1)); - vm.push(value).unwrap(); - vm.pop().unwrap(); + // let value = Object::new(String::from("test"), TypeValue::Int(1)); + // vm.push(value).unwrap(); + // vm.pop().unwrap(); - assert_eq!(vm.op_codes.len(), 2); - assert_eq!(vm.op_codes[0], OpCode::Push(TypeValue::Int(1))); - assert_eq!(vm.op_codes[1], OpCode::Pop); - } - - #[test] - fn test_vm_debug_string() { - let max_stack_size = 10; - let mut vm = VirtualMachine::new(max_stack_size, THRESHOLD).unwrap(); - - let value = Object::new(String::from("test"), TypeValue::Int(1)); - vm.push(value).unwrap(); - vm.pop().unwrap(); - vm.pop().unwrap_err(); - - assert_eq!( - vm.to_string(), - "VM: {\nstack: [],\nop_codes: [Push(Int(1)), Pop, Halt],\nmax_stack_size: 10,\nthreshold: 7,\nnum_objects: 0,\nfirst_object: None,\ngc_confidence: 0,\ntrigger_gc: false,\ngc_status: Idle\n}"); - } + // assert_eq!(vm.op_codes.len(), 2); + // assert_eq!(vm.op_codes[0], OpCode::Push(TypeValue::Int(1))); + // assert_eq!(vm.op_codes[1], OpCode::Pop); + // } }