Commit b0467947 authored by qinsoon's avatar qinsoon

BackendTypeInfo includes GCType, generating GCType during resolving type

info
parent 3ed935e1
......@@ -394,6 +394,26 @@ pub fn is_ptr(ty: &MuType) -> bool {
}
}
/// this a type reference type (located in heap)?
pub fn is_reference(ty: &MuType) -> bool {
match ty.v {
MuType_::Ref(_)
| MuType_::IRef(_)
| MuType_::WeakRef(_) => true,
_ => false
}
}
/// this is a aggregated type (consited of other types)
pub fn is_aggregate(ty: &MuType) -> bool {
match ty.v {
MuType_::Struct(_)
| MuType_::Hybrid(_)
| MuType_::Array(_, _) => true,
_ => false
}
}
/// is a type scalar type?
pub fn is_scalar(ty: &MuType) -> bool {
match ty.v {
......
......@@ -3,7 +3,10 @@ pub mod reg_alloc;
pub mod peephole_opt;
pub mod code_emission;
use ast::types;
use utils::ByteSize;
use runtime::mm;
use runtime::mm::common::gctype::{GCType, GCTYPE_INIT_ID, RefPattern, RepeatingRefPattern};
pub type Word = usize;
pub const WORD_SIZE : ByteSize = 8;
......@@ -64,35 +67,77 @@ use ast::ptr::*;
use ast::ir::*;
pub fn resolve_backend_type_info (ty: &MuType, vm: &VM) -> BackendTypeInfo {
match ty.v {
// integral
// integer
MuType_::Int(size_in_bit) => {
match size_in_bit {
1 => BackendTypeInfo{size: 1, alignment: 1, struct_layout: None},
8 => BackendTypeInfo{size: 1, alignment: 1, struct_layout: None},
16 => BackendTypeInfo{size: 2, alignment: 2, struct_layout: None},
32 => BackendTypeInfo{size: 4, alignment: 4, struct_layout: None},
64 => BackendTypeInfo{size: 8, alignment: 8, struct_layout: None},
1 => BackendTypeInfo{
size: 1, alignment: 1, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(1))
},
8 => BackendTypeInfo{
size: 1, alignment: 1, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(1))
},
16 => BackendTypeInfo{
size: 2, alignment: 2, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(2))
},
32 => BackendTypeInfo{
size: 4, alignment: 4, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(4))
},
64 => BackendTypeInfo{
size: 8, alignment: 8, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(8))
},
_ => unimplemented!()
}
},
// pointer of any type
// reference of any type
MuType_::Ref(_)
| MuType_::IRef(_)
| MuType_::WeakRef(_)
| MuType_::UPtr(_)
| MuType_::FuncRef(_)
| MuType_::WeakRef(_) => BackendTypeInfo{
size: 8, alignment: 8, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_reftype())
},
// pointer
MuType_::UPtr(_)
| MuType_::UFuncPtr(_)
| MuType_::Tagref64
| MuType_::FuncRef(_)
| MuType_::ThreadRef
| MuType_::StackRef => BackendTypeInfo{size: 8, alignment: 8, struct_layout: None},
| MuType_::StackRef => BackendTypeInfo{
size: 8, alignment: 8, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(8))
},
// tagref
MuType_::Tagref64 => unimplemented!(),
// floating point
MuType_::Float => BackendTypeInfo{size: 4, alignment: 4, struct_layout: None},
MuType_::Double => BackendTypeInfo{size: 8, alignment: 8, struct_layout: None},
MuType_::Float => BackendTypeInfo{
size: 4, alignment: 4, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(4))
},
MuType_::Double => BackendTypeInfo {
size: 8, alignment: 8, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(8))
},
// array
MuType_::Array(ref ty, len) => {
let ele_ty = vm.get_backend_type_info(ty.id());
BackendTypeInfo{size: ele_ty.size * len, alignment: ele_ty.alignment, struct_layout: None}
BackendTypeInfo{
size : ele_ty.size * len,
alignment : ele_ty.alignment,
struct_layout: None,
gc_type : mm::add_gc_type(GCType {
id : GCTYPE_INIT_ID,
size : ele_ty.size * len,
non_repeat_refs: None,
repeat_refs : Some(RepeatingRefPattern{
pattern: RefPattern::NestedType(vec![ele_ty.gc_type]),
count : len
})
})
}
}
// struct
MuType_::Struct(ref name) => {
......@@ -118,16 +163,29 @@ pub fn resolve_backend_type_info (ty: &MuType, vm: &VM) -> BackendTypeInfo {
let mut ret = layout_struct(fix_tys, vm);
// treat var_ty as array (getting its alignment)
let var_align = vm.get_backend_type_info(var_ty.id()).alignment;
let var_ele_ty = vm.get_backend_type_info(var_ty.id());
let var_align = var_ele_ty.alignment;
// fix type info as hybrid
// 1. check alignment
if ret.alignment < var_align {
ret.alignment = var_align;
}
// 2. fix gc type
let mut gctype = ret.gc_type.as_ref().clone();
gctype.repeat_refs = Some(RepeatingRefPattern {
pattern: RefPattern::NestedType(vec![var_ele_ty.gc_type.clone()]),
count : 0
});
ret.gc_type = mm::add_gc_type(gctype);
ret
}
// void
MuType_::Void => BackendTypeInfo{size: 0, alignment: 8, struct_layout: None},
MuType_::Void => BackendTypeInfo{
size: 0, alignment: 8, struct_layout: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(0))
},
// vector
MuType_::Vector(_, _) => unimplemented!()
}
......@@ -137,6 +195,11 @@ fn layout_struct(tys: &Vec<P<MuType>>, vm: &VM) -> BackendTypeInfo {
let mut offsets : Vec<ByteSize> = vec![];
let mut cur : ByteSize = 0;
let mut struct_align : ByteSize = 1;
// for gc type
let mut use_ref_offsets = true;
let mut ref_offsets = vec![];
let mut gc_types = vec![];
for ty in tys.iter() {
let ty_info = vm.get_backend_type_info(ty.id());
......@@ -154,19 +217,48 @@ fn layout_struct(tys: &Vec<P<MuType>>, vm: &VM) -> BackendTypeInfo {
offsets.push(cur);
trace!("aligned to {}", cur);
// for convenience, if the struct contains other struct/array
// we do not use reference map
if types::is_aggregate(ty) {
use_ref_offsets = false;
}
// if this type is reference type, we store its offsets
// we may not use this ref map though
if types::is_reference(ty) {
ref_offsets.push(cur);
}
// always store its gc type (we may not use it as well)
gc_types.push(ty_info.gc_type.clone());
cur += ty_info.size;
}
// if we need padding at the end
if cur % struct_align != 0 {
cur = (cur / struct_align + 1) * struct_align;
}
let size = if cur % struct_align != 0 {
(cur / struct_align + 1) * struct_align
} else {
cur
};
BackendTypeInfo {
size: cur,
alignment: struct_align,
struct_layout: Some(offsets)
size : size,
alignment : struct_align,
struct_layout: Some(offsets),
gc_type : mm::add_gc_type(GCType {
id : GCTYPE_INIT_ID,
size : size,
non_repeat_refs: Some(if use_ref_offsets {
RefPattern::Map {
offsets: ref_offsets,
size: size
}
} else {
RefPattern::NestedType(gc_types)
}),
repeat_refs : None
})
}
}
......@@ -180,7 +272,9 @@ pub fn sequetial_layout(tys: &Vec<P<MuType>>, vm: &VM) -> (ByteSize, ByteSize, V
pub struct BackendTypeInfo {
pub size: ByteSize,
pub alignment: ByteSize,
pub struct_layout: Option<Vec<ByteSize>>
pub struct_layout: Option<Vec<ByteSize>>,
pub gc_type: P<GCType>
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
......
......@@ -19,4 +19,5 @@ log = "0.3.5"
simple_logger = "0.4.0"
aligned_alloc = "0.1.2"
crossbeam = "0.2.8"
doubly = "1.1.1"
\ No newline at end of file
doubly = "1.1.1"
rustc-serialize = "*"
\ No newline at end of file
#![allow(dead_code)]
use std::sync::Arc;
use utils::POINTER_SIZE;
use utils::ByteSize;
#[derive(Clone, Debug)]
use std::usize;
pub const GCTYPE_INIT_ID: usize = usize::MAX;
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct GCType {
pub id: usize,
pub size: ByteSize,
......@@ -11,6 +16,27 @@ pub struct GCType {
}
impl GCType {
pub fn new_noreftype(size: ByteSize) -> GCType {
GCType {
id: GCTYPE_INIT_ID,
size: size,
non_repeat_refs: None,
repeat_refs : None
}
}
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
}
}
#[allow(unused_assignments)]
pub fn gen_ref_offsets(&self) -> Vec<ByteSize> {
let mut ret = vec![];
......@@ -34,13 +60,13 @@ impl GCType {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum RefPattern {
Map{
offsets: Vec<ByteSize>,
size : usize
},
NestedType(Vec<GCType>)
NestedType(Vec<Arc<GCType>>)
}
impl RefPattern {
......@@ -71,7 +97,7 @@ impl RefPattern {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct RepeatingRefPattern {
pub pattern: RefPattern,
pub count: usize
......@@ -92,6 +118,7 @@ impl RepeatingRefPattern {
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
use utils::ByteSize;
fn create_types() -> Vec<GCType> {
......@@ -126,7 +153,7 @@ mod tests {
size: 1600,
non_repeat_refs: None,
repeat_refs : Some(RepeatingRefPattern {
pattern: RefPattern::NestedType(vec![b.clone()]),
pattern: RefPattern::NestedType(vec![Arc::new(b.clone()).clone()]),
count : 10
})
};
......
......@@ -6,6 +6,7 @@ extern crate log;
extern crate simple_logger;
extern crate aligned_alloc;
extern crate crossbeam;
extern crate rustc_serialize;
use std::sync::atomic::Ordering;
......@@ -36,7 +37,7 @@ pub struct GC {
immix_space: Arc<ImmixSpace>,
lo_space : Arc<FreeListSpace>,
gc_types : Vec<GCType>
gc_types : Vec<Arc<GCType>>
}
impl fmt::Debug for GC {
......@@ -66,16 +67,18 @@ pub extern fn get_spaces() -> (Arc<ImmixSpace>, Arc<FreeListSpace>) {
}
#[no_mangle]
pub extern fn add_gc_type(mut ty: GCType) -> usize {
pub extern fn add_gc_type(mut ty: GCType) -> Arc<GCType> {
let mut gc_guard = MY_GC.write().unwrap();
let mut gc = gc_guard.as_mut().unwrap();
let index = gc.gc_types.len();
ty.id = index;
gc.gc_types.push(ty);
let ty = Arc::new(ty);
index
gc.gc_types.push(ty.clone());
ty
}
#[no_mangle]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment