Skip to content

Add garbage collector to std::gc #11399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0a203dd
std::trie: remove each_{key,value}_reverse internal iterators.
huonw Jan 12, 2014
364f101
std::trie: use unsafe code to give a 3x speed up to the iterator.
huonw Jan 13, 2014
38caca6
rustc: Implement the #[managed] attribute and add an intrinsic
huonw Jan 7, 2014
7bf35b2
std::gc: add a true garbage collector and use it for `Gc<T>`.
huonw Jan 7, 2014
879af76
std::gc: support running destructors on values in Gc<T>.
huonw Jan 8, 2014
50dbe64
std::gc: add root registration functions, using type information to
huonw Jan 8, 2014
272d90b
Add the library defined vector type from rust-core.
huonw Jan 7, 2014
84c6d81
std::libvec: make it GC safe.
huonw Jan 8, 2014
5260554
std: add Uniq<T>, a GC-safe version of ~.
huonw Jan 8, 2014
100b1d8
std::gc: cache small(ish) allocations to avoid thrashing the pointer
huonw Jan 8, 2014
7821eb6
std::gc: flip an external reachability bit instead of the reachability
huonw Jan 9, 2014
81163c0
std::gc: allow finalisers to touch the GC (in a restricted way).
huonw Jan 10, 2014
cc1015f
rustc: convert owns_new_managed to reaches_new_managed.
huonw Jan 11, 2014
c170b5b
std::gc: convert to a tracing garbage collector.
huonw Jan 11, 2014
00fc1b3
std::gc: search task-local storage for garbage collected values.
huonw Jan 12, 2014
14aeaef
std::gc: avoid putting all unreachable points into a vector.
huonw Jan 15, 2014
9c69319
std::gc: use a inverse-load-factor based collection policy.
huonw Jan 15, 2014
8e42594
std::gc: remove a branch from `compute_log_rounded_up_size`.
huonw Jan 15, 2014
93716c0
Use lang items to allow registering ~ and ~[] for scanning with the GC.
huonw Jan 15, 2014
16b0bb6
rustc: #[managed] implies not sendable.
huonw Jan 17, 2014
1668909
std::gc: borrow is no longer unsafe.
huonw Jan 17, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/librustc/front/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
("once_fns", Active),
("asm", Active),
("managed_boxes", Active),
("managed", Active),
("non_ascii_idents", Active),
("thread_local", Active),
("link_args", Active),
Expand Down Expand Up @@ -153,6 +154,16 @@ impl Visitor<()> for Context {

_ => {}
}
match i.node {
ast::ItemEnum(..) | ast::ItemStruct(..) => {
if attr::contains_name(i.attrs, "managed") {
self.gate_feature("managed", i.span,
"the `managed` attribute doesn't have safe support \
for built-in pointers like ~ and ~[]")
}
}
_ => {}
}

visit::walk_item(self, i, ());
}
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub fn collect_language_items(crate: &ast::Crate,
}

lets_do_this! {
There are 40 lang items.
There are 42 lang items.

// ID, Variant name, Name, Method name;
0, FreezeTraitLangItem, "freeze", freeze_trait;
Expand Down Expand Up @@ -260,5 +260,7 @@ lets_do_this! {
37, ManagedHeapLangItem, "managed_heap", managed_heap;
38, ExchangeHeapLangItem, "exchange_heap", exchange_heap;
39, GcLangItem, "gc", gc;
}

40, ManagedPointerNote, "managed_pointer_note", managed_pointer_note;
41, ManagedPointerUnnote, "managed_pointer_unnote", managed_pointer_unnote;
}
1 change: 1 addition & 0 deletions src/librustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,7 @@ static other_attrs: &'static [&'static str] = &[
"crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze",
"no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag",
"packed", "simd", "repr", "deriving", "unsafe_destructor", "link",
"managed",

//mod-level
"path", "link_name", "link_args", "nolink", "macro_escape", "no_implicit_prelude",
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2253,4 +2253,3 @@ fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Path> {
}
}
}

26 changes: 23 additions & 3 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use metadata::{csearch, encoder};
use middle::astencode;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::lang_items::{MallocFnLangItem, ClosureExchangeMallocFnLangItem};
use middle::lang_items::{EhPersonalityLangItem};
use middle::lang_items::{EhPersonalityLangItem, ManagedPointerNote};
use middle::trans::_match;
use middle::trans::adt;
use middle::trans::base;
Expand Down Expand Up @@ -354,17 +354,37 @@ pub fn malloc_raw_dyn<'a>(
}
}

fn require_gc_fn(bcx: &Block, t: ty::t) -> ast::DefId {
let li = &bcx.tcx().lang_items;
match li.require(ManagedPointerNote) {
Ok(id) => id,
Err(s) => {
bcx.tcx().sess.fatal(format!("allocation of `{}` {}",
bcx.ty_to_str(t), s));
}
}
}

