gctype.rs 4.33 KB
Newer Older
qinsoon's avatar
qinsoon committed
1 2
#![allow(dead_code)]

3 4
use std::sync::Arc;
use utils::POINTER_SIZE;
qinsoon's avatar
qinsoon committed
5 6
use utils::ByteSize;

7 8
use std::u32;
pub const GCTYPE_INIT_ID: u32 = u32::MAX;
9 10

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
11
pub struct GCType {
12
    pub id: u32,
qinsoon's avatar
qinsoon committed
13 14
    pub size: ByteSize,
    pub non_repeat_refs: Option<RefPattern>,
15
    pub repeat_refs    : Option<RepeatingRefPattern>,
qinsoon's avatar
qinsoon committed
16 17 18
}

impl GCType {
19 20 21 22 23
    pub fn new_noreftype(size: ByteSize) -> GCType {
        GCType {
            id: GCTYPE_INIT_ID,
            size: size,
            non_repeat_refs: None,
24
            repeat_refs    : None,
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
        }
    }

    pub fn new_reftype() -> GCType {
        GCType {
            id: GCTYPE_INIT_ID,
            size: POINTER_SIZE,
            non_repeat_refs: Some(RefPattern::Map{
                offsets: vec![0],
                size: POINTER_SIZE
            }),
            repeat_refs: None
        }
    }

qinsoon's avatar
qinsoon committed
40
    #[allow(unused_assignments)]
qinsoon's avatar
qinsoon committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
    pub fn gen_ref_offsets(&self) -> Vec<ByteSize> {
        let mut ret = vec![];

        let mut cur_offset = 0;

        match self.non_repeat_refs {
            Some(ref pattern) => {
                cur_offset = pattern.append_offsets(cur_offset, &mut ret);
            }
            None => {}
        }

        if self.repeat_refs.is_some() {
            let repeat_refs = self.repeat_refs.as_ref().unwrap();

            cur_offset = repeat_refs.append_offsets(cur_offset, &mut ret);
        }

        ret
    }
}

63
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
64 65 66 67 68
pub enum RefPattern {
    Map{
        offsets: Vec<ByteSize>,
        size : usize
    },
69
    NestedType(Vec<Arc<GCType>>)
qinsoon's avatar
qinsoon committed
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
}

impl RefPattern {
    pub fn append_offsets(&self, base: ByteSize, vec: &mut Vec<ByteSize>) -> ByteSize {
        match self {
            &RefPattern::Map{ref offsets, size} => {
                for off in offsets {
                    vec.push(base + off);
                }

                base + size
            }
            &RefPattern::NestedType(ref types) => {
                let mut cur_base = base;

                for ty in types {
                    let nested_offset = ty.gen_ref_offsets();
                    let mut nested_offset = nested_offset.iter().map(|x| x + cur_base).collect();

                    vec.append(&mut nested_offset);

                    cur_base += ty.size;
                }

                cur_base
            }
        }
    }
}

100
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
101
pub struct RepeatingRefPattern {
qinsoon's avatar
qinsoon committed
102 103
    pub pattern: RefPattern,
    pub count: usize
qinsoon's avatar
qinsoon committed
104 105 106 107 108 109
}

impl RepeatingRefPattern {
    pub fn append_offsets(&self, base: ByteSize, vec: &mut Vec<ByteSize>) -> ByteSize {
        let mut cur_base = base;

qinsoon's avatar
qinsoon committed
110
        for _ in 0..self.count {
qinsoon's avatar
qinsoon committed
111 112 113 114 115 116 117 118 119 120
            cur_base = self.pattern.append_offsets(cur_base, vec);
        }

        cur_base
    }
}

#[cfg(test)]
mod tests {
    use super::*;
121
    use std::sync::Arc;
qinsoon's avatar
qinsoon committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
    use utils::ByteSize;

    fn create_types() -> Vec<GCType> {
        // linked list: struct {ref, int64}
        let a = GCType{
            id: 0,
            size: 16,
            non_repeat_refs: Some(RefPattern::Map{
                offsets: vec![0],
                size: 16
            }),
            repeat_refs    : None
        };

        // array of struct {ref, int64} with length 10
        let b = GCType {
            id: 1,
            size: 160,
            non_repeat_refs: None,
            repeat_refs    : Some(RepeatingRefPattern {
                pattern: RefPattern::Map{
                    offsets: vec![0],
                    size   : 16
                },
                count  : 10
147
            }),
qinsoon's avatar
qinsoon committed
148 149 150 151 152 153 154 155
        };

        // array(10) of array(10) of struct {ref, int64}
        let c = GCType {
            id: 2,
            size: 1600,
            non_repeat_refs: None,
            repeat_refs    : Some(RepeatingRefPattern {
156
                pattern: RefPattern::NestedType(vec![Arc::new(b.clone()).clone()]),
qinsoon's avatar
qinsoon committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
                count  : 10
            })
        };

        vec![a, b, c]
    }

    #[test]
    fn test_types() {
        create_types();
    }

    #[test]
    fn test_ref_offsets() {
        let vec = create_types();

        assert_eq!(vec[0].gen_ref_offsets(), vec![0]);
        assert_eq!(vec[1].gen_ref_offsets(), vec![0, 16, 32, 48, 64, 80, 96, 112, 128, 144]);
        assert_eq!(vec[2].gen_ref_offsets(), (0..100).map(|x| x * 16).collect::<Vec<ByteSize>>());
    }
177
}