Skip to content

Commit 2287342

Browse files
committed
---
yaml --- r: 3690 b: refs/heads/master c: f611717 h: refs/heads/master v: v3
1 parent 4c99473 commit 2287342

File tree

7 files changed

+183
-13
lines changed

7 files changed

+183
-13
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 2e2e1f7cb36aeac0abb730a752fcd78cf91a380f
2+
refs/heads/master: f6117173c9f26efdcf50cb664d006ea2bdf0d0cb

trunk/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:

trunk/src/comp/middle/trans.rs

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

1153+
fn trans_shared_free(&@block_ctxt cx, ValueRef v) -> result {
1154+
cx.build.Call(cx.fcx.lcx.ccx.upcalls.shared_free,
1155+
[cx.fcx.lltaskptr, cx.build.PointerCast(v, T_ptr(T_i8()))]);
1156+
ret rslt(cx, C_int(0));
1157+
}
1158+
11531159
fn find_scope_cx(&@block_ctxt cx) -> @block_ctxt {
11541160
if (cx.kind != NON_SCOPE_BLOCK) { ret cx; }
11551161
alt (cx.parent) {
@@ -1578,6 +1584,18 @@ fn trans_raw_malloc(&@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) ->
15781584
ret rslt(cx, cx.build.PointerCast(rval, llptr_ty));
15791585
}
15801586

1587+
// trans_shared_malloc: expects a type indicating which pointer type we want
1588+
// and a size indicating how much space we want malloc'd.
1589+
fn trans_shared_malloc(&@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) ->
1590+
result {
1591+
// FIXME: need a table to collect tydesc globals.
1592+
1593+
auto tydesc = C_null(T_ptr(T_tydesc(cx.fcx.lcx.ccx.tn)));
1594+
auto rval =
1595+
cx.build.Call(cx.fcx.lcx.ccx.upcalls.shared_malloc,
1596+
[cx.fcx.lltaskptr, llsize, tydesc]);
1597+
ret rslt(cx, cx.build.PointerCast(rval, llptr_ty));
1598+
}
15811599

15821600
// trans_malloc_boxed: expects an unboxed type and returns a pointer to enough
15831601
// space for something of that type, along with space for a reference count;
@@ -2097,7 +2115,7 @@ fn maybe_free_ivec_heap_part(&@block_ctxt cx, ValueRef v0, ty::t unit_ty) ->
20972115
auto m = maybe_on_heap_cx.build.InBoundsGEP(stub_ptr, v);
20982116
maybe_on_heap_cx.build.Load(m)
20992117
};
2100-
auto after_free_cx = trans_non_gc_free(maybe_on_heap_cx, heap_ptr).bcx;
2118+
auto after_free_cx = trans_shared_free(maybe_on_heap_cx, heap_ptr).bcx;
21012119
after_free_cx.build.Br(next_cx.llbb);
21022120
ret rslt(next_cx, C_nil());
21032121
}
@@ -3617,7 +3635,8 @@ mod ivec {
36173635
{
36183636
auto p =
36193637
heap_resize_cx.build.PointerCast(v, T_ptr(T_opaque_ivec()));
3620-
heap_resize_cx.build.Call(cx.fcx.lcx.ccx.upcalls.ivec_resize,
3638+
auto upcall = cx.fcx.lcx.ccx.upcalls.ivec_resize_shared;
3639+
heap_resize_cx.build.Call(upcall,
36213640
[cx.fcx.lltaskptr, p, new_heap_len]);
36223641
}
36233642
auto heap_ptr_resize =
@@ -3657,7 +3676,8 @@ mod ivec {
36573676
{
36583677
auto p =
36593678
stack_spill_cx.build.PointerCast(v, T_ptr(T_opaque_ivec()));
3660-
stack_spill_cx.build.Call(cx.fcx.lcx.ccx.upcalls.ivec_spill,
3679+
auto upcall = cx.fcx.lcx.ccx.upcalls.ivec_spill_shared;
3680+
stack_spill_cx.build.Call(upcall,
36613681
[cx.fcx.lltaskptr, p, new_stack_len]);
36623682
}
36633683
auto spill_stub =
@@ -3908,7 +3928,7 @@ mod ivec {
39083928
heap_cx.build.InBoundsGEP(stub_ptr_heap,
39093929
stub_a));
39103930
auto heap_sz = heap_cx.build.Add(llsize_of(llheappartty), lllen);
3911-
auto rs = trans_raw_malloc(heap_cx, T_ptr(llheappartty), heap_sz);
3931+
auto rs = trans_shared_malloc(heap_cx, T_ptr(llheappartty), heap_sz);
39123932
auto heap_part = rs.val;
39133933
heap_cx = rs.bcx;
39143934
heap_cx.build.Store(heap_part,
@@ -4045,7 +4065,7 @@ mod ivec {
40454065

40464066
auto heap_part_sz = on_heap_cx.build.Add(alen,
40474067
llsize_of(T_opaque_ivec_heap_part()));
4048-
auto rs = trans_raw_malloc(on_heap_cx, T_ptr(llheappartty),
4068+
auto rs = trans_shared_malloc(on_heap_cx, T_ptr(llheappartty),
40494069
heap_part_sz);
40504070
on_heap_cx = rs.bcx;
40514071
auto new_heap_ptr = rs.val;
@@ -6003,7 +6023,7 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, ast::node_id id) ->
60036023
bcx.build.Store(lllen, bcx.build.InBoundsGEP(llstubptr, stub_a));
60046024

60056025
auto llheapsz = bcx.build.Add(llsize_of(llheapty), lllen);
6006-
auto rslt = trans_raw_malloc(bcx, T_ptr(llheapty), llheapsz);
6026+
auto rslt = trans_shared_malloc(bcx, T_ptr(llheapty), llheapsz);
60076027
bcx = rslt.bcx;
60086028
auto llheapptr = rslt.val;
60096029
bcx.build.Store(llheapptr,

trunk/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

trunk/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();

trunk/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++

trunk/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)