Skip to content

Commit deca79f

Browse files
committed
Merge pull request #634 from robarnold/upstream-stable
Allocate ivecs out of the kernel pool
2 parents 5547e5d + f611717 commit deca79f

File tree

8 files changed

+188
-12
lines changed

8 files changed

+188
-12
lines changed

src/comp/back/upcall.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ type upcalls =
4747
ValueRef exit,
4848
ValueRef malloc,
4949
ValueRef free,
50+
ValueRef shared_malloc,
51+
ValueRef shared_free,
5052
ValueRef mark,
5153
ValueRef new_str,
5254
ValueRef dup_str,
@@ -56,7 +58,9 @@ type upcalls =
5658
ValueRef new_task,
5759
ValueRef start_task,
5860
ValueRef ivec_resize,
59-
ValueRef ivec_spill);
61+
ValueRef ivec_spill,
62+
ValueRef ivec_resize_shared,
63+
ValueRef ivec_spill_shared);
6064

6165
fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls {
6266
fn decl(type_names tn, ModuleRef llmod, str name, vec[TypeRef] tys,
@@ -97,6 +101,9 @@ fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls {
97101
malloc=d("malloc", [T_size_t(), T_ptr(T_tydesc(tn))],
98102
T_ptr(T_i8())),
99103
free=dv("free", [T_ptr(T_i8()), T_int()]),
104+
shared_malloc=d("shared_malloc",
105+
[T_size_t(), T_ptr(T_tydesc(tn))], T_ptr(T_i8())),
106+
shared_free=dv("shared_free", [T_ptr(T_i8())]),
100107
mark=d("mark", [T_ptr(T_i8())], T_int()),
101108
new_str=d("new_str", [T_ptr(T_i8()), T_size_t()],
102109
T_ptr(T_str())),
@@ -119,7 +126,11 @@ fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls {
119126
ivec_resize=d("ivec_resize", [T_ptr(T_opaque_ivec()), T_int()],
120127
T_void()),
121128
ivec_spill=d("ivec_spill", [T_ptr(T_opaque_ivec()), T_int()],
122-
T_void()));
129+
T_void()),
130+
ivec_resize_shared=d("ivec_resize_shared",
131+
[T_ptr(T_opaque_ivec()), T_int()], T_void()),
132+
ivec_spill_shared=d("ivec_spill_shared",
133+
[T_ptr(T_opaque_ivec()), T_int()], T_void()));
123134
}
124135
//
125136
// Local Variables:

src/comp/middle/trans.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,12 @@ fn trans_non_gc_free(&@block_ctxt cx, ValueRef v) -> result {
11861186
ret rslt(cx, C_int(0));
11871187
}
11881188

