Removed free_glue from tydesc (the code is still generated, but inlined in drop_glue).

This commit is contained in:
Eduard Burtescu 2014-01-01 14:45:31 +02:00
parent 5ad2a7825b
commit 7a305f9e83
8 changed files with 79 additions and 171 deletions

View File

@ -44,11 +44,10 @@ pub static tydesc_field_size: uint = 0u;
pub static tydesc_field_align: uint = 1u;
pub static tydesc_field_take_glue: uint = 2u;
pub static tydesc_field_drop_glue: uint = 3u;
pub static tydesc_field_free_glue: uint = 4u;
pub static tydesc_field_visit_glue: uint = 5u;
pub static tydesc_field_borrow_offset: uint = 6u;
pub static tydesc_field_name_offset: uint = 7u;
pub static n_tydesc_fields: uint = 8u;
pub static tydesc_field_visit_glue: uint = 4u;
pub static tydesc_field_borrow_offset: uint = 5u;
pub static tydesc_field_name_offset: uint = 6u;
pub static n_tydesc_fields: uint = 7u;
// The two halves of a closure: code and environment.
pub static fn_field_code: uint = 0u;

View File

@ -474,7 +474,7 @@ pub fn make_opaque_cbox_drop_glue<'a>(
bcx.tcx().sess.bug("trying to trans drop glue of @fn")
}
ast::OwnedSigil => {
glue::free_ty(
glue::make_free_glue(
bcx, cboxptr,
ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
}

View File

@ -94,7 +94,6 @@ pub struct tydesc_info {
name: ValueRef,
take_glue: Cell<Option<ValueRef>>,
drop_glue: Cell<Option<ValueRef>>,
free_glue: Cell<Option<ValueRef>>,
visit_glue: Cell<Option<ValueRef>>,
}

View File

@ -23,13 +23,13 @@ use middle::trans::base::*;
use middle::trans::callee;
use middle::trans::closure;
use middle::trans::common::*;
use middle::trans::datum::immediate_rvalue;
use middle::trans::build::*;
use middle::trans::expr;
use middle::trans::machine::*;
use middle::trans::reflect;
use middle::trans::tvec;
use middle::trans::type_of::type_of;
use middle::trans::uniq;
use middle::ty;
use util::ppaux;
use util::ppaux::ty_to_short_str;
@ -86,47 +86,16 @@ pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
drop_ty(bcx, vp, t)
}
pub fn free_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t)
-> &'a Block<'a> {
// NB: v is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("free_ty");
if ty::type_needs_drop(cx.tcx(), t) {
return call_tydesc_glue(cx, v, t, abi::tydesc_field_free_glue);
}
return cx;
}
pub fn free_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
-> &'a Block<'a> {
let _icx = push_ctxt("free_ty_immediate");
match ty::get(t).sty {
ty::ty_uniq(_) |
ty::ty_vec(_, ty::vstore_uniq) |
ty::ty_str(ty::vstore_uniq) |
ty::ty_box(_) | ty::ty_opaque_box |
ty::ty_vec(_, ty::vstore_box) |
ty::ty_str(ty::vstore_box) |
ty::ty_opaque_closure_ptr(_) => {
let vp = alloca(bcx, type_of(bcx.ccx(), t), "");
Store(bcx, v, vp);
free_ty(bcx, vp, t)
}
_ => bcx.tcx().sess.bug("free_ty_immediate: non-box ty")
}
}
pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext,
static_ti: @tydesc_info) {
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, static_ti);
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_drop_glue, static_ti);
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_free_glue, static_ti);
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_visit_glue, static_ti);
}
pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
if (field == abi::tydesc_field_take_glue ||
field == abi::tydesc_field_drop_glue ||
field == abi::tydesc_field_free_glue) &&
field == abi::tydesc_field_drop_glue) &&
! ty::type_needs_drop(tcx, t) {
return ty::mk_u32();
}
@ -146,22 +115,7 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
return ty::mk_imm_box(tcx, ty::mk_u32());
}
if field == abi::tydesc_field_free_glue {
match ty::get(t).sty {
ty::ty_bare_fn(..) |
ty::ty_closure(..) |
ty::ty_box(..) |
ty::ty_opaque_box |
ty::ty_uniq(..) |
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) |
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) |
ty::ty_opaque_closure_ptr(..) => (),
_ => { return ty::mk_u32(); }
}
}
if (field == abi::tydesc_field_free_glue ||
field == abi::tydesc_field_drop_glue) {
if field == abi::tydesc_field_drop_glue {
match ty::get(t).sty {
ty::ty_box(typ)
if ! ty::type_needs_drop(tcx, typ) =>
@ -197,8 +151,6 @@ pub fn lazily_emit_simplified_tydesc_glue(ccx: @CrateContext,
ti.take_glue.set(simpl_ti.take_glue.get());
} else if field == abi::tydesc_field_drop_glue {
ti.drop_glue.set(simpl_ti.drop_glue.get());
} else if field == abi::tydesc_field_free_glue {
ti.free_glue.set(simpl_ti.free_glue.get());
} else if field == abi::tydesc_field_visit_glue {
ti.visit_glue.set(simpl_ti.visit_glue.get());
}
@ -245,19 +197,6 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext,
ppaux::ty_to_str(ccx.tcx, ti.ty));
}
}
} else if field == abi::tydesc_field_free_glue {
match ti.free_glue.get() {
Some(_) => (),
None => {
debug!("+++ lazily_emit_tydesc_glue FREE {}",
ppaux::ty_to_str(ccx.tcx, ti.ty));
let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "free");
ti.free_glue.set(Some(glue_fn));
make_generic_glue(ccx, ti.ty, glue_fn, make_free_glue, "free");
debug!("--- lazily_emit_tydesc_glue FREE {}",
ppaux::ty_to_str(ccx.tcx, ti.ty));
}
}
} else if field == abi::tydesc_field_visit_glue {
match ti.visit_glue.get() {
Some(_) => (),
@ -294,8 +233,6 @@ pub fn call_tydesc_glue_full(bcx: &Block,
sti.take_glue.get()
} else if field == abi::tydesc_field_drop_glue {
sti.drop_glue.get()
} else if field == abi::tydesc_field_free_glue {
sti.free_glue.get()
} else if field == abi::tydesc_field_visit_glue {
sti.visit_glue.get()
} else {
@ -346,8 +283,8 @@ pub fn call_tydesc_glue<'a>(
return cx;
}
pub fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
-> &'a Block<'a> {
fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
-> &'a Block<'a> {
let _icx = push_ctxt("make_visit_glue");
with_scope(bcx, None, "visitor cleanup", |bcx| {
let mut bcx = bcx;
@ -371,31 +308,32 @@ pub fn make_free_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
// NB: v0 is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("make_free_glue");
match ty::get(t).sty {
ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_free_glue"),
ty::ty_box(body_ty) => {
let v = Load(bcx, v);
let body = GEPi(bcx, v, [0u, abi::box_field_body]);
let bcx = drop_ty(bcx, body, body_ty);
trans_free(bcx, v)
}
ty::ty_opaque_box => {
let v = Load(bcx, v);
let td = Load(bcx, GEPi(bcx, v, [0u, abi::box_field_tydesc]));
let valptr = GEPi(bcx, v, [0u, abi::box_field_body]);
// Generate code that, dynamically, indexes into the
// tydesc and calls the drop glue that got set dynamically
call_tydesc_glue_full(bcx, valptr, td, abi::tydesc_field_drop_glue,
None);
trans_free(bcx, v)
}
ty::ty_uniq(..) => {
uniq::make_free_glue(bcx, v, t)
let box_datum = immediate_rvalue(Load(bcx, v), t);
let not_null = IsNotNull(bcx, box_datum.val);
with_cond(bcx, not_null, |bcx| {
let body_datum = box_datum.box_body(bcx);
let bcx = drop_ty(bcx, body_datum.to_ref_llval(bcx), body_datum.ty);
if ty::type_contents(bcx.tcx(), t).owns_managed() {
trans_free(bcx, box_datum.val)
} else {
trans_exchange_free(bcx, box_datum.val)
}
})
}
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) |
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
make_free_glue(bcx, v, tvec::expand_boxed_vec_ty(bcx.tcx(), t))
}
ty::ty_closure(_) => {
closure::make_closure_glue(bcx, v, t, free_ty)
closure::make_closure_glue(bcx, v, t, make_free_glue)
}
ty::ty_opaque_closure_ptr(ck) => {
closure::make_opaque_cbox_free_glue(bcx, ck, v)
@ -469,13 +407,14 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
let _icx = push_ctxt("make_drop_glue");
let ccx = bcx.ccx();
match ty::get(t).sty {
ty::ty_box(_) | ty::ty_opaque_box |
ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_drop_glue"),
ty::ty_box(_) |
ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => {
decr_refcnt_maybe_free(bcx, Load(bcx, v0), Some(v0), t)
decr_refcnt_maybe_free(bcx, v0, Some(t))
}
ty::ty_uniq(_) |
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
free_ty(bcx, v0, t)
make_free_glue(bcx, v0, t)
}
ty::ty_unboxed_vec(_) => {
tvec::make_drop_glue_unboxed(bcx, v0, t)
@ -500,9 +439,7 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
}
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
let llbox_ptr = GEPi(bcx, v0, [0u, abi::trt_field_box]);
let llbox = Load(bcx, llbox_ptr);
decr_refcnt_maybe_free(bcx, llbox, Some(llbox_ptr),
ty::mk_opaque_box(ccx.tcx))
decr_refcnt_maybe_free(bcx, llbox_ptr, None)
}
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
@ -517,7 +454,7 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
call_tydesc_glue_full(bcx,
lluniquevalue,
lltydesc,
abi::tydesc_field_free_glue,
abi::tydesc_field_drop_glue,
None);
bcx
})
@ -534,44 +471,46 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
}
}
// box_ptr_ptr is optional, it is constructed if not supplied.
pub fn decr_refcnt_maybe_free<'a>(
bcx: &'a Block<'a>,
box_ptr: ValueRef,
box_ptr_ptr: Option<ValueRef>,
t: ty::t)
-> &'a Block<'a> {
fn decr_refcnt_maybe_free<'a>(bcx: &'a Block<'a>, box_ptr_ptr: ValueRef,
t: Option<ty::t>) -> &'a Block<'a> {
let _icx = push_ctxt("decr_refcnt_maybe_free");
let ccx = bcx.ccx();
let decr_bcx = sub_block(bcx, "decr");
let free_bcx = sub_block(decr_bcx, "free");
let next_bcx = sub_block(bcx, "next");
let box_ptr = Load(bcx, box_ptr_ptr);
let llnotnull = IsNotNull(bcx, box_ptr);
CondBr(bcx, llnotnull, decr_bcx.llbb, next_bcx.llbb);
let rc_ptr = GEPi(decr_bcx, box_ptr, [0u, abi::box_field_refcnt]);
let rc = Sub(decr_bcx, Load(decr_bcx, rc_ptr), C_int(ccx, 1));
Store(decr_bcx, rc, rc_ptr);
let llisnull = IsNull(decr_bcx, rc);
CondBr(decr_bcx, llisnull, free_bcx.llbb, next_bcx.llbb);
CondBr(decr_bcx, IsNull(decr_bcx, rc), free_bcx.llbb, next_bcx.llbb);
let free_bcx = match box_ptr_ptr {
Some(p) => free_ty(free_bcx, p, t),
None => free_ty_immediate(free_bcx, box_ptr, t)
let free_bcx = match t {
Some(t) => make_free_glue(free_bcx, box_ptr_ptr, t),
None => {
let v = Load(free_bcx, box_ptr_ptr);
let td = Load(free_bcx, GEPi(free_bcx, v, [0u, abi::box_field_tydesc]));
let valptr = GEPi(free_bcx, v, [0u, abi::box_field_body]);
// Generate code that, dynamically, indexes into the
// tydesc and calls the drop glue that got set dynamically
call_tydesc_glue_full(free_bcx, valptr, td, abi::tydesc_field_drop_glue, None);
trans_free(free_bcx, v)
}
};
Br(free_bcx, next_bcx.llbb);
next_bcx
}
pub fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
-> &'a Block<'a> {
fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) -> &'a Block<'a> {
let _icx = push_ctxt("make_take_glue");
// NB: v is a *pointer* to type t here, not a direct value.
match ty::get(t).sty {
ty::ty_box(_) | ty::ty_opaque_box |
ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_take_glue"),
ty::ty_box(_) |
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
}
@ -608,7 +547,7 @@ pub fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
}
}
pub fn incr_refcnt_of_boxed(cx: &Block, box_ptr: ValueRef) {
fn incr_refcnt_of_boxed(cx: &Block, box_ptr: ValueRef) {
let _icx = push_ctxt("incr_refcnt_of_boxed");
let ccx = cx.ccx();
let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]);
@ -665,7 +604,6 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
name: ty_name,
take_glue: Cell::new(None),
drop_glue: Cell::new(None),
free_glue: Cell::new(None),
visit_glue: Cell::new(None),
};
debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx, t));
@ -770,21 +708,6 @@ pub fn emit_tydescs(ccx: &CrateContext) {
}
}
};
let free_glue =
match ti.free_glue.get() {
None => {
ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() +
1u);
C_null(glue_fn_ty)
}
Some(v) => {
unsafe {
ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() +
1);
llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
}
}
};
let visit_glue =
match ti.visit_glue.get() {
None => {
@ -808,7 +731,6 @@ pub fn emit_tydescs(ccx: &CrateContext) {
ti.align, // align
take_glue, // take_glue
drop_glue, // drop_glue
free_glue, // free_glue
visit_glue, // visit_glue
ti.borrow_offset, // borrow_offset
ti.name]); // name

View File

@ -25,7 +25,6 @@ pub mod build;
pub mod builder;
pub mod base;
pub mod _match;
pub mod uniq;
pub mod closure;
pub mod tvec;
pub mod meth;

View File

@ -219,7 +219,6 @@ impl Type {
int_ty, // align
glue_fn_ty, // take
glue_fn_ty, // drop
glue_fn_ty, // free
glue_fn_ty, // visit
int_ty, // borrow_offset
Type::struct_([Type::i8p(), Type::int(arch)], false)]; // name

View File

@ -1,39 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::llvm::ValueRef;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::datum::immediate_rvalue;
use middle::trans::glue;
use middle::ty;
pub fn make_free_glue<'a>(
bcx: &'a Block<'a>,
vptrptr: ValueRef,
box_ty: ty::t)
-> &'a Block<'a> {
let _icx = push_ctxt("uniq::make_free_glue");
let box_datum = immediate_rvalue(Load(bcx, vptrptr), box_ty);
let not_null = IsNotNull(bcx, box_datum.val);
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).owns_managed() {
glue::trans_free(bcx, box_datum.val)
} else {
glue::trans_exchange_free(bcx, box_datum.val)
}
})
}

