Skip to content

Commit dd9c221

Browse files
ncik-robertsccasin
andauthored
flambda-backend: Basic mixed blocks for float# in runtime 5 (#2380)
* Records mixing immediates, floats, and float64s Should be configured with: --enable-runtime5 --disable-naked-pointers --enable-reserved-header-bits=8 * Cleanup of names * Slightly more intelligible implementation of record shape detection * Small simplification + remove comment * More renames than before * Raise on poly compare and hash * Fix some, but not all, bugs in bytecomp: we segfault on the 100-generation * Fix off-by-one for zero value prefix len * No more runtime mixed blocks in bytecode Instead, just use normal blocks. This only "drops support" for 64 bit bytecode as 32 bit would just not work. (Also we don't have bits to spare in the header in 32 bit.) * Macroize things more * Support weak pointer shallow copy * A few more places where we need to check for mixed blocks * Most issues fixed * Rename more 'abstract' things to 'mixed' * Remove ability to mix boxed floats with unboxed floats * Fix bugs and more accurately track offsets * Fix bugs and more accurately track budgets * Get let-rec working with mixed blocks * Clarify comment * Use corrected-style tests and actually run the small generated examples * Fix recursive values test * Fix typo in generated TEST stanza * comment and format * Restore support for floats * Flesh out the test suite a bit to cover records with floats in the prefix * Fix bug * Small tweaks to comments / bugfixes in dead code * Fix up Chris's old tests * Cleanup and comments * Commit to storing floats flat in mixed-float-float# blocks * Actually test all floats mixed records * Finish resolving type errors related to conflicts after merge * Resolve some CRs * Resolve more CRs * Clarify that bytecode operations don't raise * Back out an unnecessary change to backend/cmm_helpers.ml * Back out probably unnecessary changes to cmmgen.ml * Add test for too many fields to show error message * Fix local test to actually test something. Use better macros. * Make polymorphic hash raise for mixed blocks * Fix updating of dummy blocks * Add some comments about mixed blocks * Revert unintentional changes to runtime4 * make fmt * Move mixed records to layouts alpha * Always set reserved header bits to 8 * Reenable support for enable-profinfo-width in runtime 4 * Fix segfault in printing + in no-allocness of hash * Most of stedolan's comments * Adopt stedolan's suggestion for structure of `oldify_one` and `oldify_mopup` * Accept TheNumbat's suggestions * Address rest of @TheNumbat's comments * Revert change to conflict markers irrelevant to this PR * no u * Segregate runtime 4 and 5 tests * Fix typo * Clarify comment * Clarify comment * Factor out a gnarly function * Use mixed_block version of primitives for getting/setting value fields * make fmt * Fix bug in all-float mixed records and fix accidental omission in tests * Segregate tests for all-float mixed records and mixed blocks * Correct comment in float64 tests * Rework test structure * Comment raisiness * Fix bug in printing * Fix confusing name * Flat_imm_element -> Imm_element * Reshuffle tests so we don't get error message clashes between runtime 4 and 5 * Stop unnecessarily numbering tests * Fix upstream build * 'Fix' upstream build * Respond to stedolan's comments * Respond to review of @TheNumbat and @lthls * Fix bug in oldify_one * Re-enable test of recursive value (accidentally disabled) and allow recursive mixed blocks * Simplify generated test code, and just check in full test * Remove unnecessary test.reference file * Fix printing bug in bytecode * Allow the Obj.double_field call in printing to work on mixed blocks * Fix tests that I accidentally broke * Continue rejecting mixed blocks from runtime 4 type-checker * Resolve hash CR: implement hash differently in native code vs. bytecode * Revert to hashing a constant for mixed blocks * Just take the hash of the scannable prefix * Minimize needless diff in runtime * Re-enable an accidentally disabled test and fix a bug related to Obj.with_tag * Slightly more consistent name (`caml_alloc_small_with_reserved`) * Add missing functionality and test for mixed block over young wosize limit (so is allocated via a different code path) * add new function to headers --------- Co-authored-by: Chris Casinghino <ccasinghino@janestreet.com>
1 parent 962b0c6 commit dd9c221

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+9990
-214
lines changed

asmcomp/cmmgen.ml

+15
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,9 @@ let rec transl env e =
646646
transl_prim_2 env p arg1 arg2 dbg
647647
| (p, [arg1; arg2; arg3]) ->
648648
transl_prim_3 env p arg1 arg2 arg3 dbg
649+
(* Mixed blocks *)
650+
| (Pmakemixedblock _ | Psetmixedfield _ | Pmixedfield _), _->
651+
Misc.fatal_error "Mixed blocks not supported in upstream compiler build"
649652
| (Pread_symbol _, _::_::_::_::_)
650653
| (Pbigarrayset (_, _, _, _), [])
651654
| (Pbigarrayref (_, _, _, _), [])
@@ -1036,6 +1039,9 @@ and transl_prim_1 env p arg dbg =
10361039
Cop(mk_load_atomic Word_int, [transl env arg], dbg)
10371040
| Patomic_load {immediate_or_pointer = Pointer} ->
10381041
Cop(mk_load_atomic Word_val, [transl env arg], dbg)
1042+
(* Mixed blocks *)
1043+
| Pmakemixedblock _ | Psetmixedfield _ | Pmixedfield _ ->
1044+
Misc.fatal_error "Mixed blocks not supported in upstream compiler build"
10391045
| (Pfield_computed | Psequand | Psequor
10401046
| Prunstack | Presume | Preperform
10411047
| Patomic_exchange | Patomic_cas | Patomic_fetch_add
@@ -1252,6 +1258,11 @@ and transl_prim_2 env p arg1 arg2 dbg =
12521258
| Patomic_fetch_add ->
12531259
Cop (Cextcall ("caml_atomic_fetch_add", typ_int, [], false),
12541260
[transl env arg1; transl env arg2], dbg)
1261+
1262+
(* Mixed blocks *)
1263+
| Pmakemixedblock _ | Psetmixedfield _ | Pmixedfield _ ->
1264+
Misc.fatal_error "Mixed blocks not supported in upstream compiler build"
1265+
12551266
| Prunstack | Pperform | Presume | Preperform | Pdls_get
12561267
| Patomic_cas | Patomic_load _
12571268
| Pnot | Pnegint | Pintoffloat _ | Pfloatofint (_, _)
@@ -1314,6 +1325,10 @@ and transl_prim_3 env p arg1 arg2 arg3 dbg =
13141325
Cop (Cextcall ("caml_atomic_cas", typ_int, [], false),
13151326
[transl env arg1; transl env arg2; transl env arg3], dbg)
13161327

1328+
(* Mixed blocks *)
1329+
| Pmakemixedblock _ | Psetmixedfield _ | Pmixedfield _ ->
1330+
Misc.fatal_error "Mixed blocks not supported in upstream compiler build"
1331+
13171332
(* Effects *)
13181333
| Presume ->
13191334
Misc.fatal_error "Effects-related primitives not yet supported"

bytecomp/bytegen.ml

+34-4
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ let preserve_tailcall_for_prim = function
120120
| Pget_header _
121121
| Pignore
122122
| Pgetglobal _ | Psetglobal _ | Pgetpredef _
123-
| Pmakeblock _ | Pmakefloatblock _ | Pmakeufloatblock _
123+
| Pmakeblock _ | Pmakefloatblock _ | Pmakeufloatblock _ | Pmakemixedblock _
124124
| Pfield _ | Pfield_computed _ | Psetfield _
125125
| Psetfield_computed _ | Pfloatfield _ | Psetfloatfield _ | Pduprecord _
126-
| Pufloatfield _ | Psetufloatfield _
126+
| Pufloatfield _ | Psetufloatfield _ | Pmixedfield _ | Psetmixedfield _
127127
| Pmake_unboxed_product _ | Punboxed_product_field _
128128
| Pccall _ | Praise _ | Pnot | Pnegint | Paddint | Psubint | Pmulint
129129
| Pdivint _ | Pmodint _ | Pandint | Porint | Pxorint | Plslint | Plsrint
@@ -204,6 +204,7 @@ let rec size_of_lambda env = function
204204
| Llet (Strict, _k, id, Lprim (Pduprecord (kind, size), _, _), body)
205205
when check_recordwith_updates id body ->
206206
begin match kind with
207+
| Record_mixed _
207208
| Record_boxed _ | Record_inlined (_, Variant_boxed _) -> RHS_block size
208209
| Record_unboxed | Record_inlined (_, Variant_unboxed) -> assert false
209210
| Record_float | Record_ufloat -> RHS_floatblock size
@@ -235,6 +236,8 @@ let rec size_of_lambda env = function
235236
| Lprim (Pmakearray (Pfloatarray, _, _), args, _)
236237
| Lprim (Pmakefloatblock _, args, _) ->
237238
RHS_floatblock (List.length args)
239+
| Lprim (Pmakemixedblock (_, _, _), args, _) ->
240+
RHS_block (List.length args)
238241
| Lprim (Pmakearray (Pgenarray, _, _), _, _) ->
239242
(* Pgenarray is excluded from recursive bindings by the
240243
check in Translcore.check_recursive_lambda *)
@@ -458,6 +461,17 @@ let comp_primitive stack_info p sz args =
458461
instructions for the ufloat primitives. *)
459462
| Pufloatfield (n, _sem) -> Kgetfloatfield n
460463
| Psetufloatfield (n, _init) -> Ksetfloatfield n
464+
| Pmixedfield (n, _, _sem) ->
465+
(* CR layouts: This will need reworking if we ever want bytecode
466+
to unbox fields that are written with unboxed types in the source
467+
language. *)
468+
(* Note, non-value mixed fields are always boxed in bytecode; they
469+
aren't stored flat like they are in native code.
470+
*)
471+
Kgetfield n
472+
| Psetmixedfield (n, _shape, _init) ->
473+
(* See the comment in the [Pmixedfield] case. *)
474+
Ksetfield n
461475
| Pduprecord _ -> Kccall("caml_obj_dup", 1)
462476
| Pccall p -> Kccall(p.prim_name, p.prim_arity)
463477
| Pperform ->
@@ -654,6 +668,7 @@ let comp_primitive stack_info p sz args =
654668
| Pmakeblock _
655669
| Pmakefloatblock _
656670
| Pmakeufloatblock _
671+
| Pmakemixedblock _
657672
| Pprobe_is_enabled _
658673
| Punbox_float _ | Pbox_float (_, _) | Punbox_int _ | Pbox_int _
659674
| Pmake_unboxed_product _ | Punboxed_product_field _
@@ -813,7 +828,8 @@ let rec comp_expr stack_info env exp sz cont =
813828
and comp_nonrec new_env sz i = function
814829
| [] -> comp_rec new_env sz ndecl decl_size
815830
| (_id, _exp, (RHS_block _ | RHS_infix _ |
816-
RHS_floatblock _ | RHS_function _))
831+
RHS_floatblock _ |
832+
RHS_function _))
817833
:: rem ->
818834
comp_nonrec new_env sz (i-1) rem
819835
| (_id, exp, RHS_nonrec) :: rem ->
@@ -822,7 +838,8 @@ let rec comp_expr stack_info env exp sz cont =
822838
and comp_rec new_env sz i = function
823839
| [] -> comp_expr stack_info new_env body sz (add_pop ndecl cont)
824840
| (_id, exp, (RHS_block _ | RHS_infix _ |
825-
RHS_floatblock _ | RHS_function _))
841+
RHS_floatblock _ |
842+
RHS_function _))
826843
:: rem ->
827844
comp_expr stack_info new_env exp sz
828845
(Kpush :: Kacc i :: Kccall("caml_update_dummy", 2) ::
@@ -895,6 +912,19 @@ let rec comp_expr stack_info env exp sz cont =
895912
let cont = add_pseudo_event loc !compunit_name cont in
896913
comp_args stack_info env args sz
897914
(Kmakefloatblock (List.length args) :: cont)
915+
| Lprim(Pmakemixedblock (_, shape, _), args, loc) ->
916+
(* There is no notion of a mixed block at runtime in bytecode. Further,
917+
source-level unboxed types are represented as boxed in bytecode, so
918+
no ceremony is needed to box values before inserting them into
919+
the (normal, unmixed) block.
920+
*)
921+
let total_len = shape.value_prefix_len + Array.length shape.flat_suffix in
922+
let cont = add_pseudo_event loc !compunit_name cont in
923+
comp_args stack_info env args sz
924+
(* CR mixed blocks v1: We will need to use the actual tag instead of [0]
925+
once mixed blocks can have non-zero tags.
926+
*)
927+
(Kmakeblock (total_len, 0) :: cont)
898928
| Lprim((Pmakearray (kind, _, _)) as p, args, loc) ->
899929
let cont = add_pseudo_event loc !compunit_name cont in
900930
begin match kind with

lambda/lambda.ml

+52-2
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,17 @@ type primitive =
145145
| Pmakeblock of int * mutable_flag * block_shape * alloc_mode
146146
| Pmakefloatblock of mutable_flag * alloc_mode
147147
| Pmakeufloatblock of mutable_flag * alloc_mode
148+
| Pmakemixedblock of mutable_flag * mixed_block_shape * alloc_mode
148149
| Pfield of int * immediate_or_pointer * field_read_semantics
149150
| Pfield_computed of field_read_semantics
150151
| Psetfield of int * immediate_or_pointer * initialization_or_assignment
151152
| Psetfield_computed of immediate_or_pointer * initialization_or_assignment
152153
| Pfloatfield of int * field_read_semantics * alloc_mode
153154
| Pufloatfield of int * field_read_semantics
155+
| Pmixedfield of int * mixed_block_read * field_read_semantics
154156
| Psetfloatfield of int * initialization_or_assignment
155157
| Psetufloatfield of int * initialization_or_assignment
158+
| Psetmixedfield of int * mixed_block_write * initialization_or_assignment
156159
| Pduprecord of Types.record_representation * int
157160
(* Unboxed products *)
158161
| Pmake_unboxed_product of layout list
@@ -337,6 +340,23 @@ and layout =
337340
and block_shape =
338341
value_kind list option
339342

343+
and flat_element = Types.flat_element = Imm | Float | Float64
344+
and flat_element_read =
345+
| Flat_read_imm
346+
| Flat_read_float of alloc_mode
347+
| Flat_read_float64
348+
and mixed_block_read =
349+
| Mread_value_prefix of immediate_or_pointer
350+
| Mread_flat_suffix of flat_element_read
351+
and mixed_block_write =
352+
| Mwrite_value_prefix of immediate_or_pointer
353+
| Mwrite_flat_suffix of flat_element
354+
355+
and mixed_block_shape = Types.mixed_record_shape =
356+
{ value_prefix_len : int;
357+
flat_suffix : flat_element array;
358+
}
359+
340360
and array_kind =
341361
Pgenarray | Paddrarray | Pintarray | Pfloatarray
342362
| Punboxedfloatarray of unboxed_float
@@ -1188,6 +1208,18 @@ let transl_prim mod_name name =
11881208
| exception Not_found ->
11891209
fatal_error ("Primitive " ^ name ^ " not found.")
11901210

1211+
let transl_mixed_record_shape : Types.mixed_record_shape -> mixed_block_shape =
1212+
fun x -> x
1213+
1214+
let count_mixed_block_values_and_floats =
1215+
Types.count_mixed_record_values_and_floats
1216+
1217+
type mixed_block_element = Types.mixed_record_element =
1218+
| Value_prefix
1219+
| Flat_suffix of flat_element
1220+
1221+
let get_mixed_block_element = Types.get_mixed_record_element
1222+
11911223
(* Compile a sequence of expressions *)
11921224

11931225
let rec make_sequence fn = function
@@ -1560,11 +1592,19 @@ let primitive_may_allocate : primitive -> alloc_mode option = function
15601592
| Pmakeblock (_, _, _, m) -> Some m
15611593
| Pmakefloatblock (_, m) -> Some m
15621594
| Pmakeufloatblock (_, m) -> Some m
1595+
| Pmakemixedblock (_, _, m) -> Some m
15631596
| Pfield _ | Pfield_computed _ | Psetfield _ | Psetfield_computed _ -> None
15641597
| Pfloatfield (_, _, m) -> Some m
15651598
| Pufloatfield _ -> None
1599+
| Pmixedfield (_, read, _) -> begin
1600+
match read with
1601+
| Mread_value_prefix _ -> None
1602+
| Mread_flat_suffix (Flat_read_float m) -> Some m
1603+
| Mread_flat_suffix (Flat_read_float64 | Flat_read_imm) -> None
1604+
end
15661605
| Psetfloatfield _ -> None
15671606
| Psetufloatfield _ -> None
1607+
| Psetmixedfield _ -> None
15681608
| Pduprecord _ -> Some alloc_heap
15691609
| Pmake_unboxed_product _ | Punboxed_product_field _ -> None
15701610
| Pccall p -> alloc_mode_of_primitive_description p
@@ -1708,7 +1748,7 @@ let primitive_result_layout (p : primitive) =
17081748
| Popaque layout | Pobj_magic layout -> layout
17091749
| Pbytes_to_string | Pbytes_of_string -> layout_string
17101750
| Pignore | Psetfield _ | Psetfield_computed _ | Psetfloatfield _ | Poffsetref _
1711-
| Psetufloatfield _
1751+
| Psetufloatfield _ | Psetmixedfield _
17121752
| Pbytessetu | Pbytessets | Parraysetu _ | Parraysets _ | Pbigarrayset _
17131753
| Pbytes_set_16 _ | Pbytes_set_32 _ | Pbytes_set_64 _ | Pbytes_set_128 _
17141754
| Pbigstring_set_16 _ | Pbigstring_set_32 _ | Pbigstring_set_64 _ | Pbigstring_set_128 _
@@ -1718,7 +1758,7 @@ let primitive_result_layout (p : primitive) =
17181758
-> layout_unit
17191759
| Pgetglobal _ | Psetglobal _ | Pgetpredef _ -> layout_module_field
17201760
| Pmakeblock _ | Pmakefloatblock _ | Pmakearray _ | Pduprecord _
1721-
| Pmakeufloatblock _
1761+
| Pmakeufloatblock _ | Pmakemixedblock _
17221762
| Pduparray _ | Pbigarraydim _ | Pobj_dup -> layout_block
17231763
| Pfield _ | Pfield_computed _ -> layout_field
17241764
| Punboxed_product_field (field, layouts) -> (Array.of_list layouts).(field)
@@ -1729,6 +1769,16 @@ let primitive_result_layout (p : primitive) =
17291769
| Pbox_float (f, _) -> layout_boxed_float f
17301770
| Pufloatfield _ -> Punboxed_float Pfloat64
17311771
| Punbox_float float_kind -> Punboxed_float float_kind
1772+
| Pmixedfield (_, kind, _) -> begin
1773+
match kind with
1774+
| Mread_value_prefix _ -> layout_field
1775+
| Mread_flat_suffix proj -> begin
1776+
match proj with
1777+
| Flat_read_imm -> layout_int
1778+
| Flat_read_float _ -> layout_boxed_float Pfloat64
1779+
| Flat_read_float64 -> layout_unboxed_float Pfloat64
1780+
end
1781+
end
17321782
| Pccall { prim_native_repr_res = _, repr_res } -> layout_of_extern_repr repr_res
17331783
| Praise _ -> layout_bottom
17341784
| Psequor | Psequand | Pnot

lambda/lambda.mli

+34
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,20 @@ type primitive =
102102
| Pmakeblock of int * mutable_flag * block_shape * alloc_mode
103103
| Pmakefloatblock of mutable_flag * alloc_mode
104104
| Pmakeufloatblock of mutable_flag * alloc_mode
105+
| Pmakemixedblock of mutable_flag * mixed_block_shape * alloc_mode
105106
| Pfield of int * immediate_or_pointer * field_read_semantics
106107
| Pfield_computed of field_read_semantics
107108
| Psetfield of int * immediate_or_pointer * initialization_or_assignment
108109
| Psetfield_computed of immediate_or_pointer * initialization_or_assignment
109110
| Pfloatfield of int * field_read_semantics * alloc_mode
110111
| Pufloatfield of int * field_read_semantics
112+
| Pmixedfield of int * mixed_block_read * field_read_semantics
113+
(* [Pmixedfield] is an access to either the flat suffix or value prefix of a
114+
mixed record.
115+
*)
111116
| Psetfloatfield of int * initialization_or_assignment
112117
| Psetufloatfield of int * initialization_or_assignment
118+
| Psetmixedfield of int * mixed_block_write * initialization_or_assignment
113119
| Pduprecord of Types.record_representation * int
114120
(* Unboxed products *)
115121
| Pmake_unboxed_product of layout list
@@ -341,6 +347,24 @@ and layout =
341347
and block_shape =
342348
value_kind list option
343349

350+
and flat_element = Imm | Float | Float64
351+
and flat_element_read =
352+
| Flat_read_imm
353+
| Flat_read_float of alloc_mode
354+
| Flat_read_float64
355+
and mixed_block_read =
356+
| Mread_value_prefix of immediate_or_pointer
357+
| Mread_flat_suffix of flat_element_read
358+
and mixed_block_write =
359+
| Mwrite_value_prefix of immediate_or_pointer
360+
| Mwrite_flat_suffix of flat_element
361+
362+
and mixed_block_shape =
363+
{ value_prefix_len : int;
364+
(* We use an array just so we can index into the middle. *)
365+
flat_suffix : flat_element array;
366+
}
367+
344368
and boxed_float = Primitive.boxed_float =
345369
| Pfloat64
346370
| Pfloat32
@@ -744,6 +768,16 @@ val transl_value_path: scoped_location -> Env.t -> Path.t -> lambda
744768
val transl_extension_path: scoped_location -> Env.t -> Path.t -> lambda
745769
val transl_class_path: scoped_location -> Env.t -> Path.t -> lambda
746770

771+
val transl_mixed_record_shape: Types.mixed_record_shape -> mixed_block_shape
772+
val count_mixed_block_values_and_floats : mixed_block_shape -> int * int
773+
774+
type mixed_block_element =
775+
| Value_prefix
776+
| Flat_suffix of flat_element
777+
778+
(** Raises if the int is out of bounds. *)
779+
val get_mixed_block_element : mixed_block_shape -> int -> mixed_block_element
780+
747781
val make_sequence: ('a -> lambda) -> 'a list -> lambda
748782

749783
val subst:

lambda/matching.ml

+17-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ let jkind_layout_must_be_value loc jkind =
119119
let check_record_field_jkind lbl =
120120
match Jkind.(get_default_value lbl.lbl_jkind), lbl.lbl_repres with
121121
| (Value | Immediate | Immediate64), _ -> ()
122-
| Float64, Record_ufloat -> ()
122+
| Float64, (Record_ufloat | Record_mixed _) -> ()
123123
| Float64, (Record_boxed _ | Record_inlined _
124124
| Record_unboxed | Record_float) ->
125125
raise (Error (lbl.lbl_loc, Illegal_record_field Float64))
@@ -2167,6 +2167,22 @@ let get_expr_args_record ~scopes head (arg, _mut, sort, layout) rem =
21672167
| Record_inlined (_, Variant_extensible) ->
21682168
Lprim (Pfield (lbl.lbl_pos + 1, ptr, sem), [ arg ], loc),
21692169
lbl_sort, lbl_layout
2170+
| Record_mixed { value_prefix_len; flat_suffix } ->
2171+
let read =
2172+
if pos < value_prefix_len then Mread_value_prefix ptr
2173+
else
2174+
let read =
2175+
match flat_suffix.(pos - value_prefix_len) with
2176+
| Imm -> Flat_read_imm
2177+
| Float64 -> Flat_read_float64
2178+
| Float ->
2179+
(* TODO: could optimise to Alloc_local sometimes *)
2180+
Flat_read_float alloc_heap
2181+
in
2182+
Mread_flat_suffix read
2183+
in
2184+
Lprim (Pmixedfield (lbl.lbl_pos, read, sem), [ arg ], loc),
2185+
lbl_sort, lbl_layout
21702186
in
21712187
let str = if Types.is_mutable lbl.lbl_mut then StrictOpt else Alias in
21722188
(access, str, sort, layout) :: make_args (pos + 1)

0 commit comments

Comments
 (0)