Skip to content

Commit fb0d4c4

Browse files
committed
---
yaml --- r: 44688 b: refs/heads/master c: 2f12e26 h: refs/heads/master v: v3
1 parent d315980 commit fb0d4c4

File tree

17 files changed

+234
-72
lines changed

17 files changed

+234
-72
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: ad414dec67f3f9583938a2a1212e104443fca798
2+
refs/heads/master: 2f12e26d06ac106c54b293f0125d2c9319ac4191
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: a6d9689399d091c3265f00434a69c551a61c28dc
55
refs/heads/try: ef355f6332f83371e4acf04fc4eb940ab41d78d3

trunk/src/libcore/cleanup.rs

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -111,45 +111,102 @@ struct Task {
111111
* This runs at task death to free all boxes.
112112
*/
113113

114+
struct AnnihilateStats {
115+
n_total_boxes: uint,
116+
n_unique_boxes: uint,
117+
n_bytes_freed: uint
118+
}
119+
120+
unsafe fn each_live_alloc(f: fn(box: *mut BoxRepr, uniq: bool) -> bool) {
121+
use managed;
122+
123+
let task: *Task = transmute(rustrt::rust_get_task());
124+
let box = (*task).boxed_region.live_allocs;
125+
let mut box: *mut BoxRepr = transmute(copy box);
126+
while box != mut_null() {
127+
let next = transmute(copy (*box).header.next);
128+
let uniq =
129+
(*box).header.ref_count == managed::raw::RC_MANAGED_UNIQUE;
130+
131+
if ! f(box, uniq) {
132+
break
133+
}
134+
135+
box = next
136+
}
137+
}
138+
139+
#[cfg(unix)]
140+
fn debug_mem() -> bool {
141+
use os;
142+
use libc;
143+
do os::as_c_charp("RUST_DEBUG_MEM") |p| {
144+
unsafe { libc::getenv(p) != null() }
145+
}
146+
}
147+
148+
#[cfg(windows)]
149+
fn debug_mem() -> bool {
150+
false
151+
}
152+
114153
/// Destroys all managed memory (i.e. @ boxes) held by the current task.
115154
#[cfg(notest)]
116155
#[lang="annihilate"]
117156
pub unsafe fn annihilate() {
118157
use rt::rt_free;
119158
use io::WriterUtil;
159+
use io;
160+
use libc;
161+
use sys;
162+
use managed;
120163

121-
let task: *Task = transmute(rustrt::rust_get_task());
164+
let mut stats = AnnihilateStats {
165+
n_total_boxes: 0,
166+
n_unique_boxes: 0,
167+
n_bytes_freed: 0
168+
};
122169

123170
// Pass 1: Make all boxes immortal.
124-
let box = (*task).boxed_region.live_allocs;
125-
let mut box: *mut BoxRepr = transmute(copy box);
126-
while box != mut_null() {
127-
debug!("making box immortal: %x", box as uint);
128-
(*box).header.ref_count = 0x77777777;
129-
box = transmute(copy (*box).header.next);
171+
for each_live_alloc |box, uniq| {
172+
stats.n_total_boxes += 1;
173+
if uniq {
174+
stats.n_unique_boxes += 1;
175+
} else {
176+
(*box).header.ref_count = managed::raw::RC_IMMORTAL;
177+
}
130178
}
131179

132180
// Pass 2: Drop all boxes.
133-
let box = (*task).boxed_region.live_allocs;
134-
let mut box: *mut BoxRepr = transmute(copy box);
135-
while box != mut_null() {
136-
debug!("calling drop glue for box: %x", box as uint);
137-
let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc);
138-
let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0));
139-
drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data));
140-
141-
box = transmute(copy (*box).header.next);
181+
for each_live_alloc |box, uniq| {
182+
if !uniq {
183+
let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc);
184+
let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0));
185+
drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data));
186+
}
142187
}
143188

144189
// Pass 3: Free all boxes.
145-
loop {
146-
let box = (*task).boxed_region.live_allocs;
147-
if box == null() { break; }
148-
let mut box: *mut BoxRepr = transmute(copy box);
149-
assert (*box).header.prev == null();
150-
151-
debug!("freeing box: %x", box as uint);
152-
rt_free(transmute(box));
190+
for each_live_alloc |box, uniq| {
191+
if !uniq {
192+
stats.n_bytes_freed +=
193+
(*((*box).header.type_desc)).size
194+
+ sys::size_of::<BoxRepr>();
195+
rt_free(transmute(box));
196+
}
197+
}
198+
199+
if debug_mem() {
200+
// We do logging here w/o allocation.
201+
let dbg = libc::STDERR_FILENO as io::fd_t;
202+
dbg.write_str("annihilator stats:");
203+
dbg.write_str("\n total_boxes: ");
204+
dbg.write_uint(stats.n_total_boxes);
205+
dbg.write_str("\n unique_boxes: ");
206+
dbg.write_uint(stats.n_unique_boxes);
207+
dbg.write_str("\n bytes_freed: ");
208+
dbg.write_uint(stats.n_bytes_freed);
209+
dbg.write_str("\n");
153210
}
154211
}
155212

