remove headers from exchange allocations

This commit is contained in:
Daniel Micay 2013-07-02 19:51:39 -04:00
parent 0aedecf96b
commit 90f1db10fa
16 changed files with 165 additions and 75 deletions

View file

@ -1395,8 +1395,12 @@ pub fn compile_submatch(bcx: block,
}
if any_uniq_pat(m, col) {
let pat_ty = node_id_type(bcx, pat_id);
let llbox = Load(bcx, val);
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
let unboxed = match ty::get(pat_ty).sty {
ty::ty_uniq(*) if !ty::type_contents(bcx.tcx(), pat_ty).contains_managed() => llbox,
_ => GEPi(bcx, llbox, [0u, abi::box_field_body])
};
compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
vec::append(~[unboxed], vals_left), chk);
return;
@ -1868,8 +1872,12 @@ pub fn bind_irrefutable_pat(bcx: block,
}
}
ast::pat_box(inner) | ast::pat_uniq(inner) => {
let pat_ty = node_id_type(bcx, pat.id);
let llbox = Load(bcx, val);
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
let unboxed = match ty::get(pat_ty).sty {
ty::ty_uniq(*) if !ty::type_contents(bcx.tcx(), pat_ty).contains_managed() => llbox,
_ => GEPi(bcx, llbox, [0u, abi::box_field_body])
};
bcx = bind_irrefutable_pat(bcx,
inner,
unboxed,

View file

@ -289,24 +289,25 @@ pub fn malloc_raw_dyn(bcx: block,
let _icx = push_ctxt("malloc_raw");
let ccx = bcx.ccx();
let (mk_fn, langcall) = match heap {
heap_managed | heap_managed_unique => {
(ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
}
heap_exchange => {
(ty::mk_imm_uniq, bcx.tcx().lang_items.exchange_malloc_fn())
}
heap_exchange_vector => {
(ty::mk_imm_uniq, bcx.tcx().lang_items.vector_exchange_malloc_fn())
}
heap_exchange_closure => {
(ty::mk_imm_uniq, bcx.tcx().lang_items.closure_exchange_malloc_fn())
}
};
if heap == heap_exchange {
let llty_value = type_of::type_of(ccx, t);
let llalign = llalign_of_min(ccx, llty_value);
if heap == heap_exchange || heap == heap_exchange_vector {
// Allocate space:
let rval = alloca(bcx, Type::i8p());
let bcx = callee::trans_lang_call(
bcx,
bcx.tcx().lang_items.exchange_malloc_fn(),
[C_i32(llalign as i32), size],
expr::SaveIn(rval));
rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty_value.ptr_to()))
} else if heap == heap_exchange_vector {
// Grab the TypeRef type of box_ptr_ty.
let box_ptr_ty = mk_fn(bcx.tcx(), t);
let element_type = match ty::get(t).sty {
ty::ty_unboxed_vec(e) => e,
_ => fail!("not a vector body")
};
let box_ptr_ty = ty::mk_evec(bcx.tcx(), element_type, ty::vstore_uniq);
let llty = type_of(ccx, box_ptr_ty);
let llty_value = type_of::type_of(ccx, t);
@ -316,11 +317,22 @@ pub fn malloc_raw_dyn(bcx: block,
let rval = alloca(bcx, Type::i8p());
let bcx = callee::trans_lang_call(
bcx,
langcall,
bcx.tcx().lang_items.vector_exchange_malloc_fn(),
[C_i32(llalign as i32), size],
expr::SaveIn(rval));
rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty))
} else {
// we treat ~fn, @fn and @[] as @ here, which isn't ideal
let (mk_fn, langcall) = match heap {
heap_managed | heap_managed_unique => {
(ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
}
heap_exchange_closure => {
(ty::mk_imm_box, bcx.tcx().lang_items.closure_exchange_malloc_fn())
}
_ => fail!("heap_exchange/heap_exchange_vector already handled")
};
// Grab the TypeRef type of box_ptr_ty.
let box_ptr_ty = mk_fn(bcx.tcx(), t);
let llty = type_of(ccx, box_ptr_ty);
@ -362,6 +374,7 @@ pub struct MallocResult {
// and pulls out the body
pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
-> MallocResult {
assert!(heap != heap_exchange);
let _icx = push_ctxt("malloc_general");
let Result {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, t, heap, size);
let body = GEPi(bcx, llbox, [0u, abi::box_field_body]);
@ -369,9 +382,9 @@ pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
MallocResult { bcx: bcx, box: llbox, body: body }
}
pub fn malloc_general(bcx: block, t: ty::t, heap: heap)
-> MallocResult {
let ty = type_of(bcx.ccx(), t);
pub fn malloc_general(bcx: block, t: ty::t, heap: heap) -> MallocResult {
let ty = type_of(bcx.ccx(), t);
assert!(heap != heap_exchange);
malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty))
}
pub fn malloc_boxed(bcx: block, t: ty::t)
@ -388,6 +401,7 @@ pub fn heap_for_unique(bcx: block, t: ty::t) -> heap {
}
pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
assert!(heap != heap_exchange);
if heap == heap_managed_unique {
// In cases where we are looking at a unique-typed allocation in the
// managed heap (thus have refcount 1 from the managed allocator),
@ -399,11 +413,6 @@ pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
}
}
pub fn malloc_unique(bcx: block, t: ty::t)
-> MallocResult {
malloc_general(bcx, t, heap_for_unique(bcx, t))
}
// Type descriptor and type glue stuff
pub fn get_tydesc_simple(ccx: &mut CrateContext, t: ty::t) -> ValueRef {

View file

@ -100,6 +100,7 @@ use middle::trans::glue;
use middle::trans::tvec;
use middle::trans::type_of;
use middle::trans::write_guard;
use middle::trans::type_::Type;
use middle::ty;
use util::common::indenter;
use util::ppaux::ty_to_str;
@ -567,8 +568,14 @@ impl Datum {
* This datum must represent an @T or ~T box. Returns a new
* by-ref datum of type T, pointing at the contents. */
let content_ty = match ty::get(self.ty).sty {
ty::ty_box(mt) | ty::ty_uniq(mt) => mt.ty,
let (content_ty, header) = match ty::get(self.ty).sty {
ty::ty_box(mt) => (mt.ty, true),
ty::ty_uniq(mt) => (mt.ty, false),
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
let unit_ty = ty::sequence_element_type(bcx.tcx(), self.ty);
let unboxed_vec_ty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
(unboxed_vec_ty, true)
}
_ => {
bcx.tcx().sess.bug(fmt!(
"box_body() invoked on non-box type %s",
@ -576,9 +583,16 @@ impl Datum {
}
};
let ptr = self.to_value_llval(bcx);
let body = opaque_box_body(bcx, content_ty, ptr);
Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
if !header && !ty::type_contents(bcx.tcx(), content_ty).contains_managed() {
let ptr = self.to_value_llval(bcx);
let ty = type_of(bcx.ccx(), content_ty);
let body = PointerCast(bcx, ptr, ty.ptr_to());
Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
} else { // has a header
let ptr = self.to_value_llval(bcx);
let body = opaque_box_body(bcx, content_ty, ptr);
Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
}
}
pub fn to_rptr(&self, bcx: block) -> Datum {

View file

@ -150,6 +150,7 @@ use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
use middle::ty;
use util::common::indenter;
use util::ppaux::Repr;
use middle::trans::machine::llsize_of;
use middle::trans::type_::Type;
@ -1329,12 +1330,23 @@ fn trans_unary_datum(bcx: block,
contents_ty: ty::t,
heap: heap) -> DatumBlock {
let _icx = push_ctxt("trans_boxed_expr");
let base::MallocResult { bcx, box: bx, body } =
base::malloc_general(bcx, contents_ty, heap);
add_clean_free(bcx, bx, heap);
let bcx = trans_into(bcx, contents, SaveIn(body));
revoke_clean(bcx, bx);
return immediate_rvalue_bcx(bcx, bx, box_ty);
if heap == heap_exchange {
let llty = type_of(bcx.ccx(), contents_ty);
let size = llsize_of(bcx.ccx(), llty);
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
heap_exchange, size);
add_clean_free(bcx, val, heap_exchange);
let bcx = trans_into(bcx, contents, SaveIn(val));
revoke_clean(bcx, val);
return immediate_rvalue_bcx(bcx, val, box_ty);
} else {
let base::MallocResult { bcx, box: bx, body } =
base::malloc_general(bcx, contents_ty, heap);
add_clean_free(bcx, bx, heap);
let bcx = trans_into(bcx, contents, SaveIn(body));
revoke_clean(bcx, bx);
return immediate_rvalue_bcx(bcx, bx, box_ty);
}
}
}

View file

@ -386,7 +386,9 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
ty::ty_uniq(*) => {
uniq::make_free_glue(bcx, v, t)
}
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) |
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
tvec::make_uniq_free_glue(bcx, v, t)
}
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
make_free_glue(bcx, v,
tvec::expand_boxed_vec_ty(bcx.tcx(), t));

View file

@ -548,6 +548,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
let _icx = push_ctxt("impl::trans_trait_callee");
let ccx = bcx.ccx();
let mut bcx = bcx;
// Load the vtable from the @Trait pair
debug!("(translating trait callee) loading vtable from pair %s",
@ -576,6 +577,10 @@ pub fn trans_trait_callee_from_llval(bcx: block,
}
ast::sty_region(*) => {
match store {
ty::UniqTraitStore
if !ty::type_contents(bcx.tcx(), callee_ty).contains_managed() => {
llself = llbox;
}
ty::BoxTraitStore |
ty::UniqTraitStore => {
llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);

View file

@ -194,7 +194,11 @@ impl Reflector {
}
ty::ty_uniq(ref mt) => {
let extra = self.c_mt(mt);
self.visit("uniq", extra)
if ty::type_contents(bcx.tcx(), t).contains_managed() {
self.visit("uniq_managed", extra)
} else {
self.visit("uniq", extra)
}
}
ty::ty_ptr(ref mt) => {
let extra = self.c_mt(mt);

View file

@ -33,6 +33,23 @@ use std::option::None;
use syntax::ast;
use syntax::codemap;
pub fn make_uniq_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
-> block {
let box_datum = immediate_rvalue(Load(bcx, vptrptr), box_ty);
let not_null = IsNotNull(bcx, box_datum.val);
do with_cond(bcx, not_null) |bcx| {
let body_datum = box_datum.box_body(bcx);
let bcx = glue::drop_ty(bcx, body_datum.to_ref_llval(bcx),
body_datum.ty);
if ty::type_contents(bcx.tcx(), box_ty).contains_managed() {
glue::trans_free(bcx, box_datum.val)
} else {
glue::trans_exchange_free(bcx, box_datum.val)
}
}
}
// Boxed vector types are in some sense currently a "shorthand" for a box
// containing an unboxed vector. This expands a boxed vector type into such an
// expanded type. It doesn't respect mutability, but that doesn't matter at
@ -42,7 +59,7 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
match ty::get(t).sty {
ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) => {
ty::mk_imm_uniq(tcx, unboxed_vec_ty)
fail!("cannot treat vectors/strings as exchange allocations yet");
}
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
ty::mk_imm_box(tcx, unboxed_vec_ty)

View file

@ -72,29 +72,6 @@ pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> Type {
}
}
pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> Type {
assert!(!ty::type_needs_infer(t));
let t_norm = ty::normalize_ty(cx.tcx, t);
if t != t_norm {
type_of_non_gc_box(cx, t_norm)
} else {
match ty::get(t).sty {
ty::ty_box(mt) => {
let ty = type_of(cx, mt.ty);
Type::box(cx, &ty).ptr_to()
}
ty::ty_uniq(mt) => {
let ty = type_of(cx, mt.ty);
Type::unique(cx, &ty).ptr_to()
}
_ => {
cx.sess.bug("non-box in type_of_non_gc_box");
}
}
}
}
// A "sizing type" is an LLVM type, the size and alignment of which are
// guaranteed to be equivalent to what you would get out of `type_of()`. It's
// useful because:
@ -231,7 +208,11 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
ty::ty_uniq(ref mt) => {
let ty = type_of(cx, mt.ty);
Type::unique(cx, &ty).ptr_to()
if ty::type_contents(cx.tcx, mt.ty).contains_managed() {
Type::unique(cx, &ty).ptr_to()
} else {
ty.ptr_to()
}
}
ty::ty_evec(ref mt, ty::vstore_uniq) => {
let ty = type_of(cx, mt.ty);

View file

@ -17,6 +17,9 @@ use middle::trans::datum::immediate_rvalue;
use middle::trans::datum;
use middle::trans::glue;
use middle::ty;
use middle::trans::machine::llsize_of;
use middle::trans::type_of;
use middle::trans::type_of::*;
pub fn make_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
-> block {
@ -44,12 +47,21 @@ pub fn duplicate(bcx: block, src_box: ValueRef, src_ty: ty::t) -> Result {
let body_datum = src_datum.box_body(bcx);
// Malloc space in exchange heap and copy src into it
let MallocResult {
bcx: bcx,
box: dst_box,
body: dst_body
} = malloc_unique(bcx, body_datum.ty);
body_datum.copy_to(bcx, datum::INIT, dst_body);
if ty::type_contents(bcx.tcx(), src_ty).contains_managed() {
let MallocResult {
bcx: bcx,
box: dst_box,
body: dst_body
} = malloc_general(bcx, body_datum.ty, heap_managed_unique);
body_datum.copy_to(bcx, datum::INIT, dst_body);
rslt(bcx, dst_box)
rslt(bcx, dst_box)
} else {
let body_datum = body_datum.to_value_datum(bcx);
let llty = type_of(bcx.ccx(), body_datum.ty);
let size = llsize_of(bcx.ccx(), llty);
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, body_datum.ty, heap_exchange, size);
body_datum.copy_to(bcx, datum::INIT, val);
Result { bcx: bcx, val: val }
}
}

View file

@ -248,6 +248,14 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
true
}
#[cfg(not(stage0))]
fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.align_to::<~u8>();
if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
self.bump_past::<~u8>();
true
}
fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.align_to::<*u8>();
if ! self.inner.visit_ptr(mtbl, inner) { return false; }

View file

@ -300,6 +300,15 @@ impl TyVisitor for ReprVisitor {
}
fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.writer.write_char('~');
self.write_mut_qualifier(mtbl);
do self.get::<*c_void> |b| {
self.visit_ptr_inner(*b, inner);
}
}
#[cfg(not(stage0))]
fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.writer.write_char('~');
self.write_mut_qualifier(mtbl);
do self.get::<&managed::raw::BoxRepr> |b| {

View file

@ -80,9 +80,8 @@ pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
#[cfg(not(stage0), not(test))]
#[lang="exchange_malloc"]
#[inline]
pub unsafe fn exchange_malloc(align: u32, size: uintptr_t) -> *c_char {
let total_size = get_box_size(size as uint, align as uint);
malloc_raw(total_size as uint) as *c_char
pub unsafe fn exchange_malloc(_align: u32, size: uintptr_t) -> *c_char {
malloc_raw(size as uint) as *c_char
}
#[cfg(not(test))]

View file

@ -91,6 +91,7 @@ pub trait TyVisitor {
fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool;

View file

@ -232,6 +232,13 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
true
}
fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.align_to::<~u8>();
if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
self.bump_past::<~u8>();
true
}
fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
self.align_to::<*u8>();
if ! self.inner.visit_ptr(mtbl, inner) { return false; }
@ -552,6 +559,7 @@ impl TyVisitor for my_visitor {
fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }

View file

@ -70,6 +70,7 @@ impl TyVisitor for MyVisitor {
fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }