Skip to content

Commit c6be352

Browse files
committed
rustc: Implement on-heap resizing for interior vectors
1 parent b7f043e commit c6be352

File tree

3 files changed

+23
-28
lines changed

3 files changed

+23
-28
lines changed

src/comp/middle/trans.rs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3718,10 +3718,10 @@ fn trans_vec_append(&@block_ctxt cx, &ty::t t,
37183718
dst, src, skip_null]));
37193719
}
37203720

3721-
// Returns a tuple consisting of a pointer to the length (to be updated), a
3722-
// pointer to the newly-reserved space, and a block context.
3721+
// Returns a tuple consisting of a pointer to the newly-reserved space and a
3722+
// block context. Updates the length appropriately.
37233723
fn reserve_ivec_space(&@block_ctxt cx, TypeRef llunitty, ValueRef v,
3724-
ValueRef len_needed) -> tup(ValueRef, ValueRef, @block_ctxt) {
3724+
ValueRef len_needed) -> result {
37253725
auto stack_len_ptr = cx.build.InBoundsGEP(v, [C_int(0),
37263726
C_uint(abi::ivec_elt_len)]);
37273727
auto stack_len = cx.build.Load(stack_len_ptr);
@@ -3755,7 +3755,7 @@ fn reserve_ivec_space(&@block_ctxt cx, TypeRef llunitty, ValueRef v,
37553755

37563756
// We're definitely on the heap. Check whether we need to resize.
37573757
auto heap_len_ptr = on_heap_cx.build.InBoundsGEP(heap_ptr, [C_int(0),
3758-
C_int(0)]);
3758+
C_uint(abi::ivec_heap_elt_len)]);
37593759
auto heap_len = on_heap_cx.build.Load(heap_len_ptr);
37603760
auto new_heap_len = on_heap_cx.build.Add(heap_len, len_needed);
37613761
auto heap_len_unscaled = on_heap_cx.build.UDiv(heap_len,
@@ -3770,6 +3770,7 @@ fn reserve_ivec_space(&@block_ctxt cx, TypeRef llunitty, ValueRef v,
37703770
// Case (1): We're on the heap and don't need to resize.
37713771
auto heap_data_no_resize = heap_no_resize_cx.build.InBoundsGEP(heap_ptr,
37723772
[C_int(0), C_uint(abi::ivec_heap_elt_elems), heap_len_unscaled]);
3773+
heap_no_resize_cx.build.Store(new_heap_len, heap_len_ptr);
37733774
heap_no_resize_cx.build.Br(next_cx.llbb);
37743775

37753776
// Case (2): We're on the heap and need to resize. This path is rare, so
@@ -3801,6 +3802,7 @@ fn reserve_ivec_space(&@block_ctxt cx, TypeRef llunitty, ValueRef v,
38013802
// Case (3): We're on the stack and don't need to spill.
38023803
auto stack_data_no_spill = stack_no_spill_cx.build.InBoundsGEP(v,
38033804
[C_int(0), C_uint(abi::ivec_elt_elems), stack_len_unscaled]);
3805+
stack_no_spill_cx.build.Store(new_stack_len, stack_len_ptr);
38043806
stack_no_spill_cx.build.Br(next_cx.llbb);
38053807

38063808
// Case (4): We're on the stack and need to spill. Like case (2), this
@@ -3824,16 +3826,12 @@ fn reserve_ivec_space(&@block_ctxt cx, TypeRef llunitty, ValueRef v,
38243826
stack_spill_cx.build.Br(next_cx.llbb);
38253827

38263828
// Phi together the different data pointers to get the result.
3827-
auto len_ptr = next_cx.build.Phi(T_ptr(T_int()),
3828-
[heap_len_ptr, heap_len_ptr, stack_len_ptr, heap_len_ptr_spill],
3829-
[heap_no_resize_cx.llbb, heap_resize_cx.llbb, stack_no_spill_cx.llbb,
3830-
stack_spill_cx.llbb]);
38313829
auto data_ptr = next_cx.build.Phi(T_ptr(llunitty),
38323830
[heap_data_no_resize, heap_data_resize, stack_data_no_spill,
38333831
heap_data_spill],
38343832
[heap_no_resize_cx.llbb, heap_resize_cx.llbb, stack_no_spill_cx.llbb,
38353833
stack_spill_cx.llbb]);
3836-
ret tup(len_ptr, data_ptr, next_cx);
3834+
ret res(next_cx, data_ptr);
38373835
}
38383836

38393837
fn trans_ivec_append(&@block_ctxt cx, &ty::t t, ValueRef lhs, ValueRef rhs)
@@ -3867,11 +3865,9 @@ fn trans_ivec_append(&@block_ctxt cx, &ty::t t, ValueRef lhs, ValueRef rhs)
38673865
auto rhs_data = rhs_len_and_data._1;
38683866
bcx = rhs_len_and_data._2;
38693867

3870-
auto lhs_len_ptr_and_data =
3871-
reserve_ivec_space(bcx, llunitty, lhs, rhs_len);
3872-
auto lhs_len_ptr = lhs_len_ptr_and_data._0;
3873-
auto lhs_data = lhs_len_ptr_and_data._1;
3874-
bcx = lhs_len_ptr_and_data._2;
3868+
rslt = reserve_ivec_space(bcx, llunitty, lhs, rhs_len);
3869+
auto lhs_data = rslt.val;
3870+
bcx = rslt.bcx;
38753871

38763872
// Work out the end pointer.
38773873
auto lhs_unscaled_idx = bcx.build.UDiv(rhs_len, llsize_of(llunitty));
@@ -3905,11 +3901,6 @@ fn trans_ivec_append(&@block_ctxt cx, &ty::t t, ValueRef lhs, ValueRef rhs)
39053901
[C_int(1)]), src_ptr);
39063902
post_copy_cx.build.Br(copy_loop_header_cx.llbb);
39073903

3908-
// Write in the new length.
3909-
auto new_len = next_cx.build.Add(next_cx.build.Load(lhs_len_ptr),
3910-
rhs_len);
3911-
next_cx.build.Store(new_len, lhs_len_ptr);
3912-
39133904
ret res(next_cx, C_nil());
39143905
}
39153906

