Skip to content

Commit bc70ebf

Browse files
committed
Add new primitives to create blocks for lazy values
This adds a new primitive in Lambda and Flambda2 to create a block for a (not short-circuited) lazy value. These primitives allow to more systematically handle lazy blocks correctly, for instance with respect to the value-let-rec size computation, and in flambda to better ensure that we do not track block appromixations for lazy values (without relying on the frontend to insert opaque identities).
1 parent f7beed2 commit bc70ebf

20 files changed

+171
-21
lines changed

bug.ml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
type t =
3+
| C of t Lazy.t Lazy.t
4+
5+
let rec x =
6+
let y = (lazy (C x)) in
7+
lazy y
8+
9+

bytecomp/bytegen.ml

+10-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ let preserve_tailcall_for_prim = function
153153
| Pget_header _
154154
| Pignore
155155
| Pgetglobal _ | Psetglobal _ | Pgetpredef _
156-
| Pmakeblock _ | Pmakefloatblock _ | Pmakeufloatblock _ | Pmakemixedblock _
156+
| Pmakeblock _ | Pmakefloatblock _ | Pmakeufloatblock _ | Pmakemixedblock _ | Pmakelazyblock _
157157
| Pfield _ | Pfield_computed _ | Psetfield _
158158
| Psetfield_computed _ | Pfloatfield _ | Psetfloatfield _ | Pduprecord _
159159
| Pufloatfield _ | Psetufloatfield _ | Pmixedfield _ | Psetmixedfield _
@@ -741,6 +741,7 @@ let comp_primitive stack_info p sz args =
741741
| Pmakefloatblock _
742742
| Pmakeufloatblock _
743743
| Pmakemixedblock _
744+
| Pmakelazyblock _
744745
| Pprobe_is_enabled _
745746
| Punbox_float _ | Pbox_float (_, _) | Punbox_int _ | Pbox_int _
746747
->
@@ -1137,6 +1138,14 @@ and comp_expr stack_info env exp sz cont =
11371138
let cont = add_pseudo_event loc !compunit_name cont in
11381139
comp_args stack_info env args sz
11391140
(Kmakeblock(List.length args, tag) :: cont)
1141+
| Lprim (Pmakelazyblock (Lazy_tag, _), args, loc) ->
1142+
let cont = add_pseudo_event loc !compunit_name cont in
1143+
comp_args stack_info env args sz
1144+
(Kmakeblock(List.length args, Config.lazy_tag) :: cont)
1145+
| Lprim (Pmakelazyblock (Forward_tag, _), args, loc) ->
1146+
let cont = add_pseudo_event loc !compunit_name cont in
1147+
comp_args stack_info env args sz
1148+
(Kmakeblock(List.length args, Obj.forward_tag) :: cont)
11401149
| Lprim(Pmake_unboxed_product _, args, loc) ->
11411150
let cont = add_pseudo_event loc !compunit_name cont in
11421151
comp_args stack_info env args sz

lambda/lambda.ml

+8-2
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ type region_close =
124124
| Rc_nontail
125125
| Rc_close_at_apply
126126

