Skip to content

Commit ce79a56

Browse files
committed
GC refactoring for closures
1 parent cdbf175 commit ce79a56

File tree

5 files changed

+90
-48
lines changed

5 files changed

+90
-48
lines changed

src/closure.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use crate::ast::FunId;
2+
use crate::vm::Value;
3+
use crate::alloc::Alloc;
4+
5+
pub struct Closure
6+
{
7+
pub fun_id: FunId,
8+
slots: *mut [Value],
9+
}
10+
11+
impl Closure
12+
{
13+
/// Allocate a new closure with a given number of slots
14+
pub fn new(fun_id: FunId, num_slots: usize, alloc: &mut Alloc) -> Result<Value, ()>
15+
{
16+
// Allocate the slots for the closure
17+
let slots = alloc.alloc_table::<Value>(num_slots)?;
18+
19+
// Create the closure struct
20+
let obj = Closure { fun_id, slots };
21+
22+
// Allocate the Object struct itself
23+
let obj_ptr = alloc.alloc(obj)?;
24+
25+
Ok(Value::Closure(obj_ptr))
26+
}
27+
28+
pub fn num_slots(&self) -> usize
29+
{
30+
unsafe { (&*self.slots).len() }
31+
}
32+
33+
// Get the given closure slot value
34+
pub fn get(&self, idx: usize) -> Value
35+
{
36+
unsafe { (*self.slots)[idx] }
37+
}
38+
39+
// Set the value of a given closure slot
40+
pub fn set(&mut self, idx: usize, val: Value)
41+
{
42+
unsafe { (*self.slots)[idx] = val }
43+
}
44+
}

src/deepcopy.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::hash::{Hash, Hasher};
33
use std::mem;
44
use crate::alloc::Alloc;
55
use crate::object::Object;
6-
use crate::vm::{Value, Closure};
6+
use crate::closure::Closure;
7+
use crate::vm::Value;
78

89
/// Custom Hash implementation for Value
910
impl Hash for Value
@@ -94,23 +95,17 @@ pub fn deepcopy(
9495
}
9596