trunk/src/libcore/managed.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ use managed::raw::BoxRepr;
1616
use prelude::*;
1717
use ptr;
1818

19+
1920
pub mod raw {
21+
22+
pub const RC_EXCHANGE_UNIQUE : uint = (-1) as uint;
23+
pub const RC_MANAGED_UNIQUE : uint = (-2) as uint;
24+
pub const RC_IMMORTAL : uint = 0x77777777;
25+
2026
use intrinsic::TyDesc;
2127

2228
pub struct BoxHeaderRepr {

trunk/src/libcore/vec.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -31,9 +31,14 @@ use vec;
3131

3232
#[abi = "cdecl"]
3333
pub extern mod rustrt {
34+
// These names are terrible. reserve_shared applies
35+
// to ~[] and reserve_shared_actual applies to @[].
3436
unsafe fn vec_reserve_shared(++t: *sys::TypeDesc,
3537
++v: **raw::VecRepr,
3638
++n: libc::size_t);
39+
unsafe fn vec_reserve_shared_actual(++t: *sys::TypeDesc,
40+
++v: **raw::VecRepr,
41+
++n: libc::size_t);
3742
}
3843

3944
/// Returns true if a vector contains no elements
@@ -59,11 +64,17 @@ pub pure fn same_length<T, U>(xs: &[const T], ys: &[const U]) -> bool {
5964
*/
6065
pub fn reserve<T>(v: &mut ~[T], n: uint) {
6166
// Only make the (slow) call into the runtime if we have to
67+
use managed;
6268
if capacity(v) < n {
6369
unsafe {
6470
let ptr: **raw::VecRepr = cast::transmute(v);
65-
rustrt::vec_reserve_shared(sys::get_type_desc::<T>(),
66-
ptr, n as size_t);
71+
let td = sys::get_type_desc::<T>();
72+
if ((**ptr).box_header.ref_count ==
73+
managed::raw::RC_MANAGED_UNIQUE) {
74+
rustrt::vec_reserve_shared_actual(td, ptr, n as size_t);
75+
} else {
76+
rustrt::vec_reserve_shared(td, ptr, n as size_t);
77+
}
6778
}
6879
}
6980
}

trunk/src/librustc/lib/llvm.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,7 +1379,12 @@ pub fn type_to_str_inner(names: @TypeNames, +outer0: &[TypeRef], ty: TypeRef)
13791379
type_to_str_inner(names, outer, out_ty)).to_managed();
13801380
}
13811381
Struct => {
1382-
let elts = struct_tys(ty);
1382+
let n_elts = llvm::LLVMCountStructElementTypes(ty) as uint;
1383+
let mut elts = vec::from_elem(n_elts, 0 as TypeRef);
1384+
if !elts.is_empty() {
1385+
llvm::LLVMGetStructElementTypes(
1386+
ty, ptr::to_mut_unsafe_ptr(&mut elts[0]));
1387+
}
13831388
// See [Note at-str]
13841389
return fmt!("{%s}", tys_str(names, outer, elts)).to_managed();
13851390
}
@@ -1440,16 +1445,17 @@ pub fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] {
14401445
}
14411446
}
14421447

