Skip to content

Commit

Permalink
Switch box_free to take the destructured contents of Box
Browse files Browse the repository at this point in the history
As of now, Box only contains a Unique pointer, so this is the sole
argument to box_free. Consequently, we remove the code supporting
the previous box_free signature. We however keep the old definition
for bootstrapping purpose.
  • Loading branch information
glandium committed Apr 25, 2018
1 parent 64f5233 commit bd8c177
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 56 deletions.
14 changes: 11 additions & 3 deletions src/liballoc/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
issue = "32838")]

use core::intrinsics::{min_align_of_val, size_of_val};
use core::ptr::NonNull;
use core::ptr::{NonNull, Unique};
use core::usize;

#[doc(inline)]
Expand Down Expand Up @@ -170,9 +170,17 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
}
}

#[cfg_attr(not(test), lang = "box_free")]
#[cfg(stage0)]
#[lang = "box_free"]
#[inline]
unsafe fn old_box_free<T: ?Sized>(ptr: *mut T) {
box_free(Unique::new_unchecked(ptr))
}

#[cfg_attr(not(any(test, stage0)), lang = "box_free")]
#[inline]
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
let ptr = ptr.as_ptr();
let size = size_of_val(&*ptr);
let align = min_align_of_val(&*ptr);
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
Expand Down
5 changes: 3 additions & 2 deletions src/liballoc/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,8 @@ impl<T: ?Sized> Arc<T> {

fn from_box(v: Box<T>) -> Arc<T> {
unsafe {
let bptr = Box::into_raw(v);
let box_unique = Box::into_unique(v);
let bptr = box_unique.as_ptr();

let value_size = size_of_val(&*bptr);
let ptr = Self::allocate_for_ptr(bptr);
Expand All @@ -578,7 +579,7 @@ impl<T: ?Sized> Arc<T> {
value_size);

// Free the allocation without dropping its contents
box_free(bptr);
box_free(box_unique);

Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
Expand Down
5 changes: 3 additions & 2 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,8 @@ impl<T: ?Sized> Rc<T> {

fn from_box(v: Box<T>) -> Rc<T> {
unsafe {
let bptr = Box::into_raw(v);
let box_unique = Box::into_unique(v);
let bptr = box_unique.as_ptr();

let value_size = size_of_val(&*bptr);
let ptr = Self::allocate_for_ptr(bptr);
Expand All @@ -693,7 +694,7 @@ impl<T: ?Sized> Rc<T> {
value_size);

// Free the allocation without dropping its contents
box_free(bptr);
box_free(box_unique);

Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
Expand Down
61 changes: 12 additions & 49 deletions src/librustc_mir/util/elaborate_drops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -879,56 +879,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
let tcx = self.tcx();
let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
let free_sig = tcx.fn_sig(free_func).skip_binder().clone();
let free_inputs = free_sig.inputs();
// If the box_free function takes a *mut T, transform the Box into
// such a pointer before calling box_free. Otherwise, pass it all
// the fields in the Box as individual arguments.
let (stmts, args) = if free_inputs.len() == 1 && free_inputs[0].is_mutable_pointer() {
let ty = substs.type_at(0);
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
ty: ty,
mutbl: hir::Mutability::MutMutable
});
let ptr_ty = tcx.mk_mut_ptr(ty);
let ref_tmp = Place::Local(self.new_temp(ref_ty));
let ptr_tmp = Place::Local(self.new_temp(ptr_ty));
let stmts = vec![
self.assign(&ref_tmp, Rvalue::Ref(
tcx.types.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
self.place.clone().deref()
)),
self.assign(&ptr_tmp, Rvalue::Cast(
CastKind::Misc,
Operand::Move(ref_tmp),
ptr_ty,
)),
];
(stmts, vec![Operand::Move(ptr_tmp)])
} else {
let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
let field = Field::new(i);
let field_ty = f.ty(self.tcx(), substs);
Operand::Move(self.place.clone().field(field, field_ty))
}).collect();
(vec![], args)
};
let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
let field = Field::new(i);
let field_ty = f.ty(self.tcx(), substs);
Operand::Move(self.place.clone().field(field, field_ty))
}).collect();

let free_block = BasicBlockData {
statements: stmts,
terminator: Some(Terminator {
kind: TerminatorKind::Call {
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
args: args,
destination: Some((unit_temp, target)),
cleanup: None
}, // FIXME(#43234)
source_info: self.source_info,
}),
is_cleanup: unwind.is_cleanup()
};
let free_block = self.elaborator.patch().new_block(free_block);
let call = TerminatorKind::Call {
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
args: args,
destination: Some((unit_temp, target)),
cleanup: None
}; // FIXME(#43234)
let free_block = self.new_block(unwind, call);

let block_start = Location { block: free_block, statement_index: 0 };
self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow);
Expand Down

0 comments on commit bd8c177

Please sign in to comment.