Skip to content

Commit 2082dff

Browse files
committed
---
yaml --- r: 633 b: refs/heads/master c: 4e355ae h: refs/heads/master i: 631: 2e68ef7 v: v3
1 parent c38185f commit 2082dff

File tree

5 files changed

+222
-29
lines changed

5 files changed

+222
-29
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: 1eb2a8b10be2063637e510794ed6bbc49693b5b8
2+
refs/heads/master: 4e355aebf7c0987c3d6f66ca0013e7023aa501dd

trunk/src/boot/be/abi.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ let iterator_args_elt_outer_frame_ptr = 1;;
102102

103103
let indirect_args_elt_closure = 0;;
104104

105-
(* dst, taskptr, closure-ptr, ty_params, src, src2=target_task *)
106-
let worst_case_glue_call_args = 6;;
105+
(* Current worst case is by vec grow glue *)
106+
let worst_case_glue_call_args = 7;;
107107

108108
type abi =
109109
{

trunk/src/boot/me/semant.ml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type glue =
4040
| GLUE_obj_drop of node_id (* Node is the obj. *)
4141
| GLUE_loop_body of node_id (* Node is the 'for each' body block. *)
4242
| GLUE_forward of (Ast.ident * Ast.ty_obj * Ast.ty_obj)
43+
| GLUE_vec_grow
4344
;;
4445

4546
type data =
@@ -1939,6 +1940,11 @@ and fn_rty (opaque_box_body:bool) (word_bits:Il.bits) : Il.referent_ty =
19391940

19401941
r [| code_ptr; box_ptr |]
19411942

1943+
and vec_sty (word_bits:Il.bits) : Il.scalar_ty =
1944+
let word = word_rty word_bits in
1945+
let ptr = Il.ScalarTy (Il.AddrTy Il.OpaqueTy) in
1946+
Il.AddrTy (Il.StructTy [| word; word; word; ptr |])
1947+
19421948
and referent_type (word_bits:Il.bits) (t:Ast.ty) : Il.referent_ty =
19431949
let s t = Il.ScalarTy t in
19441950
let v b = Il.ValTy b in
@@ -1985,7 +1991,7 @@ and referent_type (word_bits:Il.bits) (t:Ast.ty) : Il.referent_ty =
19851991
| Ast.TY_mach (TY_f64) -> sv Il.Bits64
19861992

19871993
| Ast.TY_str -> sp (Il.StructTy [| word; word; word; ptr |])
1988-
| Ast.TY_vec _ -> sp (Il.StructTy [| word; word; word; ptr |])
1994+
| Ast.TY_vec _ -> s (vec_sty word_bits)
19891995
| Ast.TY_tup tt -> tup tt
19901996
| Ast.TY_rec tr -> tup (Array.map snd tr)
19911997

@@ -2344,6 +2350,7 @@ let glue_str (cx:ctxt) (g:glue) : string =
23442350
^ id
23452351
^ "$" ^ (ty_str (Ast.TY_obj oty1))
23462352
^ "$" ^ (ty_str (Ast.TY_obj oty2))
2353+
| GLUE_vec_grow -> "glue$vec_grow"
23472354
;;
23482355

23492356

trunk/src/boot/me/trans.ml

Lines changed: 185 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,21 +1740,29 @@ let trans_visitor
17401740
(ty:Ast.ty)
17411741
(curr_iso:Ast.ty_iso option)
17421742
: fixup =
1743+
let arg_ty_params_alias = 0 in
1744+
let arg_src_alias = 1 in
1745+
let arg_initflag = 2 in
1746+
17431747
let g = GLUE_copy ty in
17441748
let inner (out_ptr:Il.cell) (args:Il.cell) =
17451749
let dst = deref out_ptr in
1746-
let ty_params = deref (get_element_ptr args 0) in
1747-
let src = deref (get_element_ptr args 1) in
1750+
let ty_params = deref (get_element_ptr args arg_ty_params_alias) in
1751+
let src = deref (get_element_ptr args arg_src_alias) in
17481752

17491753
(* Translate copy code for the dst-initializing and
17501754
* dst-non-initializing cases and branch accordingly. *)
1751-
let initflag = get_element_ptr args 2 in
1755+
let initflag = get_element_ptr args arg_initflag in
17521756
let jmps = trans_compare_simple Il.JNE (Il.Cell initflag) one in
1757+
17531758
trans_copy_ty ty_params true dst ty src ty curr_iso;
1759+
17541760
let skip_noninit_jmp = mark() in
17551761
emit (Il.jmp Il.JMP Il.CodeNone);
17561762
List.iter patch jmps;
1763+
17571764
trans_copy_ty ty_params false dst ty src ty curr_iso;
1765+
17581766
patch skip_noninit_jmp;
17591767
in
17601768
let ty_params_ptr = ty_params_covering ty in
@@ -1767,6 +1775,151 @@ let trans_visitor
17671775

17681776
and get_cmp_glue _ = failwith "TODO"
17691777

1778+
(*
1779+
* Vector-growth glue takes four arguments:
1780+
*
1781+
* 0. (Implicit) task ptr
1782+
* 1. Pointer to the typarams of the caller's frame (possibly required to
1783+
* be passed to element's copy glue).
1784+
* 2. Pointer to tydesc of the vec's stored element type, so that elements
1785+
* can be copied to a newly alloc'ed vec if one must be created.
1786+
* 3. Alias to vec that needs to grow (i.e. ptr to ptr to rust_vec).
1787+
* 4. Number of bytes of growth requested
1788+
*)
1789+
and emit_vec_grow_glue
1790+
(fix:fixup)
1791+
(g:glue)
1792+
: unit =
1793+
let arg_typarams_ptr = 0 in
1794+
let arg_tydesc_ptr = 1 in
1795+
let arg_vec_alias = 2 in
1796+
let arg_nbytes = 3 in
1797+
1798+
let name = glue_str cx g in
1799+
log cx "emitting glue: %s" name;
1800+
1801+
let fn_ty =
1802+
mk_simple_ty_fn
1803+
[| ty_params_covering Ast.TY_int; (* an OK lie *)
1804+
local_slot Ast.TY_type;
1805+
alias_slot (Ast.TY_vec Ast.TY_int); (* an OK lie *)
1806+
local_slot Ast.TY_uint; |]
1807+
in
1808+
1809+
let args_rty = call_args_referent_type cx 0 fn_ty None in
1810+
1811+
let callsz = Il.referent_ty_size word_bits args_rty in
1812+
let spill = new_fixup (name ^ " spill") in
1813+
trans_glue_frame_entry callsz spill false;
1814+
1815+
let args_cell =
1816+
get_element_ptr (caller_args_cell args_rty) Abi.calltup_elt_args
1817+
in
1818+
1819+
let vec_alias_cell = get_element_ptr args_cell arg_vec_alias in
1820+
let vec_cell = deref vec_alias_cell in
1821+
let nbytes_cell = get_element_ptr args_cell arg_nbytes in
1822+
let td_ptr_cell = get_element_ptr args_cell arg_tydesc_ptr in
1823+
let ty_params_cell =
1824+
deref (get_element_ptr args_cell arg_typarams_ptr)
1825+
in
1826+
1827+
let need_copy_cell = next_vreg_cell word_sty in
1828+
let new_vec_cell = next_vreg_cell (vec_sty word_bits) in
1829+
1830+
aliasing true need_copy_cell
1831+
begin
1832+
fun need_copy_alias_cell ->
1833+
trans_upcall "upcall_vec_grow"
1834+
new_vec_cell
1835+
[| Il.Cell vec_cell;
1836+
Il.Cell nbytes_cell;
1837+
Il.Cell need_copy_alias_cell |]
1838+
end;
1839+
1840+
let no_copy_jmps =
1841+
trans_compare_simple Il.JE (Il.Cell need_copy_cell) zero
1842+
in
1843+
1844+
let dst_vec = deref new_vec_cell in
1845+
let src_vec = deref vec_cell in
1846+
1847+
let fill =
1848+
get_element_ptr_dyn ty_params_cell src_vec Abi.vec_elt_fill
1849+
in
1850+
let elt_sz =
1851+
get_element_ptr (deref td_ptr_cell) Abi.tydesc_field_size
1852+
in
1853+
1854+
let dst_buf =
1855+
get_element_ptr_dyn ty_params_cell dst_vec Abi.vec_elt_data
1856+
in
1857+
let src_buf =
1858+
get_element_ptr_dyn ty_params_cell src_vec Abi.vec_elt_data
1859+
in
1860+
1861+
(* Copy loop: *)
1862+
let eltp_sty = Il.AddrTy (Il.OpaqueTy) in
1863+
let dptr = next_vreg_cell eltp_sty in
1864+
let sptr = next_vreg_cell eltp_sty in
1865+
let dlim = next_vreg_cell eltp_sty in
1866+
1867+
lea dptr (fst (need_mem_cell dst_buf));
1868+
lea sptr (fst (need_mem_cell src_buf));
1869+
mov dlim (Il.Cell dptr);
1870+
add_to dlim (Il.Cell fill);
1871+
1872+
(* Copy loop body: *)
1873+
let fwd_jmp = mark () in
1874+
emit (Il.jmp Il.JMP Il.CodeNone);
1875+
let back_jmp_targ = mark () in
1876+
1877+
(* Copy *)
1878+
let ty_params_ptr =
1879+
get_tydesc_params ty_params_cell td_ptr_cell
1880+
in
1881+
let initflag = Il.Reg (force_to_reg one) in
1882+
trans_call_dynamic_glue
1883+
td_ptr_cell
1884+
Abi.tydesc_field_copy_glue
1885+
(Some (deref dptr))
1886+
[| ty_params_ptr; sptr; initflag |]
1887+
None;
1888+
1889+
add_to dptr (Il.Cell elt_sz);
1890+
add_to sptr (Il.Cell elt_sz);
1891+
1892+
patch fwd_jmp;
1893+
let back_jmp =
1894+
trans_compare_simple Il.JB (Il.Cell dptr) (Il.Cell dlim)
1895+
in
1896+
List.iter
1897+
(fun j -> patch_existing j back_jmp_targ) back_jmp;
1898+
1899+
(* Set the new vec's fill to the original vec's fill *)
1900+
let dst_fill = get_element_ptr dst_vec Abi.vec_elt_fill in
1901+
let v = next_vreg_cell word_sty in
1902+
mov v (Il.Cell fill);
1903+
mov dst_fill (Il.Cell v);
1904+
1905+
List.iter patch no_copy_jmps;
1906+
1907+
mov vec_cell (Il.Cell new_vec_cell);
1908+
1909+
trans_glue_frame_exit fix spill g
1910+
1911+
1912+
and get_vec_grow_glue _
1913+
: fixup =
1914+
let g = GLUE_vec_grow in
1915+
match htab_search cx.ctxt_glue_code g with
1916+
Some code -> code.code_fixup
1917+
| None ->
1918+
begin
1919+
let fix = new_fixup (glue_str cx g) in
1920+
emit_vec_grow_glue fix g;
1921+
fix
1922+
end
17701923

17711924
(* Glue functions use mostly the same calling convention as ordinary
17721925
* functions.
@@ -4418,21 +4571,29 @@ let trans_visitor
44184571
(Ast.TY_str, Ast.TY_str)
44194572
| (Ast.TY_vec _, Ast.TY_vec _)
44204573
when (simplified_ty dst_ty) = (simplified_ty src_ty) ->
4421-
let is_gc = if type_has_state src_ty then 1L else 0L in
4574+
44224575
let src_cell = need_cell src_oper in
44234576
let src_vec = deref src_cell in
44244577
let src_fill = get_element_ptr src_vec Abi.vec_elt_fill in
44254578
let dst_vec = deref dst_cell in
44264579
let dst_fill = get_element_ptr dst_vec Abi.vec_elt_fill in
4580+
44274581
if trailing_null
44284582
then sub_from dst_fill (imm 1L);
4429-
trans_upcall "upcall_vec_grow"
4430-
dst_cell
4431-
[| Il.Cell dst_cell;
4432-
Il.Cell src_fill;
4433-
imm is_gc |];
44344583

4435-
(*
4584+
aliasing true dst_cell
4585+
begin
4586+
fun dst_vec_alias ->
4587+
trans_call_simple_static_glue
4588+
(get_vec_grow_glue ())
4589+
(get_ty_params_of_current_frame ())
4590+
[| get_tydesc None elt_ty;
4591+
dst_vec_alias;
4592+
src_fill; |]
4593+
None
4594+
end;
4595+
4596+
(*
44364597
* By now, dst_cell points to a vec/str with room for us
44374598
* to add to.
44384599
*)
@@ -4486,13 +4647,21 @@ let trans_visitor
44864647
| (Ast.TY_vec _, e)
44874648
when e = simplified_ty elt_ty ->
44884649

4489-
let dst_is_gc = if type_has_state dst_ty then 1L else 0L in
44904650
let elt_sz = ty_sz_in_current_frame elt_ty in
4491-
trans_upcall "upcall_vec_grow"
4492-
dst_cell
4493-
[| Il.Cell dst_cell;
4494-
elt_sz;
4495-
imm dst_is_gc |];
4651+
let elt_sz_cell = next_vreg_cell word_sty in
4652+
mov elt_sz_cell elt_sz;
4653+
4654+
aliasing true dst_cell
4655+
begin
4656+
fun dst_vec_alias ->
4657+
trans_call_simple_static_glue
4658+
(get_vec_grow_glue ())
4659+
(get_ty_params_of_current_frame ())
4660+
[| get_tydesc None elt_ty;
4661+
dst_vec_alias;
4662+
elt_sz_cell; |]
4663+
None
4664+
end;
44964665

44974666
(*
44984667
* By now, dst_cell points to a vec/str with room for us

trunk/src/rt/rust_upcall.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -384,18 +384,23 @@ upcall_new_vec(rust_task *task, size_t fill, type_desc *td) {
384384
return v;
385385
}
386386

387-
extern "C" CDECL rust_str *
387+
extern "C" CDECL rust_vec *
388388
upcall_vec_grow(rust_task *task,
389389
rust_vec *v,
390390
size_t n_bytes,
391-
uintptr_t is_gc) {
391+
uintptr_t *need_copy)
392+
{
392393
LOG_UPCALL_ENTRY(task);
393394
rust_dom *dom = task->dom;
394-
task->log(rust_log::UPCALL|rust_log::MEM,
395-
"upcall vec_grow(0x%" PRIxPTR ", %" PRIdPTR
396-
"), alloc=%" PRIdPTR ", fill=%" PRIdPTR,
397-
v, n_bytes, v->alloc, v->fill);
395+
task->log(rust_log::UPCALL | rust_log::MEM,
396+
"upcall vec_grow(0x%" PRIxPTR ", %" PRIdPTR
397+
"), alloc=%" PRIdPTR ", fill=%" PRIdPTR
398+
", need_copy=0x%" PRIxPTR,
399+
v, n_bytes, v->alloc, v->fill, need_copy);
400+
401+
*need_copy = 0;
398402
size_t alloc = next_power_of_two(sizeof(rust_vec) + v->fill + n_bytes);
403+
399404
if (v->ref_count == 1) {
400405

401406
// Fastest path: already large enough.
@@ -414,16 +419,28 @@ upcall_vec_grow(rust_task *task,
414419
v->alloc = alloc;
415420

416421
} else {
417-
// Slowest path: make a new vec.
422+
/**
423+
* Slowest path: make a new vec.
424+
*
425+
* 1. Allocate a new rust_vec with desired additional space.
426+
* 2. Down-ref the shared rust_vec, point to the new one instead.
427+
* 3. Copy existing elements into the new rust_vec.
428+
*
429+
* Step 3 is a bit tricky. We don't know how to properly copy the
430+
* elements in the runtime (all we have are bits in a buffer; no
431+
* type infromation and no copy glue). What we do instead is set the
432+
* need_copy outparam flag to indicate to our caller (vec-copy glue)
433+
* that we need the copies performed for us.
434+
*/
418435
task->log(rust_log::UPCALL | rust_log::MEM, "new vec path");
419436
void *mem = dom->malloc(alloc);
420437
if (!mem) {
421438
task->fail(4);
422439
return NULL;
423440
}
424441
v->deref();
425-
v = new (mem) rust_vec(dom, alloc, v->fill,
426-
v->fill ? &v->data[0] : NULL);
442+
v = new (mem) rust_vec(dom, alloc, 0, NULL);
443+
*need_copy = 1;
427444
}
428445
I(dom, sizeof(rust_vec) + v->fill <= v->alloc);
429446
return v;

0 commit comments

Comments
 (0)