Skip to content

Commit 03a5eb4

Browse files
committed
add an align parameter to exchange_malloc
Closes #13094
1 parent 1b1ca6d commit 03a5eb4

File tree

6 files changed

+101
-15
lines changed

6 files changed

+101
-15
lines changed

src/libarena/lib.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use std::cmp;
3333
use std::intrinsics::{TyDesc, get_tydesc};
3434
use std::intrinsics;
3535
use std::mem;
36+
use std::mem::min_align_of;
3637
use std::num;
3738
use std::ptr::read;
3839
use std::rc::Rc;
@@ -204,7 +205,7 @@ impl Arena {
204205
#[inline]
205206
fn alloc_copy<'a, T>(&'a mut self, op: || -> T) -> &'a T {
206207
unsafe {
207-
let ptr = self.alloc_copy_inner(mem::size_of::<T>(), mem::min_align_of::<T>());
208+
let ptr = self.alloc_copy_inner(mem::size_of::<T>(), min_align_of::<T>());
208209
let ptr: *mut T = transmute(ptr);
209210
mem::move_val_init(&mut (*ptr), op());
210211
return transmute(ptr);
@@ -261,7 +262,7 @@ impl Arena {
261262
unsafe {
262263
let tydesc = get_tydesc::<T>();
263264
let (ty_ptr, ptr) =
264-
self.alloc_noncopy_inner(mem::size_of::<T>(), mem::min_align_of::<T>());
265+
self.alloc_noncopy_inner(mem::size_of::<T>(), min_align_of::<T>());
265266
let ty_ptr: *mut uint = transmute(ty_ptr);
266267
let ptr: *mut T = transmute(ptr);
267268
// Write in our tydesc along with a bit indicating that it
@@ -353,11 +354,12 @@ struct TypedArenaChunk<T> {
353354
}
354355

355356
impl<T> TypedArenaChunk<T> {
357+
#[cfg(stage0)]
356358
#[inline]
357359
fn new(next: Option<Box<TypedArenaChunk<T>>>, capacity: uint)
358360
-> Box<TypedArenaChunk<T>> {
359361
let mut size = mem::size_of::<TypedArenaChunk<T>>();
360-
size = round_up(size, mem::min_align_of::<T>());
362+
size = round_up(size, min_align_of::<T>());
361363
let elem_size = mem::size_of::<T>();
362364
let elems_size = elem_size.checked_mul(&capacity).unwrap();
363365
size = size.checked_add(&elems_size).unwrap();
@@ -373,6 +375,27 @@ impl<T> TypedArenaChunk<T> {
373375
chunk
374376
}
375377

378+
#[inline]
379+
#[cfg(not(stage0))]
380+
fn new(next: Option<Box<TypedArenaChunk<T>>>, capacity: uint)
381+
-> Box<TypedArenaChunk<T>> {
382+
let mut size = mem::size_of::<TypedArenaChunk<T>>();
383+
size = round_up(size, mem::min_align_of::<T>());
384+
let elem_size = mem::size_of::<T>();
385+
let elems_size = elem_size.checked_mul(&capacity).unwrap();
386+
size = size.checked_add(&elems_size).unwrap();
387+
388+
let mut chunk = unsafe {
389+
let chunk = global_heap::exchange_malloc(size, min_align_of::<TypedArenaChunk<T>>());
390+
let mut chunk: Box<TypedArenaChunk<T>> = cast::transmute(chunk);
391+
mem::move_val_init(&mut chunk.next, next);
392+
chunk
393+
};
394+
395+
chunk.capacity = capacity;
396+
chunk
397+
}
398+
376399
/// Destroys this arena chunk. If the type descriptor is supplied, the
377400
/// drop glue is called; otherwise, drop glue is not called.
378401
#[inline]
@@ -402,7 +425,7 @@ impl<T> TypedArenaChunk<T> {
402425
fn start(&self) -> *u8 {
403426
let this: *TypedArenaChunk<T> = self;
404427
unsafe {
405-
cast::transmute(round_up(this.offset(1) as uint, mem::min_align_of::<T>()))
428+
cast::transmute(round_up(this.offset(1) as uint, min_align_of::<T>()))
406429
}
407430
}
408431

src/libcore/should_not_exist.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,29 @@ use str::StrSlice;
2929

3030
#[allow(ctypes)]
3131
extern {
32-
fn malloc(size: uint) -> *u8;
33-
fn free(ptr: *u8);
32+
#[cfg(stage0)]
33+
fn rust_malloc(size: uint) -> *u8;
34+
#[cfg(not(stage0))]
35+
fn rust_malloc(size: uint, align: uint) -> *u8;
36+
fn rust_free(ptr: *u8);
3437
}
3538

39+
#[cfg(stage0)]
3640
unsafe fn alloc(cap: uint) -> *mut Vec<()> {
3741
let cap = cap.checked_add(&mem::size_of::<Vec<()>>()).unwrap();
38-
let ret = malloc(cap) as *mut Vec<()>;
42+
let ret = rust_malloc(cap) as *mut Vec<()>;
43+
if ret.is_null() {
44+
intrinsics::abort();
45+
}
46+
(*ret).fill = 0;
47+
(*ret).alloc = cap;
48+
ret
49+
}
50+
51+
#[cfg(not(stage0))]
52+
unsafe fn alloc(cap: uint) -> *mut Vec<()> {
53+
let cap = cap.checked_add(&mem::size_of::<Vec<()>>()).unwrap();
54+
let ret = rust_malloc(cap, 8) as *mut Vec<()>;
3955
if ret.is_null() {
4056
intrinsics::abort();
4157
}
@@ -102,7 +118,7 @@ impl FromIterator<char> for ~str {
102118
ptr::copy_nonoverlapping_memory(&mut (*ptr2).data,
103119
&(*ptr).data,
104120
len);
105-
free(ptr as *u8);
121+
rust_free(ptr as *u8);
106122
cast::forget(ret);
107123
ret = cast::transmute(ptr2);
108124
ptr = ptr2;
@@ -172,7 +188,7 @@ impl<A: Clone> Clone for ~[A] {
172188
for j in range(0, *i as int) {
173189
ptr::read(&*p.offset(j));
174190
}
175-
free(ret as *u8);
191+
rust_free(ret as *u8);
176192
});
177193
cast::transmute(ret)
178194
}

src/librustc/middle/trans/base.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,15 +345,16 @@ fn require_alloc_fn(bcx: &Block, info_ty: ty::t, it: LangItem) -> ast::DefId {
345345

346346
pub fn malloc_raw_dyn<'a>(bcx: &'a Block<'a>,
347347
ptr_ty: ty::t,
348-
size: ValueRef)
348+
size: ValueRef,
349+
align: ValueRef)
349350
-> Result<'a> {
350351
let _icx = push_ctxt("malloc_raw_exchange");
351352
let ccx = bcx.ccx();
352353

353354
// Allocate space:
354355
let r = callee::trans_lang_call(bcx,
355356
require_alloc_fn(bcx, ptr_ty, ExchangeMallocFnLangItem),
356-
[size],
357+
[size, align],
357358
None);
358359

359360
let llty_ptr = type_of::type_of(ccx, ptr_ty);

src/librustc/middle/trans/expr.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use middle::typeck::MethodCall;
6767
use util::common::indenter;
6868
use util::ppaux::Repr;
6969
use util::nodemap::NodeMap;
70-
use middle::trans::machine::{llsize_of, llsize_of_alloc};
70+
use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_alloc};
7171
use middle::trans::type_::Type;
7272

7373
use syntax::ast;
@@ -1170,10 +1170,11 @@ fn trans_uniq_expr<'a>(bcx: &'a Block<'a>,
11701170
let fcx = bcx.fcx;
11711171
let llty = type_of::type_of(bcx.ccx(), contents_ty);
11721172
let size = llsize_of(bcx.ccx(), llty);
1173+
let align = C_uint(bcx.ccx(), llalign_of_min(bcx.ccx(), llty) as uint);
11731174
// We need to a make a pointer type because box_ty is ty_bot
11741175
// if content_ty is, e.g. box fail!().
11751176
let real_box_ty = ty::mk_uniq(bcx.tcx(), contents_ty);
1176-
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size);
1177+
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size, align);
11771178
// Unique boxes do not allocate for zero-size types. The standard library
11781179
// may assume that `free` is never called on the pointer returned for
11791180
// `Box<ZeroSizeType>`.

src/librustc/middle/trans/tvec.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,9 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
278278

279279
let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
280280

281-
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize);
281+
// ~[T] is not going to be changed to support alignment, since it's obsolete.
282+
let align = C_uint(ccx, 8);
283+
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize, align);
282284
Store(bcx, fill, GEPi(bcx, val, [0u, abi::vec_elt_fill]));
283285
Store(bcx, alloc, GEPi(bcx, val, [0u, abi::vec_elt_alloc]));
284286

