Skip to content

Commit d2124fb

Browse files
committed
[compiler] take ownership of transl_record
1 parent 32750c5 commit d2124fb

File tree

1 file changed

+67
-2
lines changed

1 file changed

+67
-2
lines changed

vendor/ocaml/bytecomp/translcore.ml

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ exception Not_constant
694694

695695
let extract_constant = function
696696
Lconst sc -> sc
697-
| _ -> raise Not_constant
697+
| _ -> raise_notrace Not_constant
698698

699699
let extract_float = function
700700
Const_base(Const_float f) -> f
@@ -973,7 +973,10 @@ and transl_exp0 e =
973973
[Lconst(Const_base(Const_int tag)); lam], e.exp_loc)
974974
end
975975
| Texp_record ((_, lbl1, _) :: _ as lbl_expr_list, opt_init_expr) ->
976-
transl_record e.exp_loc lbl1.lbl_all lbl1.lbl_repres lbl_expr_list opt_init_expr
976+
if !Clflags.bs_only then
977+
transl_record_bs e.exp_loc lbl1.lbl_all lbl1.lbl_repres lbl_expr_list opt_init_expr
978+
else
979+
transl_record e.exp_loc lbl1.lbl_all lbl1.lbl_repres lbl_expr_list opt_init_expr
977980
| Texp_record ([], _) ->
978981
fatal_error "Translcore.transl_exp: bad Texp_record"
979982
| Texp_field(arg, _, lbl) ->
@@ -1338,6 +1341,68 @@ and transl_record loc all_labels repres lbl_expr_list opt_init_expr =
13381341
end
13391342
end
13401343

1344+
and transl_record_bs loc all_labels repres lbl_expr_list opt_init_expr =
1345+
let size = Array.length all_labels in
1346+
(* Determine if there are "enough" new fields *)
1347+
if opt_init_expr = None || size <= 20 || 3 + 2 * List.length lbl_expr_list >= size
1348+
then begin
1349+
(* Allocate new record with given fields (and remaining fields
1350+
taken from init_expr if any *)
1351+
let lv = Array.make size staticfail in
1352+
let init_id = Ident.create "init" in
1353+
for i = 0 to Array.length all_labels - 1 do
1354+
let access =
1355+
let lbl = all_labels.(i) in
1356+
Pfield (i, Fld_record lbl.lbl_name)
1357+
in
1358+
lv.(i) <- Lprim(access, [Lvar init_id], loc)
1359+
done;
1360+
List.iter
1361+
(fun (_, lbl, expr) -> lv.(lbl.lbl_pos) <- transl_exp expr)
1362+
lbl_expr_list;
1363+
let ll = Array.to_list lv in
1364+
let mut = ref Immutable in
1365+
let all_labels_info =
1366+
Lambda.Blk_record (all_labels |> Array.map (fun x -> x.Types.lbl_name)) in
1367+
let lam =
1368+
try
1369+
for i = 0 to Array.length all_labels - 1 do
1370+
if (Array.unsafe_get all_labels i).lbl_mut = Mutable then
1371+
begin
1372+
mut := Mutable;
1373+
raise_notrace Not_constant
1374+
end
1375+
done ;
1376+
let cl = List.map extract_constant ll in
1377+
Lconst(Const_block(0, all_labels_info, cl))
1378+
with Not_constant ->
1379+
Lprim(Pmakeblock(0, all_labels_info, !mut), ll,loc)
1380+
in
1381+
begin match opt_init_expr with
1382+
None -> lam
1383+
| Some init_expr -> Llet(Strict, init_id, transl_exp init_expr, lam)
1384+
end
1385+
end else begin
1386+
(* Take a shallow copy of the init record, then mutate the fields
1387+
of the copy *)
1388+
(* If you change anything here, you will likely have to change
1389+
[check_recursive_recordwith] in this file. *)
1390+
let copy_id = Ident.create "newrecord" in
1391+
let update_field (_, ({lbl_pos; lbl_name} : Types.label_description), expr) cont =
1392+
let upd =
1393+
Psetfield(lbl_pos, true, Fld_record_set lbl_name)
1394+
(* don't care pointer or not *)
1395+
in
1396+
Lsequence(Lprim(upd, [Lvar copy_id; transl_exp expr], loc), cont) in
1397+
begin match opt_init_expr with
1398+
None -> assert false
1399+
| Some init_expr ->
1400+
Llet(Strict, copy_id,
1401+
Lprim(Pduprecord (repres, size), [transl_exp init_expr], loc),
1402+
List.fold_right update_field lbl_expr_list (Lvar copy_id))
1403+
end
1404+
end
1405+
13411406
and transl_match e arg pat_expr_list exn_pat_expr_list partial =
13421407
let id = name_pattern "exn" exn_pat_expr_list
13431408
and cases = transl_cases pat_expr_list

0 commit comments

Comments
 (0)