Skip to content

Commit 022a7b3

Browse files
committed
auto merge of #14322 : thestinger/rust/secret_santa_heap, r=alexcrichton
2 parents 22e2204 + f1ce693 commit 022a7b3

File tree

8 files changed

+67
-45
lines changed

8 files changed

+67
-45
lines changed

src/liballoc/heap.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
// FIXME: #13994: port to the sized deallocation API when available
12-
// FIXME: #13996: need a way to mark the `allocate` and `reallocate` return values as `noalias`
12+
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` and `nonnull`
1313

1414
use core::intrinsics::{abort, cttz32};
1515
use core::option::{None, Option};
@@ -119,14 +119,8 @@ pub fn stats_print() {
119119
/// The allocator for unique pointers.
120120
#[cfg(not(test))]
121121
#[lang="exchange_malloc"]
122-
#[inline(always)]
123-
pub unsafe fn exchange_malloc_(size: uint, align: uint) -> *mut u8 {
124-
exchange_malloc(size, align)
125-
}
126-
127-
/// The allocator for unique pointers.
128122
#[inline]
129-
pub unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
123+
unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
130124
// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
131125
// allocations can point to this `static`. It would be incorrect to use a null
132126
// pointer, due to enums assuming types like unique pointers are never null.
@@ -139,14 +133,20 @@ pub unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
139133
}
140134
}
141135

142-
#[cfg(not(test))]
136+
#[cfg(not(test), stage0)]
143137
#[lang="exchange_free"]
144138
#[inline]
145-
// FIXME: #13994 (rustc should pass align and size here)
146139
unsafe fn exchange_free(ptr: *mut u8) {
147140
deallocate(ptr, 0, 8);
148141
}
149142

143+
#[cfg(not(test), not(stage0))]
144+
#[lang="exchange_free"]
145+
#[inline]
146+
unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
147+
deallocate(ptr, size, align);
148+
}
149+
150150
// FIXME: #7496
151151
#[cfg(not(test))]
152152
#[lang="closure_exchange_malloc"]
@@ -167,16 +167,16 @@ unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, align: uin
167167
#[doc(hidden)]
168168
#[deprecated]
169169
#[cfg(not(test))]
170-
pub unsafe extern "C" fn rust_malloc(size: uint, align: uint) -> *mut u8 {
171-
exchange_malloc(size, align)
170+
pub unsafe extern "C" fn rust_allocate(size: uint, align: uint) -> *mut u8 {
171+
allocate(size, align)
172172
}
173173

174174
// hack for libcore
175175
#[no_mangle]
176176
#[doc(hidden)]
177177
#[deprecated]
178178
#[cfg(not(test))]
179-
pub unsafe extern "C" fn rust_free(ptr: *mut u8, size: uint, align: uint) {
179+
pub unsafe extern "C" fn rust_deallocate(ptr: *mut u8, size: uint, align: uint) {
180180
deallocate(ptr, size, align)
181181
}
182182

src/libarena/lib.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use std::mem;
3838
use std::num;
3939
use std::ptr::read;
4040
use std::rc::Rc;
41-
use std::rt::heap::exchange_malloc;
41+
use std::rt::heap::allocate;
4242

4343
// The way arena uses arrays is really deeply awful. The arrays are
4444
// allocated, and have capacities reserved, but the fill for the array
@@ -358,8 +358,7 @@ impl<T> TypedArenaChunk<T> {
358358
size = size.checked_add(&elems_size).unwrap();
359359

360360
let mut chunk = unsafe {
361-
let chunk = exchange_malloc(size,
362-
mem::min_align_of::<TypedArenaChunk<T>>());
361+
let chunk = allocate(size, mem::min_align_of::<TypedArenaChunk<T>>());
363362
let mut chunk: Box<TypedArenaChunk<T>> = mem::transmute(chunk);
364363
mem::overwrite(&mut chunk.next, next);
365364
chunk

src/libcore/should_not_exist.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ use str::StrSlice;
4444

4545
#[allow(ctypes)]
4646
extern {
47-
fn rust_malloc(size: uint, align: uint) -> *u8;
48-
fn rust_free(ptr: *u8, size: uint, align: uint);
47+
fn rust_allocate(size: uint, align: uint) -> *u8;
48+
fn rust_deallocate(ptr: *u8, size: uint, align: uint);
4949
}
5050

5151
unsafe fn alloc(cap: uint) -> *mut Vec<()> {
5252
let cap = cap.checked_add(&mem::size_of::<Vec<()>>()).unwrap();
5353
// this should use the real alignment, but the new representation will take care of that
54-
let ret = rust_malloc(cap, 8) as *mut Vec<()>;
54+
let ret = rust_allocate(cap, 8) as *mut Vec<()>;
5555
if ret.is_null() {
5656
intrinsics::abort();
5757
}
@@ -119,7 +119,7 @@ impl FromIterator<char> for ~str {
119119
&(*ptr).data,
120120
len);
121121
// FIXME: #13994: port to the sized deallocation API when available
122-
rust_free(ptr as *u8, 0, 8);
122+
rust_deallocate(ptr as *u8, 0, 8);
123123
mem::forget(ret);
124124
ret = mem::transmute(ptr2);
125125
ptr = ptr2;
@@ -191,7 +191,7 @@ impl<A: Clone> Clone for ~[A] {
191191
for j in range(0, *i as int) {
192192
ptr::read(&*p.offset(j));
193193
}
194-
rust_free(ret as *u8, 0, 8);
194+
rust_deallocate(ret as *u8, 0, 8);
195195
});
196196
mem::transmute(ret)
197197
}

src/librustc/middle/trans/cleanup.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,14 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
278278
fn schedule_free_value(&self,
279279
cleanup_scope: ScopeId,
280280
val: ValueRef,
281-
heap: Heap) {
281+
heap: Heap,
282+
content_ty: ty::t) {
282283
/*!
283284
* Schedules a call to `free(val)`. Note that this is a shallow
284285
* operation.
285286
*/
286287

287-
let drop = box FreeValue { ptr: val, heap: heap };
288+
let drop = box FreeValue { ptr: val, heap: heap, content_ty: content_ty };
288289

289290
debug!("schedule_free_value({:?}, val={}, heap={:?})",
290291
cleanup_scope,
@@ -847,6 +848,7 @@ pub enum Heap {
847848
pub struct FreeValue {
848849
ptr: ValueRef,
849850
heap: Heap,
851+
content_ty: ty::t
850852
}
851853

852854
impl Cleanup for FreeValue {
@@ -860,7 +862,7 @@ impl Cleanup for FreeValue {
860862
glue::trans_free(bcx, self.ptr)
861863
}
862864
HeapExchange => {
863-
glue::trans_exchange_free(bcx, self.ptr)
865+
glue::trans_exchange_free_ty(bcx, self.ptr, self.content_ty)
864866
}
865867
}
866868
}
@@ -931,7 +933,8 @@ pub trait CleanupMethods<'a> {
931933
fn schedule_free_value(&self,
932934
cleanup_scope: ScopeId,
933935
val: ValueRef,
934-
heap: Heap);
936+
heap: Heap,
937+
content_ty: ty::t);
935938
fn schedule_clean(&self,
936939
cleanup_scope: ScopeId,
937940
cleanup: Box<Cleanup>);

src/librustc/middle/trans/expr.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ fn trans_uniq_expr<'a>(bcx: &'a Block<'a>,
11831183
} else {
11841184
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
11851185
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
1186-
val, cleanup::HeapExchange);
1186+
val, cleanup::HeapExchange, contents_ty);
11871187
let bcx = trans_into(bcx, contents, SaveIn(val));
11881188
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
11891189
bcx
@@ -1205,7 +1205,7 @@ fn trans_managed_expr<'a>(bcx: &'a Block<'a>,
12051205

12061206
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
12071207
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
1208-
bx, cleanup::HeapManaged);
1208+
bx, cleanup::HeapManaged, contents_ty);
12091209
let bcx = trans_into(bcx, contents, SaveIn(body));
12101210
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
12111211
immediate_rvalue_bcx(bcx, bx, box_ty).to_expr_datumblock()
@@ -1789,13 +1789,14 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
17891789
let scope = cleanup::temporary_scope(bcx.tcx(), expr.id);
17901790
let ptr = Load(bcx, datum.val);
17911791
if !type_is_zero_size(bcx.ccx(), content_ty) {
1792-
bcx.fcx.schedule_free_value(scope, ptr, cleanup::HeapExchange);
1792+
bcx.fcx.schedule_free_value(scope, ptr, cleanup::HeapExchange, content_ty);
17931793
}
17941794
}
17951795
RvalueExpr(Rvalue { mode: ByValue }) => {
17961796
let scope = cleanup::temporary_scope(bcx.tcx(), expr.id);
17971797
if !type_is_zero_size(bcx.ccx(), content_ty) {
1798-
bcx.fcx.schedule_free_value(scope, datum.val, cleanup::HeapExchange);
1798+
bcx.fcx.schedule_free_value(scope, datum.val, cleanup::HeapExchange,
1799+
content_ty);
17991800
}
18001801
}
18011802
LvalueExpr => { }

src/librustc/middle/trans/glue.rs

+28-12
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,30 @@ pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> {
5050
Some(expr::Ignore)).bcx
5151
}
5252

53-
pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef)
54-
-> &'a Block<'a> {
53+
fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef, size: u64,
54+
align: u64) -> &'a Block<'a> {
5555
let _icx = push_ctxt("trans_exchange_free");
56+
let ccx = cx.ccx();
5657
callee::trans_lang_call(cx,
5758
langcall(cx, None, "", ExchangeFreeFnLangItem),
58-
[PointerCast(cx, v, Type::i8p(cx.ccx()))],
59+
[PointerCast(cx, v, Type::i8p(ccx)), C_uint(ccx, size as uint), C_uint(ccx, align as uint)],
5960
Some(expr::Ignore)).bcx
6061
}
6162

63+
pub fn trans_exchange_free_ty<'a>(bcx: &'a Block<'a>, ptr: ValueRef,
64+
content_ty: ty::t) -> &'a Block<'a> {
65+
let sizing_type = sizing_type_of(bcx.ccx(), content_ty);
66+
let content_size = llsize_of_alloc(bcx.ccx(), sizing_type);
67+
68+
// `Box<ZeroSizeType>` does not allocate.
69+
if content_size != 0 {
70+
let content_align = llalign_of_min(bcx.ccx(), sizing_type);
71+
trans_exchange_free(bcx, ptr, content_size, content_align)
72+
} else {
73+
bcx
74+
}
75+
}
76+
6277
pub fn take_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
6378
-> &'a Block<'a> {
6479
// NB: v is an *alias* of type t here, not a direct value.
@@ -87,17 +102,15 @@ fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
87102
ty::ty_vec(_, None) | ty::ty_str => t,
88103
_ => {
89104
let llty = sizing_type_of(ccx, typ);
90-
// Unique boxes do not allocate for zero-size types. The standard
91-
// library may assume that `free` is never called on the pointer
92-
// returned for `Box<ZeroSizeType>`.
105+
// `Box<ZeroSizeType>` does not allocate.
93106
if llsize_of_alloc(ccx, llty) == 0 {
94107
ty::mk_i8()
95108
} else {
96109
ty::mk_uniq(tcx, ty::mk_i8())
97110
}
98-
}
99-
}
100111
}
112+
}
113+
}
101114
_ => t
102115
}
103116
}
@@ -285,20 +298,22 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
285298
ty::ty_vec(mt, None) => {
286299
with_cond(bcx, not_null, |bcx| {
287300
let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, mt.ty);
288-
trans_exchange_free(bcx, llbox)
301+
// FIXME: #13994: the old `Box<[T]>` will not support sized deallocation
302+
trans_exchange_free(bcx, llbox, 0, 8)
289303
})
290304
}
291305
ty::ty_str => {
292306
with_cond(bcx, not_null, |bcx| {
293307
let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
294308
let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, unit_ty);
295-
trans_exchange_free(bcx, llbox)
309+
// FIXME: #13994: the old `Box<str>` will not support sized deallocation
310+
trans_exchange_free(bcx, llbox, 0, 8)
296311
})
297312
}
298313
_ => {
299314
with_cond(bcx, not_null, |bcx| {
300315
let bcx = drop_ty(bcx, llbox, content_ty);
301-
trans_exchange_free(bcx, llbox)
316+
trans_exchange_free_ty(bcx, llbox, content_ty)
302317
})
303318
}
304319
}
@@ -340,7 +355,8 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
340355
Call(bcx, dtor, [PointerCast(bcx, cdata, Type::i8p(bcx.ccx()))], []);
341356

342357
// Free the environment itself
343-
trans_exchange_free(bcx, env)
358+
// FIXME: #13994: pass align and size here
359+
trans_exchange_free(bcx, env, 0, 8)
344360
})
345361
}
346362
_ => {

src/librustc/middle/trans/tvec.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,11 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
287287
// Create a temporary scope lest execution should fail while
288288
// constructing the vector.
289289
let temp_scope = fcx.push_custom_cleanup_scope();
290+
291+
// FIXME: #13994: the old `Box<[T]> will not support sized deallocation, this is a placeholder
292+
let content_ty = vt.unit_ty;
290293
fcx.schedule_free_value(cleanup::CustomScope(temp_scope),
291-
val, cleanup::HeapExchange);
294+
val, cleanup::HeapExchange, content_ty);
292295

293296
let dataptr = get_dataptr(bcx, val);
294297

src/libstd/slice.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ use ops::Drop;
109109
use option::{None, Option, Some};
110110
use ptr::RawPtr;
111111
use ptr;
112-
use rt::heap::{exchange_malloc, deallocate};
112+
use rt::heap::{allocate, deallocate};
113113
use unstable::finally::try_finally;
114114
use vec::Vec;
115115

@@ -304,7 +304,7 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
304304

305305
unsafe {
306306
// this should pass the real required alignment
307-
let ret = exchange_malloc(size, 8) as *mut RawVec<()>;
307+
let ret = allocate(size, 8) as *mut RawVec<()>;
308308

309309
let a_size = mem::size_of::<T>();
310310
let a_size = if a_size == 0 {1} else {a_size};
@@ -968,7 +968,7 @@ mod tests {
968968
assert_eq!(v_b[0], 2);
969969
assert_eq!(v_b[1], 3);
970970

971-
// Test on exchange heap.
971+
// Test `Box<[T]>`
972972
let vec_unique = box [1, 2, 3, 4, 5, 6];
973973
let v_d = vec_unique.slice(1u, 6u).to_owned();
974974
assert_eq!(v_d.len(), 5u);

0 commit comments

Comments
 (0)