9697
Value::Closure(p) => {
97-
let new_clos = unsafe { (*p).clone() };
98+
let clos = unsafe { &*p };
99+
let mut new_clos = Closure::new(clos.fun_id, clos.num_slots(), dst_alloc)?;
100+
let mut new_clos = new_clos.unwrap_clos();
98101

99-
for val in &new_clos.slots {
100-
push_val!(val);
101-
}
102-
103-
Value::Closure(dst_alloc.alloc(new_clos)?)
104-
}
105-
106-
Value::Dict(p) => {
107-
let new_obj = unsafe { (*p).clone() };
108-
109-
for val in new_obj.hash.values() {
110-
push_val!(val);
102+
for i in 0..clos.num_slots() {
103+
let val = clos.get(i);
104+
new_clos.set(i, val);
105+
push_val!(&val);
111106
}
112107

113-
Value::Dict(dst_alloc.alloc(new_obj)?)
108+
Value::Closure(new_clos)
114109
}
115110

116111
Value::Object(p) => {
@@ -127,6 +122,16 @@ pub fn deepcopy(
127122
Value::Object(new_obj)
128123
}
129124

125+
Value::Dict(p) => {
126+
let new_obj = unsafe { (*p).clone() };
127+
128+
for val in new_obj.hash.values() {
129+
push_val!(val);
130+
}
131+
132+
Value::Dict(dst_alloc.alloc(new_obj)?)
133+
}
134+
130135
Value::Array(p) => {
131136
let arr = unsafe { &*p };
132137
let new_arr = arr.clone(dst_alloc)?;
@@ -175,15 +180,10 @@ pub fn remap(dst_map: &mut HashMap<Value, Value>)
175180

176181
Value::Closure(p) => {
177182
let clos = unsafe { &mut **p };
178-
for slot_val in &mut clos.slots {
179-
remap_val!(slot_val);
180-
}
181-
}
182-
183-
Value::Dict(p) => {
184-
let dict = unsafe { &mut **p };
185-
for val in dict.hash.values_mut() {
186-
remap_val!(val);
183+
for i in 0..clos.num_slots() {
184+
let mut val = clos.get(i);
185+
remap_val!(&mut val);
186+
clos.set(i, val);
187187
}
188188
}
189189

@@ -196,6 +196,14 @@ pub fn remap(dst_map: &mut HashMap<Value, Value>)
196196
}
197197
}
198198

199+
200+
Value::Dict(p) => {
201+
let dict = unsafe { &mut **p };
202+
for val in dict.hash.values_mut() {
203+
remap_val!(val);
204+
}
205+
}
206+
199207
Value::Array(p) => {
200208
let arr = unsafe { &mut **p };
201209
for val in arr.items_mut() {

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod codegen;
1313
mod vm;
1414
mod alloc;
1515
mod object;
16+
mod closure;
1617
mod array;
1718
mod bytearray;
1819
mod runtime;

src/object.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,6 @@ pub struct Object
1010

1111
impl Object
1212
{
13-
/*
14-
pub fn new(class_id: ClassId, slots: *mut [Value]) -> Self
15-
{
16-
Object {
17-
class_id,
18-
slots,
19-
}
20-
}
21-
*/
22-
2313
/// Allocate a new object with a given number of slots
2414
pub fn new(class_id: ClassId, num_slots: usize, alloc: &mut Alloc) -> Result<Value, ()>
2515
{

src/vm.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::lexer::SrcPos;
77
use crate::ast::{Program, FunId, ClassId, Class};
88
use crate::alloc::Alloc;
99
use crate::object::Object;
10+
use crate::closure::Closure;
1011
use crate::array::Array;
1112
use crate::bytearray::ByteArray;
1213
use crate::codegen::CompiledFun;
@@ -173,15 +174,6 @@ pub enum Insn
173174
ret,
174175
}
175176

176-
#[derive(Clone)]
177-
pub struct Closure
178-
{
179-
pub fun_id: FunId,
180-
181-
// Captured variable slots
182-
pub slots: Vec<Value>,
183-
}
184-
185177
#[derive(Clone, Default)]
186178
pub struct Dict
187179
{
@@ -341,6 +333,14 @@ impl Value
341333
}
342334
}
343335

336+
pub fn unwrap_clos(&mut self) -> &mut Closure
337+
{
338+
match self {
339+
Value::Closure(p) => unsafe { &mut **p },
340+
_ => panic!("expected closure value but got {:?}", self)
341+
}
342+
}
343+
344344
pub fn unwrap_arr(&mut self) -> &mut Array
345345
{
346346
match self {
@@ -1680,9 +1680,8 @@ impl Actor
16801680
&mut [],
16811681
);
16821682

1683-
let clos = Closure { fun_id, slots: vec![Undef; num_slots] };
1684-
let clos_val = self.alloc.alloc(clos).unwrap();
1685-
push!(Value::Closure(clos_val));
1683+
let clos = Closure::new(fun_id, num_slots, &mut self.alloc).unwrap();
1684+
push!(clos);
16861685
}
16871686

16881687
// Set a closure slot
@@ -1693,7 +1692,7 @@ impl Actor
16931692
match clos {
16941693
Value::Closure(clos) => {
16951694
let clos = unsafe { &mut *clos };
1696-
clos.slots[idx as usize] = val;
1695+
clos.set(idx as usize, val);
16971696
}
16981697
_ => error!("clos_set", "expected closure")
16991698
}
@@ -1706,7 +1705,7 @@ impl Actor
17061705
let val = match fun {
17071706
Value::Closure(clos) => {
17081707
let clos = unsafe { &**clos };
1709-
clos.slots[idx as usize]
1708+
clos.get(idx as usize)
17101709
}
17111710
_ => error!("clos_get", "not a closure")
17121711
};

0 commit comments

Comments
 (0)