1189+
fn trans_shared_free(&@block_ctxt cx, ValueRef v) -> result {
1190+
cx.build.Call(cx.fcx.lcx.ccx.upcalls.shared_free,
1191+
[cx.fcx.lltaskptr, cx.build.PointerCast(v, T_ptr(T_i8()))]);
1192+
ret rslt(cx, C_int(0));
1193+
}
1194+
11891195
fn find_scope_cx(&@block_ctxt cx) -> @block_ctxt {
11901196
if (cx.kind != NON_SCOPE_BLOCK) { ret cx; }
11911197
alt (cx.parent) {
@@ -1614,6 +1620,18 @@ fn trans_raw_malloc(&@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) ->
16141620
ret rslt(cx, cx.build.PointerCast(rval, llptr_ty));
16151621
}
16161622

1623+
// trans_shared_malloc: expects a type indicating which pointer type we want
1624+
// and a size indicating how much space we want malloc'd.
1625+
fn trans_shared_malloc(&@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) ->
1626+
result {
1627+
// FIXME: need a table to collect tydesc globals.
1628+
1629+
auto tydesc = C_null(T_ptr(T_tydesc(cx.fcx.lcx.ccx.tn)));
1630+
auto rval =
1631+
cx.build.Call(cx.fcx.lcx.ccx.upcalls.shared_malloc,
1632+
[cx.fcx.lltaskptr, llsize, tydesc]);
1633+
ret rslt(cx, cx.build.PointerCast(rval, llptr_ty));
1634+
}
16171635

16181636
// trans_malloc_boxed: expects an unboxed type and returns a pointer to enough
16191637
// space for something of that type, along with space for a reference count;
@@ -2133,7 +2151,7 @@ fn maybe_free_ivec_heap_part(&@block_ctxt cx, ValueRef v0, ty::t unit_ty) ->
21332151
auto m = maybe_on_heap_cx.build.InBoundsGEP(stub_ptr, v);
21342152
maybe_on_heap_cx.build.Load(m)
21352153
};
2136-
auto after_free_cx = trans_non_gc_free(maybe_on_heap_cx, heap_ptr).bcx;
2154+
auto after_free_cx = trans_shared_free(maybe_on_heap_cx, heap_ptr).bcx;
21372155
after_free_cx.build.Br(next_cx.llbb);
21382156
ret rslt(next_cx, C_nil());
21392157
}
@@ -3673,7 +3691,8 @@ mod ivec {
36733691
{
36743692
auto p =
36753693
heap_resize_cx.build.PointerCast(v, T_ptr(T_opaque_ivec()));
3676-
heap_resize_cx.build.Call(cx.fcx.lcx.ccx.upcalls.ivec_resize,
3694+
auto upcall = cx.fcx.lcx.ccx.upcalls.ivec_resize_shared;
3695+
heap_resize_cx.build.Call(upcall,
36773696
[cx.fcx.lltaskptr, p, new_heap_len]);
36783697
}
36793698
auto heap_ptr_resize =
@@ -3713,7 +3732,8 @@ mod ivec {
37133732
{
37143733
auto p =
37153734
stack_spill_cx.build.PointerCast(v, T_ptr(T_opaque_ivec()));
3716-
stack_spill_cx.build.Call(cx.fcx.lcx.ccx.upcalls.ivec_spill,
3735+
auto upcall = cx.fcx.lcx.ccx.upcalls.ivec_spill_shared;
3736+
stack_spill_cx.build.Call(upcall,
37173737
[cx.fcx.lltaskptr, p, new_stack_len]);
37183738
}
37193739
auto spill_stub =
@@ -3963,7 +3983,7 @@ mod ivec {
39633983
heap_cx.build.InBoundsGEP(stub_ptr_heap,
39643984
stub_a));
39653985
auto heap_sz = heap_cx.build.Add(llsize_of(llheappartty), lllen);
3966-
auto rs = trans_raw_malloc(heap_cx, T_ptr(llheappartty), heap_sz);
3986+
auto rs = trans_shared_malloc(heap_cx, T_ptr(llheappartty), heap_sz);
39673987
auto heap_part = rs.val;
39683988
heap_cx = rs.bcx;
39693989
heap_cx.build.Store(heap_part,
@@ -4100,7 +4120,7 @@ mod ivec {
41004120

41014121
auto heap_part_sz = on_heap_cx.build.Add(alen,
41024122
llsize_of(T_opaque_ivec_heap_part()));
4103-
auto rs = trans_raw_malloc(on_heap_cx, T_ptr(llheappartty),
4123+
auto rs = trans_shared_malloc(on_heap_cx, T_ptr(llheappartty),
41044124
heap_part_sz);
41054125
on_heap_cx = rs.bcx;
41064126
auto new_heap_ptr = rs.val;
@@ -6038,7 +6058,7 @@ fn trans_ivec(@block_ctxt bcx, &(@ast::expr)[] args, ast::node_id id) ->
60386058
bcx.build.Store(lllen, bcx.build.InBoundsGEP(llstubptr, stub_a));
60396059

60406060
auto llheapsz = bcx.build.Add(llsize_of(llheapty), lllen);
6041-
auto rslt = trans_raw_malloc(bcx, T_ptr(llheapty), llheapsz);
6061+
auto rslt = trans_shared_malloc(bcx, T_ptr(llheapty), llheapsz);
60426062
bcx = rslt.bcx;
60436063
auto llheapptr = rslt.val;
60446064
bcx.build.Store(llheapptr,

src/lib/ivec.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ native "rust-intrinsic" mod rusti {
1111
}
1212

1313
native "rust" mod rustrt {
14-
fn ivec_reserve[T](&mutable T[mutable?] v, uint n);
14+
fn ivec_reserve_shared[T](&mutable T[mutable?] v, uint n);
1515
fn ivec_on_heap[T](&T[] v) -> uint;
1616
fn ivec_to_ptr[T](&T[] v) -> *T;
17-
fn ivec_copy_from_buf[T](&mutable T[mutable?] v, *T ptr, uint count);
17+
fn ivec_copy_from_buf_shared[T](&mutable T[mutable?] v,
18+
*T ptr, uint count);
1819
}
1920

2021
/// Reserves space for `n` elements in the given vector.
2122
fn reserve[T](&mutable T[mutable?] v, uint n) {
22-
rustrt::ivec_reserve(v, n);
23+
rustrt::ivec_reserve_shared(v, n);
2324
}
2425

2526
fn on_heap[T](&T[] v) -> bool {
@@ -204,7 +205,7 @@ fn all[T](fn(&T)->bool f, &T[] v) -> bool {
204205

205206
mod unsafe {
206207
fn copy_from_buf[T](&mutable T[] v, *T ptr, uint count) {
207-
ret rustrt::ivec_copy_from_buf(v, ptr, count);
208+
ret rustrt::ivec_copy_from_buf_shared(v, ptr, count);
208209
}
209210
}
210211

src/rt/rust_builtin.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,37 @@ ivec_reserve(rust_task *task, type_desc *ty, rust_ivec *v, size_t n_elems)
648648
v->alloc = new_alloc;
649649
}
650650

651+
/**
652+
* Preallocates the exact number of bytes in the given interior vector.
653+
*/
654+
extern "C" CDECL void
655+
ivec_reserve_shared(rust_task *task, type_desc *ty, rust_ivec *v,
656+
size_t n_elems)
657+
{
658+
size_t new_alloc = n_elems * ty->size;
659+
if (new_alloc <= v->alloc)
660+
return; // Already big enough.
661+
662+
rust_ivec_heap *heap_part;
663+
if (v->fill || !v->payload.ptr) {
664+
// On stack; spill to heap.
665+
heap_part = (rust_ivec_heap *)task->kernel->malloc(new_alloc +
666+
sizeof(size_t));
667+
heap_part->fill = v->fill;
668+
memcpy(&heap_part->data, v->payload.data, v->fill);
669+
670+
v->fill = 0;
671+
v->payload.ptr = heap_part;
672+
} else {
673+
// On heap; resize.
674+
heap_part = (rust_ivec_heap *)task->kernel->realloc(v->payload.ptr,
675+
new_alloc + sizeof(size_t));
676+
v->payload.ptr = heap_part;
677+
}
678+
679+
v->alloc = new_alloc;
680+
}
681+
651682
/**
652683
* Returns true if the given vector is on the heap and false if it's on the
653684
* stack.
@@ -706,6 +737,35 @@ ivec_copy_from_buf(rust_task *task, type_desc *ty, rust_ivec *v, void *ptr,
706737
v->payload.ptr->fill = new_size;
707738
}
708739

740+
/**
741+
* Copies elements in an unsafe buffer to the given interior vector. The
742+
* vector must have size zero.
743+
*/
744+
extern "C" CDECL void
745+
ivec_copy_from_buf_shared(rust_task *task, type_desc *ty, rust_ivec *v,
746+
void *ptr, size_t count)
747+
{
748+
size_t old_size = get_ivec_size(v);
749+
if (old_size) {
750+
task->fail(1);
751+
return;
752+
}
753+
754+
ivec_reserve_shared(task, ty, v, count);
755+
756+
size_t new_size = count * ty->size;
757+
if (v->fill || !v->payload.ptr) {
758+
// On stack.
759+
memmove(v->payload.data, ptr, new_size);
760+
v->fill = new_size;
761+
return;
762+
}
763+
764+
// On heap.
765+
memmove(v->payload.ptr->data, ptr, new_size);
766+
v->payload.ptr->fill = new_size;
767+
}
768+
709769
extern "C" CDECL void
710770
pin_task(rust_task *task) {
711771
task->pin();

src/rt/rust_kernel.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ rust_kernel::malloc(size_t size) {
206206
return _region->malloc(size);
207207
}
208208

209+
void *
210+
rust_kernel::realloc(void *mem, size_t size) {
211+
return _region->realloc(mem, size);
212+
}
213+
209214
void rust_kernel::free(void *mem) {
210215
_region->free(mem);
211216
}

src/rt/rust_kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class rust_kernel : public rust_thread {
110110
virtual ~rust_kernel();
111111

112112
void *malloc(size_t size);
113+
void *realloc(void *mem, size_t size);
113114
void free(void *mem);
114115

115116
// FIXME: this should go away

src/rt/rust_upcall.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,36 @@ upcall_free(rust_task *task, void* ptr, uintptr_t is_gc) {
289289
task->free(ptr, (bool) is_gc);
290290
}
291291

292+
extern "C" CDECL uintptr_t
293+
upcall_shared_malloc(rust_task *task, size_t nbytes, type_desc *td) {
294+
LOG_UPCALL_ENTRY(task);
295+
scoped_lock with(task->kernel->scheduler_lock);
296+
297+
LOG(task, mem,
298+
"upcall shared_malloc(%" PRIdPTR ", 0x%" PRIxPTR ")",
299+
nbytes, td);
300+
void *p = task->kernel->malloc(nbytes);
301+
LOG(task, mem,
302+
"upcall shared_malloc(%" PRIdPTR ", 0x%" PRIxPTR
303+
") = 0x%" PRIxPTR,
304+
nbytes, td, (uintptr_t)p);
305+
return (uintptr_t) p;
306+
}
307+
308+
/**
309+
* Called whenever an object's ref count drops to zero.
310+
*/
311+
extern "C" CDECL void
312+
upcall_shared_free(rust_task *task, void* ptr) {
313+
LOG_UPCALL_ENTRY(task);
314+
scoped_lock with(task->kernel->scheduler_lock);
315+
rust_scheduler *sched = task->sched;
316+
DLOG(sched, mem,
317+
"upcall shared_free(0x%" PRIxPTR")",
318+
(uintptr_t)ptr);
319+
task->kernel->free(ptr);
320+
}
321+
292322
extern "C" CDECL uintptr_t
293323
upcall_mark(rust_task *task, void* ptr) {
294324
LOG_UPCALL_ENTRY(task);
@@ -537,6 +567,7 @@ extern "C" CDECL void
537567
upcall_ivec_resize(rust_task *task,
538568
rust_ivec *v,
539569
size_t newsz) {
570+
LOG_UPCALL_ENTRY(task);
540571
scoped_lock with(task->kernel->scheduler_lock);
541572
I(task->sched, !v->fill);
542573

@@ -556,6 +587,7 @@ extern "C" CDECL void
556587
upcall_ivec_spill(rust_task *task,
557588
rust_ivec *v,
558589
size_t newsz) {
590+
LOG_UPCALL_ENTRY(task);
559591
scoped_lock with(task->kernel->scheduler_lock);
560592
size_t new_alloc = next_power_of_two(newsz);
561593

@@ -569,6 +601,46 @@ upcall_ivec_spill(rust_task *task,
569601
v->payload.ptr = heap_part;
570602
}
571603

604+
/**
605+
* Resizes an interior vector that has been spilled to the heap.
606+
*/
607+
extern "C" CDECL void
608+
upcall_ivec_resize_shared(rust_task *task,
609+
rust_ivec *v,
610+
size_t newsz) {
611+
LOG_UPCALL_ENTRY(task);
612+
scoped_lock with(task->kernel->scheduler_lock);
613+
I(task->sched, !v->fill);
614+
615+
size_t new_alloc = next_power_of_two(newsz);
616+
rust_ivec_heap *new_heap_part = (rust_ivec_heap *)
617+
task->kernel->realloc(v->payload.ptr, new_alloc + sizeof(size_t));
618+
619+
new_heap_part->fill = newsz;
620+
v->alloc = new_alloc;
621+
v->payload.ptr = new_heap_part;
622+
}
623+
624+
/**
625+
* Spills an interior vector to the heap.
626+
*/
627+
extern "C" CDECL void
628+
upcall_ivec_spill_shared(rust_task *task,
629+
rust_ivec *v,
630+
size_t newsz) {
631+
LOG_UPCALL_ENTRY(task);
632+
scoped_lock with(task->kernel->scheduler_lock);
633+
size_t new_alloc = next_power_of_two(newsz);
634+
635+
rust_ivec_heap *heap_part = (rust_ivec_heap *)
636+
task->kernel->malloc(new_alloc + sizeof(size_t));
637+
heap_part->fill = newsz;
638+
memcpy(&heap_part->data, v->payload.data, v->fill);
639+
640+
v->fill = 0;
641+
v->alloc = new_alloc;
642+
v->payload.ptr = heap_part;
643+
}
572644
//
573645
// Local Variables:
574646
// mode: C++

src/rt/rustrt.def.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ debug_tydesc
1111
do_gc
1212
get_time
1313
ivec_copy_from_buf
14+
ivec_copy_from_buf_shared
1415
ivec_on_heap
1516
ivec_reserve
17+
ivec_reserve_shared
1618
ivec_to_ptr
1719
last_os_error
1820
nano_time
@@ -59,7 +61,9 @@ upcall_free
5961
upcall_get_type_desc
6062
upcall_grow_task
6163
upcall_ivec_resize
64+
upcall_ivec_resize_shared
6265
upcall_ivec_spill
66+
upcall_ivec_spill_shared
6367
upcall_kill
6468
upcall_log_double
6569
upcall_log_float
@@ -74,6 +78,8 @@ upcall_new_task
7478
upcall_new_vec
7579
upcall_recv
7680
upcall_send
81+
upcall_shared_malloc
82+
upcall_shared_free
7783
upcall_sleep
7884
upcall_start_task
7985
upcall_trace_str

0 commit comments

Comments
 (0)