127+
type lazy_block_tag =
128+
| Lazy_tag
129+
| Forward_tag
130+
127131
type primitive =
128132
| Pbytes_to_string
129133
| Pbytes_of_string
@@ -137,6 +141,7 @@ type primitive =
137141
| Pmakefloatblock of mutable_flag * locality_mode
138142
| Pmakeufloatblock of mutable_flag * locality_mode
139143
| Pmakemixedblock of int * mutable_flag * mixed_block_shape * locality_mode
144+
| Pmakelazyblock of lazy_block_tag * locality_mode
140145
| Pfield of int * immediate_or_pointer * field_read_semantics
141146
| Pfield_computed of field_read_semantics
142147
| Psetfield of int * immediate_or_pointer * initialization_or_assignment
@@ -1823,6 +1828,7 @@ let primitive_may_allocate : primitive -> locality_mode option = function
18231828
| Pmakefloatblock (_, m) -> Some m
18241829
| Pmakeufloatblock (_, m) -> Some m
18251830
| Pmakemixedblock (_, _, _, m) -> Some m
1831+
| Pmakelazyblock (_, m) -> Some m
18261832
| Pfield _ | Pfield_computed _ | Psetfield _ | Psetfield_computed _ -> None
18271833
| Pfloatfield (_, _, m) -> Some m
18281834
| Pufloatfield _ -> None
@@ -2056,7 +2062,7 @@ let primitive_can_raise prim =
20562062
| Pmakefloatblock _ | Pfield _ | Pfield_computed _ | Psetfield _
20572063
| Psetfield_computed _ | Pfloatfield _ | Psetfloatfield _ | Pduprecord _
20582064
| Pmakeufloatblock _ | Pufloatfield _ | Psetufloatfield _ | Psequand | Psequor
2059-
| Pmixedfield _ | Psetmixedfield _ | Pmakemixedblock _ | Pnot | Pnegint
2065+
| Pmixedfield _ | Psetmixedfield _ | Pmakemixedblock _ | Pmakelazyblock _ | Pnot | Pnegint
20602066
| Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint | Plslint | Plsrint
20612067
| Pasrint | Pintcomp _ | Pcompare_ints | Pcompare_floats _ | Pcompare_bints _
20622068
| Poffsetint _ | Poffsetref _ | Pintoffloat _
@@ -2254,7 +2260,7 @@ let primitive_result_layout (p : primitive) =
22542260
-> layout_unit
22552261
| Pgetglobal _ | Psetglobal _ | Pgetpredef _ -> layout_module_field
22562262
| Pmakeblock _ | Pmakefloatblock _ | Pmakearray _ | Pmakearray_dynamic _
2257-
| Pduprecord _ | Pmakeufloatblock _ | Pmakemixedblock _
2263+
| Pduprecord _ | Pmakeufloatblock _ | Pmakemixedblock _ | Pmakelazyblock _
22582264
| Pduparray _ | Pbigarraydim _ | Pobj_dup -> layout_block
22592265
| Pfield _ | Pfield_computed _ -> layout_value_field
22602266
| Punboxed_product_field (field, layouts) -> (Array.of_list layouts).(field)

lambda/lambda.mli

+5
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ type region_close =
104104
tail call because the outer region needs to end there.)
105105
*)
106106