if heap == heap_exchange {
let llty_value = type_of::type_of(ccx, t);


// Allocate space:
let r = callee::trans_lang_call(
bcx,
require_alloc_fn(bcx, t, ExchangeMallocFnLangItem),
[size],
None);
rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to()))

if ty::type_contents(bcx.tcx(), t).reaches_new_managed() {
let s = callee::trans_lang_call(
r.bcx,
require_gc_fn(r.bcx, t),
[r.val, size],
None);
rslt(s.bcx, PointerCast(s.bcx, r.val, llty_value.ptr_to()))
} else {
rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to()))
}
} else {
// we treat ~fn, @fn and @[] as @ here, which isn't ideal
let langcall = match heap {
Expand Down
14 changes: 11 additions & 3 deletions src/librustc/middle/trans/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use back::abi;
use back::link::*;
use lib;
use lib::llvm::{llvm, ValueRef, True};
use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem};
use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem, ManagedPointerUnnote};
use middle::trans::adt;
use middle::trans::base::*;
use middle::trans::callee;
Expand Down Expand Up @@ -111,7 +111,7 @@ fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
return ty::mk_box(tcx, ty::mk_nil());
}

if field == abi::tydesc_field_drop_glue {
if field == abi::tydesc_field_drop_glue && !ty::type_contents(tcx, t).reaches_new_managed() {
match ty::get(t).sty {
ty::ty_box(typ)
if !ty::type_needs_drop(tcx, typ) =>
Expand Down Expand Up @@ -302,7 +302,15 @@ pub fn make_free_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::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);
let mut bcx = drop_ty(bcx, body_datum.to_ref_llval(bcx), body_datum.ty);

if ty::type_contents(bcx.tcx(), t).reaches_new_managed() {
bcx = callee::trans_lang_call(bcx,
langcall(bcx, None, bcx.ty_to_str(t),
ManagedPointerUnnote),
[PointerCast(bcx, box_datum.val, Type::i8p())],
None).bcx;
}
trans_exchange_free(bcx, box_datum.val)
})
}
Expand Down
8 changes: 6 additions & 2 deletions src/librustc/middle/trans/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,9 +414,13 @@ pub fn trans_intrinsic(ccx: @CrateContext,
let tp_ty = substs.tys[0];
Ret(bcx, C_bool(ty::type_needs_drop(ccx.tcx, tp_ty)));
}
"owns_managed" => {
"owns_at_managed" => {
let tp_ty = substs.tys[0];
Ret(bcx, C_bool(ty::type_contents(ccx.tcx, tp_ty).owns_managed()));
Ret(bcx, C_bool(ty::type_contents(ccx.tcx, tp_ty).owns_at_managed()));
}
"reaches_new_managed" => {
let tp_ty = substs.tys[0];
Ret(bcx, C_bool(ty::type_contents(ccx.tcx, tp_ty).reaches_new_managed()));
}
"visit_tydesc" => {
let td = get_param(decl, first_real_arg);
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/trans/tvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,4 +720,3 @@ pub fn iter_vec_unboxed<'r,
let dataptr = get_dataptr(bcx, body_ptr);
return iter_vec_raw(bcx, dataptr, vec_ty, fill, f);
}

66 changes: 36 additions & 30 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1750,31 +1750,32 @@ macro_rules! def_type_content_sets(

def_type_content_sets!(
mod TC {
None = 0b0000__00000000__0000,
None = 0b00000000__00000000__0000,

// Things that are interior to the value (first nibble):
InteriorUnsized = 0b0000__00000000__0001,
// InteriorAll = 0b0000__00000000__1111,
InteriorUnsized = 0b00000000__00000000__0001,
// InteriorAll = 0b000000000__00000000__1111,

// Things that are owned by the value (second and third nibbles):
OwnsOwned = 0b0000__00000001__0000,
OwnsDtor = 0b0000__00000010__0000,
OwnsManaged /* see [1] below */ = 0b0000__00000100__0000,
OwnsAffine = 0b0000__00001000__0000,
OwnsAll = 0b0000__11111111__0000,

// Things that are reachable by the value in any way (fourth nibble):
ReachesNonsendAnnot = 0b0001__00000000__0000,
ReachesBorrowed = 0b0010__00000000__0000,
// ReachesManaged /* see [1] below */ = 0b0100__00000000__0000,
ReachesMutable = 0b1000__00000000__0000,
ReachesAll = 0b1111__00000000__0000,
OwnsOwned = 0b00000000__00000001__0000,
OwnsDtor = 0b00000000__00000010__0000,
OwnsAtManaged /* see [1] below */ = 0b00000000__00000100__0000,
OwnsAffine = 0b00000000__00001000__0000,
OwnsAll = 0b00000000__11111111__0000,

// Things that are reachable by the value in any way :
ReachesNonsendAnnot = 0b00000001__00000000__0000,
ReachesBorrowed = 0b00000010__00000000__0000,
// ReachesAtManaged /* see [1] below */ = 0b00000100__00000000__0000,
ReachesMutable = 0b00001000__00000000__0000,
ReachesNewManaged = 0b00010000__00000000__0000,
ReachesAll = 0b11111111__00000000__0000,

// Things that cause values to *move* rather than *copy*
Moves = 0b0000__00001011__0000,
Moves = 0b00000000__00001011__0000,

// Things that mean drop glue is necessary
NeedsDrop = 0b0000__00000111__0000,
NeedsDrop = 0b00000000__00000111__0000,

// Things that prevent values from being sent
//
Expand All @@ -1783,29 +1784,29 @@ def_type_content_sets!(
// both ReachesManaged and OwnsManaged so that when
// a parameter has a bound T:Send, we are able to deduce
// that it neither reaches nor owns a managed pointer.
Nonsendable = 0b0111__00000100__0000,
Nonsendable = 0b00010111__00000100__0000,

// Things that prevent values from being considered freezable
Nonfreezable = 0b1000__00000000__0000,
Nonfreezable = 0b00001000__00000000__0000,

// Things that prevent values from being considered 'static
Nonstatic = 0b0010__00000000__0000,
Nonstatic = 0b00000010__00000000__0000,

// Things that prevent values from being considered sized
Nonsized = 0b0000__00000000__0001,
Nonsized = 0b00000000__00000000__0001,

// Things that make values considered not POD (same as `Moves`)
Nonpod = 0b0000__00001111__0000,
Nonpod = 0b00000000__00001111__0000,

// Bits to set when a managed value is encountered
//
// [1] Do not set the bits TC::OwnsManaged or
// TC::ReachesManaged directly, instead reference
// TC::Managed to set them both at once.
Managed = 0b0100__00000100__0000,
AtManaged = 0b00000100__00000100__0000,

// All bits
All = 0b1111__11111111__1111
All = 0b11111111__11111111__1111
}
)

Expand Down Expand Up @@ -1840,8 +1841,12 @@ impl TypeContents {
!self.intersects(TC::Nonsendable)
}

pub fn owns_managed(&self) -> bool {
self.intersects(TC::OwnsManaged)
pub fn owns_at_managed(&self) -> bool {
self.intersects(TC::OwnsAtManaged)
}

pub fn reaches_new_managed(&self) -> bool {
self.intersects(TC::ReachesNewManaged)
}

pub fn is_freezable(&self, _: ctxt) -> bool {
Expand Down Expand Up @@ -1887,7 +1892,7 @@ impl TypeContents {
* Includes only those bits that still apply
* when indirected through a managed pointer (`@`)
*/
TC::Managed | (
TC::AtManaged | (
*self & TC::ReachesAll)
}

Expand Down Expand Up @@ -2055,7 +2060,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
}

ty_str(vstore_box) => {
TC::Managed
TC::AtManaged
}

ty_str(vstore_slice(r)) => {
Expand Down Expand Up @@ -2126,7 +2131,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
ty_opaque_closure_ptr(sigil) => {
match sigil {
ast::BorrowedSigil => TC::ReachesBorrowed,
ast::ManagedSigil => TC::Managed,
ast::ManagedSigil => TC::AtManaged,
ast::OwnedSigil => TC::OwnsOwned,
}
}
Expand Down Expand Up @@ -2156,7 +2161,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
-> TypeContents {
tc |
TC::ReachesMutable.when(has_attr(cx, did, "no_freeze")) |
TC::ReachesNonsendAnnot.when(has_attr(cx, did, "no_send"))
TC::ReachesNonsendAnnot.when(has_attr(cx, did, "no_send")) |
TC::ReachesNewManaged.when(has_attr(cx, did, "managed"))
}

fn borrowed_contents(region: ty::Region,
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4112,7 +4112,7 @@ pub fn check_intrinsic_type(ccx: @CrateCtxt, it: &ast::ForeignItem) {
ty::mk_nil())
}
"needs_drop" => (1u, ~[], ty::mk_bool()),
"owns_managed" => (1u, ~[], ty::mk_bool()),
"owns_at_managed" | "reaches_new_managed" => (1u, ~[], ty::mk_bool()),
"atomic_xchg" | "atomic_xadd" | "atomic_xsub" |
"atomic_xchg_acq" | "atomic_xadd_acq" | "atomic_xsub_acq" |
"atomic_xchg_rel" | "atomic_xadd_rel" | "atomic_xsub_rel" => {
Expand Down Expand Up @@ -4367,4 +4367,3 @@ pub fn check_intrinsic_type(ccx: @CrateCtxt, it: &ast::ForeignItem) {
ppaux::ty_to_str(ccx.tcx, fty)));
}
}

Loading