View File

@ -47,9 +47,9 @@ pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor, TypeId};
pub type GlueFn = extern "Rust" fn(*i8);
// NB: this has to be kept in sync with `type_desc` in `rt`
// NOTE remove after next snapshot
#[lang="ty_desc"]
#[cfg(not(test))]
#[cfg(not(test), stage0)]
pub struct TyDesc {
// sizeof(T)
size: uint,
@ -80,6 +80,35 @@ pub struct TyDesc {
name: &'static str
}
#[lang="ty_desc"]
#[cfg(not(test), not(stage0))]
pub struct TyDesc {
// sizeof(T)
size: uint,
// alignof(T)
align: uint,
// Called on a copy of a value of type `T` *after* memcpy
take_glue: GlueFn,
// Called when a value of type `T` is no longer needed
drop_glue: GlueFn,
// Called by reflection visitor to visit a value of type `T`
visit_glue: GlueFn,
// If T represents a box pointer (`@U` or `~U`), then
// `borrow_offset` is the amount that the pointer must be adjusted
// to find the payload. This is always derivable from the type
// `U`, but in the case of `@Trait` or `~Trait` objects, the type
// `U` is unknown.
borrow_offset: uint,
// Name corresponding to the type
name: &'static str
}
#[lang="opaque"]
#[cfg(not(test))]
pub enum Opaque { }