auto merge of #17188 : thestinger/rust/tvec, r=pcwalton
`Box<[T]>` is created by allocating `Box<[T, ..n]>` and coercing it so this code path is never used. It's also broken because it clamps the capacity of the memory allocations to 4 elements and that's incompatible with sized deallocation. This dates back to when `~[T]` was a growable vector type implemented as: *{ { tydesc, ref_count, prev, next }, { length, capacity, data[] } } Since even empty vectors had to allocate, it started off the capacity of all vectors at 4 as a heuristic. It's not possible to grow `Box<[T]>` and there is no need for a memory allocation when it's empty, so it would be a terrible heuristic today even if it worked.
This commit is contained in:
commit
79a5448f41
@ -587,25 +587,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let contents_ty = expr_ty(bcx, &**contents);
|
||||
match ty::get(box_ty).sty {
|
||||
ty::ty_uniq(..) => {
|
||||
let is_vec = match contents.node {
|
||||
ast::ExprRepeat(..) | ast::ExprVec(..) => true,
|
||||
ast::ExprLit(lit) => match lit.node {
|
||||
ast::LitStr(..) => true,
|
||||
_ => false
|
||||
},
|
||||
_ => false
|
||||
};
|
||||
|
||||
if is_vec {
|
||||
// Special case for owned vectors.
|
||||
fcx.push_ast_cleanup_scope(contents.id);
|
||||
let datum = unpack_datum!(
|
||||
bcx, tvec::trans_uniq_vec(bcx, expr, &**contents));
|
||||
bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id);
|
||||
DatumBlock::new(bcx, datum)
|
||||
} else {
|
||||
trans_uniq_expr(bcx, box_ty, &**contents, contents_ty)
|
||||
}
|
||||
trans_uniq_expr(bcx, box_ty, &**contents, contents_ty)
|
||||
}
|
||||
ty::ty_box(..) => {
|
||||
trans_managed_expr(bcx, box_ty, &**contents, contents_ty)
|
||||
|
@ -13,11 +13,9 @@
|
||||
use back::abi;
|
||||
use llvm;
|
||||
use llvm::{ValueRef};
|
||||
use middle::lang_items::StrDupUniqFnLangItem;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::base;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::callee;
|
||||
use middle::trans::cleanup;
|
||||
use middle::trans::cleanup::CleanupMethods;
|
||||
use middle::trans::common::*;
|
||||
@ -241,94 +239,6 @@ pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trans_uniq_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
uniq_expr: &ast::Expr,
|
||||
content_expr: &ast::Expr)
|
||||
-> DatumBlock<'blk, 'tcx, Expr> {
|
||||
/*!
|
||||
* Box<[...]> and "...".to_string() allocate boxes in the exchange heap and write
|
||||
* the array elements into them.
|
||||
*/
|
||||
|
||||
debug!("trans_uniq_vec(uniq_expr={})", bcx.expr_to_string(uniq_expr));
|
||||
let fcx = bcx.fcx;
|
||||
let ccx = fcx.ccx;
|
||||
|
||||
// Handle "".to_string().
|
||||
match content_expr.node {
|
||||
ast::ExprLit(lit) => {
|
||||
match lit.node {
|
||||
ast::LitStr(ref s, _) => {
|
||||
let llptrval = C_cstr(ccx, (*s).clone(), false);
|
||||
let llptrval = PointerCast(bcx, llptrval, Type::i8p(ccx));
|
||||
let llsizeval = C_uint(ccx, s.get().len());
|
||||
let typ = ty::mk_uniq(bcx.tcx(), ty::mk_str(bcx.tcx()));
|
||||
let lldestval = rvalue_scratch_datum(bcx,
|
||||
typ,
|
||||
"");
|
||||
let alloc_fn = langcall(bcx,
|
||||
Some(lit.span),
|
||||
"",
|
||||
StrDupUniqFnLangItem);
|
||||
let bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
alloc_fn,
|
||||
[ llptrval, llsizeval ],
|
||||
Some(expr::SaveIn(lldestval.val))).bcx;
|
||||
return DatumBlock::new(bcx, lldestval).to_expr_datumblock();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let vt = vec_types_from_expr(bcx, content_expr);
|
||||
let count = elements_required(bcx, content_expr);
|
||||
debug!(" vt={}, count={:?}", vt.to_string(ccx), count);
|
||||
let vec_ty = node_id_type(bcx, uniq_expr.id);
|
||||
|
||||
let llty = type_of::type_of(ccx, vt.unit_ty);
|
||||
let unit_sz = nonzero_llsize_of(ccx, llty);
|
||||
let llcount = if count < 4u {
|
||||
C_int(ccx, 4)
|
||||
} else {
|
||||
C_uint(ccx, count)
|
||||
};
|
||||
let alloc = Mul(bcx, llcount, unit_sz);
|
||||
let llty_ptr = llty.ptr_to();
|
||||
let align = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint);
|
||||
let Result { bcx: bcx, val: dataptr } = malloc_raw_dyn(bcx,
|
||||
llty_ptr,
|
||||
vec_ty,
|
||||
alloc,
|
||||
align);
|
||||
|
||||
// Create a temporary scope lest execution should fail while
|
||||
// constructing the vector.
|
||||
let temp_scope = fcx.push_custom_cleanup_scope();
|
||||
|
||||
fcx.schedule_free_slice(cleanup::CustomScope(temp_scope),
|
||||
dataptr, alloc, align, cleanup::HeapExchange);
|
||||
|
||||
debug!(" alloc_uniq_vec() returned dataptr={}, len={}",
|
||||
bcx.val_to_string(dataptr), count);
|
||||
|
||||
let bcx = write_content(bcx, &vt, uniq_expr,
|
||||
content_expr, SaveIn(dataptr));
|
||||
|
||||
fcx.pop_custom_cleanup_scope(temp_scope);
|
||||
|
||||
if ty::type_is_sized(bcx.tcx(), vec_ty) {
|
||||
immediate_rvalue_bcx(bcx, dataptr, vec_ty).to_expr_datumblock()
|
||||
} else {
|
||||
let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
|
||||
Store(bcx, dataptr, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
|
||||
Store(bcx, llcount, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
|
||||
DatumBlock::new(bcx, scratch.to_expr_datum())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
vt: &VecTypes,
|
||||
vstore_expr: &ast::Expr,
|
||||
|
Loading…
x
Reference in New Issue
Block a user