Skip to content

Commit 71ce1d6

Browse files
committed
Separate variant layouts from constructor matching plans
The runtime representation of a variant is declaration-level data, while the decision for a particular match depends on its arms, actions, default, and exhaustiveness. Represent the two separately: - Variant_runtime.layout stores immutable constructor representations and declaration-level matching facts computed once. - Type_variant stores an abstract one-shot layout_ref. Recursive declarations allocate it while provisional, then complete the same identity after the recursive group is available. - Ordinary constructor descriptions address their representation by layout reference and source position, removing repeated name lookup and duplicated layout storage. - Matching builds one occurrence-specific constructor_matching_plan in combine_constructor and immediately lowers it to existing Lambda forms. No Lam or Lambda expression form is added. - Construction, matching, and type-based optimization consume the canonical representation instead of reinterpreting runtime attributes. Rename Transparent to Unboxed and variant_dispatch to matching_facts so the remaining terms describe the represented facts rather than an implementation strategy. Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
1 parent eba15a7 commit 71ce1d6

19 files changed

Lines changed: 417 additions & 238 deletions

compiler/ml/datarepr.ml

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ let constructor_args priv cd_args cd_res path rep =
7070
let type_params = Type_set.elements arg_vars_set in
7171
let type_representation =
7272
match rep with
73-
| Record_unboxed _ -> Transparent
73+
| Record_unboxed _ -> Unboxed
7474
| _ -> Boxed
7575
in
7676
let tdecl =
@@ -102,19 +102,37 @@ let constructor_has_optional_shape
102102

103103
(* The constructor's entry in its variant's canonical layout *)
104104
let constructor_case (cstr : constructor_description) =
105-
match cstr.cstr_layout with
106-
| Some layout -> Variant_runtime.constructor_by_name layout cstr.cstr_name
107-
| None -> assert false
105+
match cstr.cstr_kind with
106+
| Ordinary_constructor representation ->
107+
Variant_runtime.representation representation
108+
| Extension_constructor _ -> assert false
108109

109-
(* Sole payload-carrying constructor of an unboxed type: constructing it is
110-
the identity at runtime *)
111-
let constructor_is_transparent (cstr : constructor_description) =
112-
(match cstr.cstr_layout with
113-
| Some [|Block _|] -> true
114-
| _ -> false)
115-
&& List.exists
116-
(fun (attribute, _) -> attribute.txt = "unboxed")
117-
cstr.cstr_attributes
110+
let constructor_variant (cstr : constructor_description) =
111+
match cstr.cstr_kind with
112+
| Ordinary_constructor {variant} -> Variant_runtime.get_layout variant
113+
| Extension_constructor _ -> assert false
114+
115+
let constructor_position (cstr : constructor_description) =
116+
match cstr.cstr_kind with
117+
| Ordinary_constructor {position} -> position
118+
| Extension_constructor _ -> assert false
119+
120+
let constructor_payload_is_unboxed (cstr : constructor_description) =
121+
match cstr.cstr_kind with
122+
| Ordinary_constructor representation -> (
123+
match Variant_runtime.representation representation with
124+
| Block {runtime = {untagged = true}} -> true
125+
| Constant _ | Block _ -> false)
126+
| Extension_constructor _ -> false
127+
128+
(* Sole payload-carrying constructor of an @unboxed type: constructing it is
129+
the identity at runtime. *)
130+
let constructor_is_unboxed (cstr : constructor_description) =
131+
match cstr.cstr_kind with
132+
| Ordinary_constructor {variant} ->
133+
constructor_payload_is_unboxed cstr
134+
&& Variant_runtime.length (Variant_runtime.get_layout variant) = 1
135+
| Extension_constructor _ -> false
118136

