@@ -694,7 +694,7 @@ exception Not_constant
694694
695695let extract_constant = function
696696 Lconst sc -> sc
697- | _ -> raise Not_constant
697+ | _ -> raise_notrace Not_constant
698698
699699let 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+
13411406and 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