107+
type lazy_block_tag =
108+
| Lazy_tag
109+
| Forward_tag
110+
107111
(* CR layouts v5: When we add more blocks of non-scannable values, consider
108112
whether some of the primitives specific to ufloat records
109113
([Pmakeufloatblock], [Pufloatfield], and [Psetufloatfield]) can/should be
@@ -121,6 +125,7 @@ type primitive =
121125
| Pmakefloatblock of mutable_flag * locality_mode
122126
| Pmakeufloatblock of mutable_flag * locality_mode
123127
| Pmakemixedblock of int * mutable_flag * mixed_block_shape * locality_mode
128+
| Pmakelazyblock of lazy_block_tag * locality_mode
124129
| Pfield of int * immediate_or_pointer * field_read_semantics
125130
| Pfield_computed of field_read_semantics
126131
| Psetfield of int * immediate_or_pointer * initialization_or_assignment

lambda/matching.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2124,7 +2124,7 @@ let inline_lazy_force_cond arg pos loc =
21242124
( Strict,
21252125
Lambda.layout_lazy,
21262126
idarg,
2127-
arg,
2127+
Lprim (Popaque Lambda.layout_lazy, [arg], loc),
21282128
Llet
21292129
( Alias,
21302130
Lambda.layout_int,

lambda/printlambda.ml

+5
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,10 @@ let primitive ppf = function
469469
| Pmakemixedblock (tag, Mutable, abs, mode) ->
470470
fprintf ppf "make%amixedblock %i Mutable%a"
471471
locality_mode mode tag (mixed_block_shape (fun _ _ -> ())) abs
472+
| Pmakelazyblock (Lazy_tag, mode) ->
473+
fprintf ppf "make%alazyblock" locality_mode mode
474+
| Pmakelazyblock (Forward_tag, mode) ->
475+
fprintf ppf "make%aforwardblock" locality_mode mode
472476
| Pfield (n, ptr, sem) ->
473477
let instr =
474478
match ptr, sem with
@@ -918,6 +922,7 @@ let name_of_primitive = function
918922
| Pmakefloatblock _ -> "Pmakefloatblock"
919923
| Pmakeufloatblock _ -> "Pmakeufloatblock"
920924
| Pmakemixedblock _ -> "Pmakemixedblock"
925+
| Pmakelazyblock _ -> "Pmakelazyblock"
921926
| Pfield _ -> "Pfield"
922927
| Pfield_computed _ -> "Pfield_computed"
923928
| Psetfield _ -> "Psetfield"

lambda/tmc.ml

+3
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,9 @@ let rec choice ctx t =
910910
| Punbox_int _ | Pbox_int _
911911
| Punbox_vector _ | Pbox_vector (_, _)
912912

913+
(* it doesn't seem worth it to support lazy blocks for tmc *)
914+
| Pmakelazyblock _
915+
913916
(* we don't handle array indices as destinations yet *)
914917
| (Pmakearray _ | Pduparray _ | Pmakearray_dynamic _)
915918

lambda/translcore.ml

+4-8
Original file line numberDiff line numberDiff line change
@@ -1012,8 +1012,7 @@ and transl_exp0 ~in_new_scope ~scopes sort e =
10121012
(* We don't need to wrap with Popaque: this forward
10131013
block will never be shortcutted since it points to a float
10141014
and Config.flat_float_array is true. *)
1015-
Lprim(Pmakeblock(Obj.forward_tag, Immutable, None,
1016-
alloc_heap),
1015+
Lprim(Pmakelazyblock(Forward_tag, alloc_heap),
10171016
[transl_exp ~scopes Jkind.Sort.Const.for_lazy_body e],
10181017
of_location ~scopes e.exp_loc)
10191018
| `Identifier `Forward_value ->
@@ -1023,11 +1022,8 @@ and transl_exp0 ~in_new_scope ~scopes sort e =
10231022
optimisation in Flambda, but the concept of a mutable
10241023
block doesn't really match what is going on here. This
10251024
value may subsequently turn into an immediate... *)
1026-
Lprim (Popaque Lambda.layout_lazy,
1027-
[Lprim(Pmakeblock(Obj.forward_tag, Immutable, None,
1028-
alloc_heap),
1029-
[transl_exp ~scopes Jkind.Sort.Const.for_lazy_body e],
1030-
of_location ~scopes e.exp_loc)],
1025+
Lprim(Pmakelazyblock(Forward_tag, alloc_heap),
1026+
[transl_exp ~scopes Jkind.Sort.Const.for_lazy_body e],
10311027
of_location ~scopes e.exp_loc)
10321028
| `Identifier `Other ->
10331029
transl_exp ~scopes Jkind.Sort.Const.for_lazy_body e
@@ -1053,7 +1049,7 @@ and transl_exp0 ~in_new_scope ~scopes sort e =
10531049
Lambda.layout_lazy_contents
10541050
(transl_exp ~scopes Jkind.Sort.Const.for_lazy_body e))
10551051
in
1056-
Lprim(Pmakeblock(Config.lazy_tag, Mutable, None, alloc_heap), [fn],
1052+
Lprim(Pmakelazyblock(Lazy_tag, alloc_heap), [fn],
10571053
of_location ~scopes e.exp_loc)
10581054
end
10591055
| Texp_object (cs, meths) ->

lambda/translprim.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1929,7 +1929,7 @@ let lambda_primitive_needs_event_after = function
19291929
| Parray_to_iarray | Parray_of_iarray
19301930
| Pignore | Psetglobal _
19311931
| Pgetglobal _ | Pgetpredef _ | Pmakeblock _ | Pmakefloatblock _
1932-
| Pmakeufloatblock _ | Pmakemixedblock _
1932+
| Pmakeufloatblock _ | Pmakemixedblock _ | Pmakelazyblock _
19331933
| Pmake_unboxed_product _ | Punboxed_product_field _
19341934
| Parray_element_size_in_bytes _
19351935
| Pfield _ | Pfield_computed _ | Psetfield _

lambda/value_rec_compiler.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ let compute_static_size lam =
245245
| Record_inlined (_, _, (Variant_unboxed | Variant_with_null)) ->
246246
Misc.fatal_error "size_of_primitive"
247247
end
248-
| Pmakeblock _ ->
248+
| Pmakeblock _ | Pmakelazyblock _ ->
249249
(* The block shape is unfortunately an option, so we rely on the
250250
number of arguments instead.
251251
Note that flat float arrays/records use Pmakearray, so we don't need

middle_end/flambda2/from_lambda/closure_conversion.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,8 @@ let close_primitive acc env ~let_bound_ids_with_kinds named
10531053
| Patomic_fetch_add | Patomic_add | Patomic_sub | Patomic_land
10541054
| Patomic_lor | Patomic_lxor | Pdls_get | Ppoll | Patomic_load _
10551055
| Patomic_set _ | Preinterpret_tagged_int63_as_unboxed_int64
1056-
| Preinterpret_unboxed_int64_as_tagged_int63 | Ppeek _ | Ppoke _ ->
1056+
| Preinterpret_unboxed_int64_as_tagged_int63 | Ppeek _ | Ppoke _
1057+
| Pmakelazyblock _ ->
10571058
(* Inconsistent with outer match *)
10581059
assert false
10591060
in

middle_end/flambda2/from_lambda/lambda_to_flambda_primitives.ml

+4-1
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,9 @@ let convert_lprim ~big_endian (prim : L.primitive) (args : Simple.t list list)
13821382
let shape = convert_block_shape shape ~num_fields:(List.length args) in
13831383
let mutability = Mutability.from_lambda mutability in
13841384
[Variadic (Make_block (Values (tag, shape), mutability, mode), args)]
1385+
| Pmakelazyblock (lazy_tag, mode), [[arg]] ->
1386+
let mode = Alloc_mode.For_allocations.from_lambda mode ~current_region in
1387+
[Unary (Make_lazy (lazy_tag, mode), arg)]
13851388
| Pmake_unboxed_product layouts, _ ->
13861389
(* CR mshinwell: this should check the unarized lengths of [layouts] and
13871390
[args] (like [Parray_element_size_in_bytes] below) *)
@@ -2492,7 +2495,7 @@ let convert_lprim ~big_endian (prim : L.primitive) (args : Simple.t list list)
24922495
| Pufloatfield _ | Patomic_load _ | Pmixedfield _
24932496
| Preinterpret_unboxed_int64_as_tagged_int63
24942497
| Preinterpret_tagged_int63_as_unboxed_int64
2495-
| Parray_element_size_in_bytes _ | Ppeek _ ),
2498+
| Parray_element_size_in_bytes _ | Ppeek _ | Pmakelazyblock _ ),
24962499
([] | _ :: _ :: _ | [([] | _ :: _ :: _)]) ) ->
24972500
Misc.fatal_errorf
24982501
"Closure_conversion.convert_primitive: Wrong arity for unary primitive \

middle_end/flambda2/parser/flambda_to_fexpr.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ let unop env (op : Flambda_primitive.unary_primitive) : Fexpr.unop =
582582
| Boolean_not -> Boolean_not
583583
| Int_as_pointer _ | Duplicate_block _ | Duplicate_array _ | Bigarray_length _
584584
| Float_arith _ | Reinterpret_64_bit_word _ | Is_boxed_float | Obj_dup
585-
| Get_header | Atomic_load _ | Peek _ ->
585+
| Get_header | Atomic_load _ | Peek _ | Make_lazy _ ->
586586
Misc.fatal_errorf "TODO: Unary primitive: %a"
587587
Flambda_primitive.Without_args.print
588588
(Flambda_primitive.Without_args.Unary op)

middle_end/flambda2/simplify/simplify_unary_primitive.ml

+7
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,12 @@ let simplify_mutable_block_load _access_kind ~field:_ ~original_prim dacc
888888
(P.result_kind' original_prim)
889889
~original_term
890890

891+
let simplify_lazy ~original_prim dacc ~original_term ~arg:_ ~arg_ty:_
892+
~result_var =
893+
SPR.create_unknown dacc ~result_var
894+
(P.result_kind' original_prim)
895+
~original_term
896+
891897
(* CR layouts v3: implement a real simplifier. *)
892898
let simplify_is_null dacc ~original_term ~arg:scrutinee ~arg_ty:scrutinee_ty
893899
~result_var =
@@ -962,5 +968,6 @@ let simplify_unary_primitive dacc original_prim (prim : P.unary_primitive) ~arg
962968
| Atomic_load block_access_field_kind ->
963969
simplify_atomic_load block_access_field_kind ~original_prim
964970
| Peek _ -> simplify_peek ~original_prim
971+
| Make_lazy _ -> simplify_lazy ~original_prim
965972
in
966973
simplifier dacc ~original_term ~arg ~arg_ty ~result_var

middle_end/flambda2/terms/code_size.ml

+1
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ let unary_prim_size prim =
380380
| Obj_dup -> needs_caml_c_call_extcall_size + 1
381381
| Get_header -> 2
382382
| Atomic_load _ | Peek _ -> 1
383+
| Make_lazy (_, _alloc_mode) -> alloc_size
383384

384385
let binary_prim_size prim =
385386
match (prim : Flambda_primitive.binary_primitive) with

0 commit comments

Comments
 (0)