Optimize += [x] into a simple push operation
This is a preparation for making vectors always-on-the-heap again, which would cause way too much malloc traffic for this idiom. I will add an efficient std::vec::push in the future, and migrate += [x] to that instead. Reduces compiler code size by 3%
This commit is contained in:
parent
bead045f27
commit
e58c48bdda
@ -43,6 +43,7 @@ type upcalls =
|
||||
ivec_spill: ValueRef,
|
||||
ivec_resize_shared: ValueRef,
|
||||
ivec_spill_shared: ValueRef,
|
||||
ivec_push: ValueRef,
|
||||
cmp_type: ValueRef,
|
||||
log_type: ValueRef,
|
||||
dynastack_mark: ValueRef,
|
||||
@ -101,6 +102,9 @@ fn declare_upcalls(_tn: type_names, tydesc_type: TypeRef,
|
||||
ivec_spill_shared:
|
||||
d("ivec_spill_shared", [T_ptr(T_opaque_ivec()), T_int()],
|
||||
T_void()),
|
||||
ivec_push:
|
||||
d("ivec_push", [T_ptr(T_opaque_ivec()), T_ptr(tydesc_type),
|
||||
T_ptr(T_i8())], T_void()),
|
||||
cmp_type:
|
||||
dr("cmp_type",
|
||||
[T_ptr(T_i1()), taskptr_type, T_ptr(tydesc_type),
|
||||
|
@ -4351,16 +4351,32 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) ->
|
||||
ret rslt(bcx, C_nil());
|
||||
}
|
||||
ast::expr_assign_op(op, dst, src) {
|
||||
let t = ty::expr_ty(bcx_tcx(cx), src);
|
||||
let tcx = bcx_tcx(cx);
|
||||
let t = ty::expr_ty(tcx, src);
|
||||
let lhs_res = trans_lval(cx, dst);
|
||||
assert (lhs_res.is_mem);
|
||||
// FIXME Fill in lhs_res.res.bcx.sp
|
||||
|
||||
// Special case for `+= [x]`
|
||||
alt ty::struct(tcx, t) {
|
||||
ty::ty_vec(_) {
|
||||
alt src.node {
|
||||
ast::expr_vec(args, _) {
|
||||
let bcx = ivec::trans_append_literal
|
||||
(lhs_res.res.bcx, lhs_res.res.val, t, args);
|
||||
ret rslt(bcx, C_nil());
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
|
||||
// FIXME Fill in lhs_res.res.bcx.sp
|
||||
let rhs_res = trans_expr(lhs_res.res.bcx, src);
|
||||
if ty::type_is_sequence(bcx_tcx(cx), t) {
|
||||
if ty::type_is_sequence(tcx, t) {
|
||||
alt op {
|
||||
ast::add. {
|
||||
if ty::sequence_is_interior(bcx_tcx(cx), t) {
|
||||
if ty::sequence_is_interior(tcx, t) {
|
||||
ret ivec::trans_append(rhs_res.bcx, t, lhs_res.res.val,
|
||||
rhs_res.val);
|
||||
}
|
||||
|
@ -11,9 +11,6 @@ import trans::{call_memmove, trans_shared_malloc, llsize_of,
|
||||
new_sub_block_ctxt};
|
||||
import trans_common::*;
|
||||
|
||||
export trans_ivec, get_len_and_data, duplicate_heap_part, trans_add,
|
||||
trans_append, alloc_with_heap;
|
||||
|
||||
fn alloc_with_heap(bcx: @block_ctxt, typ: &ty::t, vecsz: uint) ->
|
||||
{bcx: @block_ctxt,
|
||||
unit_ty: ty::t,
|
||||
@ -342,15 +339,13 @@ fn reserve_space(cx: &@block_ctxt, llunitty: TypeRef, v: ValueRef,
|
||||
stack_no_spill_cx.llbb, stack_spill_cx.llbb]);
|
||||
ret rslt(next_cx, data_ptr);
|
||||
}
|
||||
fn trans_append(cx: &@block_ctxt, t: ty::t, orig_lhs: ValueRef,
|
||||
orig_rhs: ValueRef) -> result {
|
||||
fn trans_append(cx: &@block_ctxt, t: ty::t, lhs: ValueRef,
|
||||
rhs: ValueRef) -> result {
|
||||
// Cast to opaque interior vector types if necessary.
|
||||
let lhs;
|
||||
let rhs;
|
||||
if ty::type_has_dynamic_size(bcx_tcx(cx), t) {
|
||||
lhs = cx.build.PointerCast(orig_lhs, T_ptr(T_opaque_ivec()));
|
||||
rhs = cx.build.PointerCast(orig_rhs, T_ptr(T_opaque_ivec()));
|
||||
} else { lhs = orig_lhs; rhs = orig_rhs; }
|
||||
lhs = cx.build.PointerCast(lhs, T_ptr(T_opaque_ivec()));
|
||||
rhs = cx.build.PointerCast(rhs, T_ptr(T_opaque_ivec()));
|
||||
}
|
||||
|
||||
let unit_ty = ty::sequence_element_type(bcx_tcx(cx), t);
|
||||
let llunitty = type_of_or_i8(cx, unit_ty);
|
||||
@ -448,6 +443,24 @@ fn trans_append(cx: &@block_ctxt, t: ty::t, orig_lhs: ValueRef,
|
||||
ret rslt(next_cx, C_nil());
|
||||
}
|
||||
|
||||
fn trans_append_literal(bcx: &@block_ctxt, v: ValueRef, vec_ty: ty::t,
|
||||
vals: &[@ast::expr]) -> @block_ctxt {
|
||||
let elt_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
|
||||
let ti = none;
|
||||
let {bcx, val: td} = get_tydesc(bcx, elt_ty, false, ti).result;
|
||||
trans::lazily_emit_all_tydesc_glue(bcx, ti);
|
||||
let opaque_v = bcx.build.PointerCast(v, T_ptr(T_opaque_ivec()));
|
||||
for val in vals {
|
||||
let {bcx: e_bcx, val: elt} = trans::trans_expr(bcx, val);
|
||||
bcx = e_bcx;
|
||||
let spilled = trans::spill_if_immediate(bcx, elt, elt_ty);
|
||||
bcx.build.Call(bcx_ccx(bcx).upcalls.ivec_push,
|
||||
[bcx.fcx.lltaskptr, opaque_v, td,
|
||||
bcx.build.PointerCast(spilled, T_ptr(T_i8()))]);
|
||||
}
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
type alloc_result =
|
||||
{bcx: @block_ctxt,
|
||||
llptr: ValueRef,
|
||||
@ -756,3 +769,13 @@ fn duplicate_heap_part(cx: &@block_ctxt, orig_vptr: ValueRef,
|
||||
|
||||
ret rslt(next_cx, C_nil());
|
||||
}
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
||||
// End:
|
||||
//
|
||||
|
@ -394,6 +394,30 @@ upcall_ivec_spill_shared(rust_task *task,
|
||||
v->payload.ptr = heap_part;
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
upcall_ivec_push(rust_task* task, rust_ivec* v, type_desc* elt_ty, void* x) {
|
||||
LOG_UPCALL_ENTRY(task);
|
||||
bool is_interior = v->fill || !v->payload.ptr;
|
||||
size_t sz = elt_ty->size;
|
||||
size_t old_fill = is_interior ? v->fill : v->payload.ptr->fill;
|
||||
size_t new_sz = sz + old_fill;
|
||||
if (new_sz > v->alloc) {
|
||||
if (is_interior) {
|
||||
upcall_ivec_spill_shared(task, v, new_sz);
|
||||
is_interior = false;
|
||||
} else {
|
||||
upcall_ivec_resize_shared(task, v, new_sz);
|
||||
}
|
||||
} else {
|
||||
if (is_interior) v->fill = new_sz;
|
||||
else v->payload.ptr->fill = new_sz;
|
||||
}
|
||||
uint8_t* dataptr = is_interior ? &v->payload.data[0]
|
||||
: &v->payload.ptr->data[0];
|
||||
copy_elements(task, elt_ty, dataptr + old_fill, x, sz);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a token that can be used to deallocate all of the allocated space
|
||||
* space in the dynamic stack.
|
||||
|
@ -89,6 +89,7 @@ upcall_get_type_desc
|
||||
upcall_grow_task
|
||||
upcall_ivec_resize_shared
|
||||
upcall_ivec_spill_shared
|
||||
upcall_ivec_push
|
||||
upcall_kill
|
||||
upcall_log_double
|
||||
upcall_log_float
|
||||
|
Loading…
Reference in New Issue
Block a user