@@ -5866,11 +5857,8 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann)
58665857
auto rslt = size_of(bcx, unit_ty);
58675858
auto unit_sz = rslt.val;
58685859
bcx = rslt.bcx;
5869-
rslt = align_of(bcx, unit_ty);
5870-
auto unit_align = rslt.val;
5871-
bcx = rslt.bcx;
58725860

5873-
auto llalen = bcx.build.Mul(unit_align, C_uint(abi::ivec_default_length));
5861+
auto llalen = bcx.build.Mul(unit_sz, C_uint(abi::ivec_default_length));
58745862

58755863
auto llunitty = type_of_or_i8(bcx, unit_ty);
58765864
auto llvecptr;
@@ -5938,7 +5926,7 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann)
59385926
auto lleltptr;
59395927
if (ty::type_has_dynamic_size(bcx.fcx.lcx.ccx.tcx, unit_ty)) {
59405928
lleltptr = bcx.build.InBoundsGEP(llfirsteltptr,
5941-
[bcx.build.Mul(C_uint(i), unit_align)]);
5929+
[bcx.build.Mul(C_uint(i), unit_sz)]);
59425930
} else {
59435931
lleltptr = bcx.build.InBoundsGEP(llfirsteltptr, [C_uint(i)]);
59445932
}

src/rt/rust_upcall.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,8 +581,15 @@ extern "C" CDECL void
581581
upcall_ivec_resize(rust_task *task,
582582
rust_ivec *v,
583583
size_t newsz) {
584-
// TODO
585-
task->fail(4);
584+
I(task->dom, !v->fill);
585+
586+
size_t new_alloc = next_power_of_two(newsz);
587+
rust_ivec_heap *new_heap_part = (rust_ivec_heap *)
588+
task->realloc(v->payload.ptr, new_alloc);
589+
590+
new_heap_part->fill = newsz;
591+
v->alloc = new_alloc;
592+
v->payload.ptr = new_heap_part;
586593
}
587594

588595
/**

src/rt/rust_util.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@ rust_ivec_heap
197197
union
198198
rust_ivec_payload
199199
{
200-
uint8_t data[]; // if on stack
201-
struct rust_ivec_heap *ptr; // if on heap
200+
rust_ivec_heap *ptr; // if on heap
201+
uint8_t data[]; // if on stack
202202
};
203203

204204
struct

0 commit comments

Comments
 (0)