src/libstd/rt/global_heap.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 {
6868
}
6969

7070
/// The allocator for unique pointers without contained managed pointers.
71-
#[cfg(not(test))]
71+
#[cfg(not(test), stage0)]
7272
#[lang="exchange_malloc"]
7373
#[inline]
7474
pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
@@ -85,6 +85,23 @@ pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
8585
}
8686
}
8787

88+
/// The allocator for unique pointers without contained managed pointers.
89+
#[cfg(not(test), not(stage0))]
90+
#[lang="exchange_malloc"]
91+
#[inline]
92+
pub unsafe fn exchange_malloc(size: uint, _align: uint) -> *mut u8 {
93+
// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
94+
// allocations can point to this `static`. It would be incorrect to use a null
95+
// pointer, due to enums assuming types like unique pointers are never null.
96+
static EMPTY: () = ();
97+
98+
if size == 0 {
99+
&EMPTY as *() as *mut u8
100+
} else {
101+
malloc_raw(size)
102+
}
103+
}
104+
88105
// FIXME: #7496
89106
#[cfg(not(test))]
90107
#[lang="closure_exchange_malloc"]
@@ -118,6 +135,32 @@ pub unsafe fn exchange_free(ptr: *u8) {
118135
free(ptr as *mut c_void);
119136
}
120137

138+
// hack for libcore
139+
#[no_mangle]
140+
#[doc(hidden)]
141+
#[deprecated]
142+
#[cfg(stage0)]
143+
pub extern "C" fn rust_malloc(size: uint) -> *mut u8 {
144+
unsafe { exchange_malloc(size) }
145+
}
146+
147+
// hack for libcore
148+
#[no_mangle]
149+
#[doc(hidden)]
150+
#[deprecated]
151+
#[cfg(not(stage0))]
152+
pub extern "C" fn rust_malloc(size: uint, align: uint) -> *mut u8 {
153+
unsafe { exchange_malloc(size, align) }
154+
}
155+
156+
// hack for libcore
157+
#[no_mangle]
158+
#[doc(hidden)]
159+
#[deprecated]
160+
pub extern "C" fn rust_free(ptr: *u8) {
161+
unsafe { exchange_free(ptr) }
162+
}
163+
121164
#[cfg(test)]
122165
mod bench {
123166
extern crate test;

0 commit comments

Comments
 (0)