1443-
pub fn struct_tys(struct_ty: TypeRef) -> ~[TypeRef] {
1448+
pub fn struct_element_types(struct_ty: TypeRef) -> ~[TypeRef] {
14441449
unsafe {
1445-
let n_elts = llvm::LLVMCountStructElementTypes(struct_ty) as uint;
1446-
if n_elts == 0 {
1447-
return ~[];
1450+
let count = llvm::LLVMCountStructElementTypes(struct_ty);
1451+
let mut buf: ~[TypeRef] =
1452+
vec::from_elem(count as uint,
1453+
cast::transmute::<uint,TypeRef>(0));
1454+
if buf.len() > 0 {
1455+
llvm::LLVMGetStructElementTypes(
1456+
struct_ty, ptr::to_mut_unsafe_ptr(&mut buf[0]));
14481457
}
1449-
let mut elts = vec::from_elem(n_elts, ptr::null());
1450-
llvm::LLVMGetStructElementTypes(
1451-
struct_ty, ptr::to_mut_unsafe_ptr(&mut elts[0]));
1452-
return elts;
1458+
return buf;
14531459
}
14541460
}
14551461

trunk/src/librustc/middle/trans/base.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ pub fn malloc_raw_dyn(bcx: block,
286286
let ccx = bcx.ccx();
287287

288288
let (mk_fn, langcall) = match heap {
289-
heap_shared => {
289+
heap_managed | heap_managed_unique => {
290290
(ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
291291
}
292292
heap_exchange => {
@@ -310,7 +310,9 @@ pub fn malloc_raw_dyn(bcx: block,
310310
langcall,
311311
~[tydesc, size],
312312
expr::SaveIn(rval));
313-
return rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty));
313+
let r = rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty));
314+
maybe_set_managed_unique_rc(r.bcx, r.val, heap);
315+
r
314316
}
315317

316318
/**
@@ -364,11 +366,31 @@ pub fn malloc_general(bcx: block, t: ty::t, heap: heap)
364366
}
365367
pub fn malloc_boxed(bcx: block, t: ty::t)
366368
-> MallocResult {
367-
malloc_general(bcx, t, heap_shared)
369+
malloc_general(bcx, t, heap_managed)
368370
}
371+
372+
pub fn heap_for_unique(bcx: block, t: ty::t) -> heap {
373+
if ty::type_contents(bcx.tcx(), t).contains_managed() {
374+
heap_managed_unique
375+
} else {
376+
heap_exchange
377+
}
378+
}
379+
380+
pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
381+
if heap == heap_managed_unique {
382+
// In cases where we are looking at a unique-typed allocation in the
383+
// managed heap (thus have refcount 1 from the managed allocator),
384+
// such as a ~(@foo) or such. These need to have their refcount forced
385+
// to -2 so the annihilator ignores them.
386+
let rc = GEPi(bcx, bx, [0u, abi::box_field_refcnt]);
387+
Store(bcx, C_int(bcx.ccx(), -2), rc);
388+
}
389+
}
390+
369391
pub fn malloc_unique(bcx: block, t: ty::t)
370392
-> MallocResult {
371-
malloc_general(bcx, t, heap_exchange)
393+
malloc_general(bcx, t, heap_for_unique(bcx, t))
372394
}
373395

374396
// Type descriptor and type glue stuff
@@ -2150,6 +2172,11 @@ pub fn trans_mod(ccx: @CrateContext, m: ast::_mod) {
21502172
}
21512173
}
21522174
2175+
pub fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
2176+
// Bit of a kludge: pick the fn typeref out of the pair.
2177+
return struct_elt(llpairty, 0u);
2178+
}
2179+
21532180
pub fn register_fn(ccx: @CrateContext,
21542181
sp: span,
21552182
+path: path,

trunk/src/librustc/middle/trans/cabi_x86_64.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use lib::llvm::{llvm, TypeRef, ValueRef, Integer, Pointer, Float, Double};
1515
use lib::llvm::{Struct, Array, Attribute};
1616
use lib::llvm::{StructRetAttribute, ByValAttribute};
17-
use lib::llvm::struct_tys;
1817
use middle::trans::common::*;
1918
use middle::trans::cabi::*;
2019

@@ -66,6 +65,19 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
6665
return (off + a - 1u) / a * a;
6766
}
6867

68+
fn struct_tys(ty: TypeRef) -> ~[TypeRef] {
69+
unsafe {
70+
let n = llvm::LLVMCountStructElementTypes(ty);
71+
if (n == 0) {
72+
return ~[];
73+
}
74+
let mut elts = vec::from_elem(n as uint, ptr::null());
75+
llvm::LLVMGetStructElementTypes(ty,
76+
ptr::to_mut_unsafe_ptr(&mut elts[0]));
77+
return elts;
78+
}
79+
}
80+
6981
fn ty_align(ty: TypeRef) -> uint {
7082
unsafe {
7183
return match llvm::LLVMGetTypeKind(ty) {

trunk/src/librustc/middle/trans/callee.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ pub fn trans_rtcall_or_lang_call_with_type_params(bcx: block,
380380
fty);
381381
let mut llfnty = type_of::type_of(callee.bcx.ccx(),
382382
substituted);
383-
llfnty = lib::llvm::struct_tys(llfnty)[0];
383+
llfnty = T_ptr(struct_elt(llfnty, 0));
384384
new_llval = PointerCast(callee.bcx, fn_data.llfn, llfnty);
385385
}
386386
_ => fail!()

trunk/src/librustc/middle/trans/closure.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,10 @@ pub fn allocate_cbox(bcx: block, sigil: ast::Sigil, cdata_ty: ty::t)
178178
// Allocate and initialize the box:
179179
match sigil {
180180
ast::ManagedSigil => {
181-
malloc_raw(bcx, cdata_ty, heap_shared)
181+
malloc_raw(bcx, cdata_ty, heap_managed)
182182
}
183183
ast::OwnedSigil => {
184-
malloc_raw(bcx, cdata_ty, heap_exchange)
184+
malloc_raw(bcx, cdata_ty, heap_for_unique(bcx, cdata_ty))
185185
}
186186
ast::BorrowedSigil => {
187187
let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
@@ -574,7 +574,7 @@ pub fn make_opaque_cbox_free_glue(
574574
// Free the ty descr (if necc) and the box itself
575575
match sigil {
576576
ast::ManagedSigil => glue::trans_free(bcx, cbox),
577-
ast::OwnedSigil => glue::trans_unique_free(bcx, cbox),
577+
ast::OwnedSigil => glue::trans_exchange_free(bcx, cbox),
578578
ast::BorrowedSigil => {
579579
bcx.sess().bug(~"impossible")
580580
}

0 commit comments

Comments
 (0)