119137
let constructor_descrs ty_path decl cstrs =
120138
let layout =
@@ -123,27 +141,32 @@ let constructor_descrs ty_path decl cstrs =
123141
| Type_abstract | Type_record _ | Type_open -> assert false
124142
in
125143
let ty_res = newgenconstr ty_path decl.type_params in
126-
let num_nonconsts = Variant_runtime.num_blocks layout in
127-
let rec describe_constructors = function
144+
let rec describe_constructors position = function
128145
| [] -> []
129146
| {cd_id; cd_args; cd_res; cd_loc; cd_attributes} :: rem ->
130147
let ty_res =
131148
match cd_res with
132149
| Some ty_res' -> ty_res'
133150
| None -> ty_res
134151
in
135-
let descr_rem = describe_constructors rem in
152+
let descr_rem = describe_constructors (position + 1) rem in
136153
let cstr_name = Ident.name cd_id in
154+
let representation : Variant_runtime.constructor_reference =
155+
{variant = layout; position}
156+
in
137157
let existentials, cstr_args, cstr_inlined =
138-
let representation =
139-
if decl.type_representation = Transparent then Record_unboxed true
140-
else
141-
Record_inlined
142-
{name = cstr_name; num_nonconsts; attrs = cd_attributes}
158+
let record_representation =
159+
match cd_args with
160+
| Cstr_tuple _ ->
161+
(* [constructor_args] ignores this value for tuple payloads. *)
162+
Record_regular
163+
| Cstr_record _ when decl.type_representation = Unboxed ->
164+
Record_unboxed true
165+
| Cstr_record _ -> Record_inlined {name = cstr_name; representation}
143166
in
144167
constructor_args decl.type_private cd_args cd_res
145168
(Path.Pdot (ty_path, cstr_name, Path.nopos))
146-
representation
169+
record_representation
147170
in
148171
let cstr =
149172
{
@@ -152,8 +175,7 @@ let constructor_descrs ty_path decl cstrs =
152175
cstr_existentials = existentials;
153176
cstr_args;
154177
cstr_arity = List.length cstr_args;
155-
cstr_kind = Ordinary_constructor;
156-
cstr_layout = Some layout;
178+
cstr_kind = Ordinary_constructor representation;
157179
cstr_private = decl.type_private;
158180
cstr_generalized = cd_res <> None;
159181
cstr_loc = cd_loc;
@@ -163,7 +185,7 @@ let constructor_descrs ty_path decl cstrs =
163185
in
164186
(cd_id, cstr) :: descr_rem
165187
in
166-
let result = describe_constructors cstrs in
188+
let result = describe_constructors 0 cstrs in
167189
match result with
168190
| [
169191
(({Ident.name = "None"} as a_id), ({cstr_args = []} as a_descr));
@@ -204,7 +226,6 @@ let extension_descr path_ext ext =
204226
cstr_args;
205227
cstr_arity = List.length cstr_args;
206228
cstr_kind = Extension_constructor path_ext;
207-
cstr_layout = None;
208229
cstr_private = ext.ext_private;
209230
cstr_generalized = ext.ext_ret_type <> None;
210231
cstr_loc = ext.ext_loc;

compiler/ml/datarepr.mli

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ open Types
2121
val constructor_has_optional_shape : Types.constructor_description -> bool
2222
val constructor_case :
2323
Types.constructor_description -> Variant_runtime.constructor_case
24-
val constructor_is_transparent : Types.constructor_description -> bool
24+
val constructor_variant :
25+
Types.constructor_description -> Variant_runtime.layout
26+
val constructor_position : Types.constructor_description -> int
27+
val constructor_payload_is_unboxed : Types.constructor_description -> bool
28+
val constructor_is_unboxed : Types.constructor_description -> bool
2529

2630
val extension_descr : Path.t -> extension_constructor -> constructor_description
2731

compiler/ml/includecore.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,8 @@ let type_declarations ?(equality = false) ~loc env name decl1 id decl2 =
350350
in
351351
match
352352
( decl2.type_kind,
353-
decl1.type_representation = Transparent || untagged1,
354-
decl2.type_representation = Transparent || untagged2 )
353+
decl1.type_representation = Unboxed || untagged1,
354+
decl2.type_representation = Unboxed || untagged2 )
355355
with
356356
| Type_abstract, _, _ -> []
357357
| _, true, false -> [Unboxed_representation false]

compiler/ml/lambda.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ and switch_key =
385385

386386
and switch_dispatch =
387387
| Switch_direct
388-
| Switch_variant of Variant_runtime.variant_dispatch
388+
| Switch_variant of Variant_runtime.matching_facts
389389

390390
and 'a switch = {
391391
sw_consts_full: bool;

compiler/ml/lambda.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ and switch_key =
357357

358358
and switch_dispatch =
359359
| Switch_direct
360-
| Switch_variant of Variant_runtime.variant_dispatch
360+
| Switch_variant of Variant_runtime.matching_facts
361361

362362
and 'a switch = {
363363
sw_consts_full: bool;

0 commit comments

Comments
 (0)