Skip to content

Commit da45c6c

Browse files
authored
[Custom Descriptors] Heap2Local: Store descriptors as non-nullable (#7921)
#7915 only handled literal nulls, but the type can be nullable too. Simplify this by just storing a non-nullable type.
1 parent 8778512 commit da45c6c

2 files changed

Lines changed: 87 additions & 36 deletions

File tree

src/passes/Heap2Local.cpp

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,10 @@ struct Struct2Local : PostWalker<Struct2Local> {
604604
Builder builder;
605605
const FieldList& fields;
606606

607+
// The descriptor can arrive as nullable, but we trap if it is null, so there
608+
// is only something to store if it is non-nullable, and we store it that way.
609+
Type descType;
610+
607611
Struct2Local(StructNew* allocation,
608612
EscapeAnalyzer& analyzer,
609613
Function* func,
@@ -616,7 +620,8 @@ struct Struct2Local : PostWalker<Struct2Local> {
616620
localIndexes.push_back(builder.addVar(func, field.type));
617621
}
618622
if (allocation->desc) {
619-
localIndexes.push_back(builder.addVar(func, allocation->desc->type));
623+
descType = allocation->desc->type.with(NonNullable);
624+
localIndexes.push_back(builder.addVar(func, descType));
620625
}
621626

622627
// Replace the things we need to using the visit* methods.
@@ -744,7 +749,7 @@ struct Struct2Local : PostWalker<Struct2Local> {
744749
}
745750
}
746751
if (curr->desc) {
747-
tempIndexes.push_back(builder.addVar(func, curr->desc->type));
752+
tempIndexes.push_back(builder.addVar(func, descType));
748753
}
749754

750755
// Store the initial values into the temp locals.
@@ -773,8 +778,7 @@ struct Struct2Local : PostWalker<Struct2Local> {
773778
contents.push_back(builder.makeLocalSet(localIndexes[i], val));
774779
}
775780
if (curr->desc) {
776-
auto* val =
777-
builder.makeLocalGet(tempIndexes[numTemps - 1], curr->desc->type);
781+
auto* val = builder.makeLocalGet(tempIndexes[numTemps - 1], descType);
778782
contents.push_back(
779783
builder.makeLocalSet(localIndexes[fields.size()], val));
780784
}
@@ -902,13 +906,12 @@ struct Struct2Local : PostWalker<Struct2Local> {
902906
} else {
903907
// The cast succeeds iff the optimized allocation's descriptor is the
904908
// same as the given descriptor and traps otherwise.
905-
auto type = allocation->desc->type;
906909
replaceCurrent(builder.blockify(
907910
builder.makeDrop(curr->ref),
908911
builder.makeIf(
909912
builder.makeRefEq(
910913
curr->desc,
911-
builder.makeLocalGet(localIndexes[fields.size()], type)),
914+
builder.makeLocalGet(localIndexes[fields.size()], descType)),
912915
builder.makeRefNull(allocation->type.getHeapType()),
913916
builder.makeUnreachable())));
914917
}
@@ -939,18 +942,8 @@ struct Struct2Local : PostWalker<Struct2Local> {
939942
return;
940943
}
941944

942-
auto type = allocation->desc->type;
943-
Expression* value = builder.makeLocalGet(localIndexes[fields.size()], type);
944-
if (type != curr->type) {
945-
// We know exactly the allocation that flows into this expression, so we
946-
// know the exact type of the descriptor. This type may be more precise
947-
// than the static type of this expression.
948-
refinalize = true;
949-
if (type.isNull()) {
950-
// This traps.
951-
value = builder.makeUnreachable();
952-
}
953-
}
945+
auto descIndex = localIndexes[fields.size()];
946+
Expression* value = builder.makeLocalGet(descIndex, descType);
954947
replaceCurrent(builder.blockify(builder.makeDrop(curr->ref), value));
955948
}
956949

test/lit/passes/heap2local-desc.wast

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@
5454

5555
;; CHECK: (func $dropped (type $10)
5656
;; CHECK-NEXT: (local $0 i32)
57-
;; CHECK-NEXT: (local $1 (ref null (exact $descriptor)))
57+
;; CHECK-NEXT: (local $1 (ref (exact $descriptor)))
5858
;; CHECK-NEXT: (local $2 i32)
59-
;; CHECK-NEXT: (local $3 (ref null (exact $descriptor)))
59+
;; CHECK-NEXT: (local $3 (ref (exact $descriptor)))
6060
;; CHECK-NEXT: (drop
6161
;; CHECK-NEXT: (block (result nullref)
6262
;; CHECK-NEXT: (local.set $2
@@ -88,8 +88,8 @@
8888

8989
;; CHECK: (func $dropped-default (type $10)
9090
;; CHECK-NEXT: (local $0 i32)
91-
;; CHECK-NEXT: (local $1 (ref null (exact $descriptor)))
92-
;; CHECK-NEXT: (local $2 (ref null (exact $descriptor)))
91+
;; CHECK-NEXT: (local $1 (ref (exact $descriptor)))
92+
;; CHECK-NEXT: (local $2 (ref (exact $descriptor)))
9393
;; CHECK-NEXT: (drop
9494
;; CHECK-NEXT: (block (result nullref)
9595
;; CHECK-NEXT: (local.set $2
@@ -211,7 +211,7 @@
211211
;; CHECK-NEXT: (local $1 (ref (exact $sub.desc)))
212212
;; CHECK-NEXT: (block (result (ref (exact $sub.desc)))
213213
;; CHECK-NEXT: (drop
214-
;; CHECK-NEXT: (block (result nullref)
214+
;; CHECK-NEXT: (block (result (ref null $super))
215215
;; CHECK-NEXT: (block (result nullref)
216216
;; CHECK-NEXT: (local.set $1
217217
;; CHECK-NEXT: (struct.new_default $sub.desc)
@@ -241,8 +241,8 @@
241241

242242
;; CHECK: (func $cast-desc-success (type $10)
243243
;; CHECK-NEXT: (local $desc (ref null (exact $super.desc)))
244-
;; CHECK-NEXT: (local $1 (ref null (exact $super.desc)))
245-
;; CHECK-NEXT: (local $2 (ref null (exact $super.desc)))
244+
;; CHECK-NEXT: (local $1 (ref (exact $super.desc)))
245+
;; CHECK-NEXT: (local $2 (ref (exact $super.desc)))
246246
;; CHECK-NEXT: (local.set $desc
247247
;; CHECK-NEXT: (struct.new_default $super.desc)
248248
;; CHECK-NEXT: )
@@ -334,8 +334,8 @@
334334
)
335335

336336
;; CHECK: (func $cast-desc-fail-reverse (type $11) (param $desc (ref null (exact $super.desc)))
337-
;; CHECK-NEXT: (local $1 (ref null (exact $super.desc)))
338-
;; CHECK-NEXT: (local $2 (ref null (exact $super.desc)))
337+
;; CHECK-NEXT: (local $1 (ref (exact $super.desc)))
338+
;; CHECK-NEXT: (local $2 (ref (exact $super.desc)))
339339
;; CHECK-NEXT: (drop
340340
;; CHECK-NEXT: (block (result nullref)
341341
;; CHECK-NEXT: (drop
@@ -639,8 +639,8 @@
639639

640640
;; CHECK: (func $cast-desc-and-ref (type $14) (param $desc (ref null (exact $chain-descriptor)))
641641
;; CHECK-NEXT: (local $middle (ref null (exact $chain-middle)))
642-
;; CHECK-NEXT: (local $2 (ref null (exact $chain-descriptor)))
643-
;; CHECK-NEXT: (local $3 (ref null (exact $chain-descriptor)))
642+
;; CHECK-NEXT: (local $2 (ref (exact $chain-descriptor)))
643+
;; CHECK-NEXT: (local $3 (ref (exact $chain-descriptor)))
644644
;; CHECK-NEXT: (drop
645645
;; CHECK-NEXT: (block (result nullref)
646646
;; CHECK-NEXT: (local.set $3
@@ -687,8 +687,8 @@
687687

688688
;; CHECK: (func $cast-desc-and-ref-nullable (type $14) (param $desc (ref null (exact $chain-descriptor)))
689689
;; CHECK-NEXT: (local $middle (ref null (exact $chain-middle)))
690-
;; CHECK-NEXT: (local $2 (ref null (exact $chain-descriptor)))
691-
;; CHECK-NEXT: (local $3 (ref null (exact $chain-descriptor)))
690+
;; CHECK-NEXT: (local $2 (ref (exact $chain-descriptor)))
691+
;; CHECK-NEXT: (local $3 (ref (exact $chain-descriptor)))
692692
;; CHECK-NEXT: (drop
693693
;; CHECK-NEXT: (block (result nullref)
694694
;; CHECK-NEXT: (local.set $3
@@ -868,9 +868,11 @@
868868

869869
;; CHECK: (type $2 (func (result (ref (exact $desc)))))
870870

871-
;; CHECK: (func $test (type $2) (result (ref (exact $desc)))
872-
;; CHECK-NEXT: (local $0 nullref)
873-
;; CHECK-NEXT: (local $1 nullref)
871+
;; CHECK: (type $3 (func (param (ref null (exact $desc))) (result (ref (exact $desc)))))
872+
873+
;; CHECK: (func $null (type $2) (result (ref (exact $desc)))
874+
;; CHECK-NEXT: (local $0 (ref none))
875+
;; CHECK-NEXT: (local $1 (ref none))
874876
;; CHECK-NEXT: (drop
875877
;; CHECK-NEXT: (block (result nullref)
876878
;; CHECK-NEXT: (local.set $1
@@ -884,9 +886,9 @@
884886
;; CHECK-NEXT: (ref.null none)
885887
;; CHECK-NEXT: )
886888
;; CHECK-NEXT: )
887-
;; CHECK-NEXT: (unreachable)
889+
;; CHECK-NEXT: (local.get $0)
888890
;; CHECK-NEXT: )
889-
(func $test (result (ref (exact $desc)))
891+
(func $null (result (ref (exact $desc)))
890892
;; Read a null descriptor from a struct.new we can convert to locals. We do
891893
;; not end up with a (ref (exact $desc)) here, since this will trap, so we
892894
;; emit an unreachable.
@@ -896,6 +898,62 @@
896898
)
897899
)
898900
)
901+
902+
;; CHECK: (func $nullable-param (type $3) (param $desc (ref null (exact $desc))) (result (ref (exact $desc)))
903+
;; CHECK-NEXT: (local $1 (ref (exact $desc)))
904+
;; CHECK-NEXT: (local $2 (ref (exact $desc)))
905+
;; CHECK-NEXT: (drop
906+
;; CHECK-NEXT: (block (result nullref)
907+
;; CHECK-NEXT: (local.set $2
908+
;; CHECK-NEXT: (ref.as_non_null
909+
;; CHECK-NEXT: (local.get $desc)
910+
;; CHECK-NEXT: )
911+
;; CHECK-NEXT: )
912+
;; CHECK-NEXT: (local.set $1
913+
;; CHECK-NEXT: (local.get $2)
914+
;; CHECK-NEXT: )
915+
;; CHECK-NEXT: (ref.null none)
916+
;; CHECK-NEXT: )
917+
;; CHECK-NEXT: )
918+
;; CHECK-NEXT: (local.get $1)
919+
;; CHECK-NEXT: )
920+
(func $nullable-param (param $desc (ref null (exact $desc))) (result (ref (exact $desc)))
921+
;; Read a null descriptor from a nullable param.
922+
(ref.get_desc $struct
923+
(struct.new_default $struct
924+
(local.get $desc)
925+
)
926+
)
927+
)
928+
929+
;; CHECK: (func $nullable-local (type $2) (result (ref (exact $desc)))
930+
;; CHECK-NEXT: (local $desc (ref null (exact $desc)))
931+
;; CHECK-NEXT: (local $1 (ref (exact $desc)))
932+
;; CHECK-NEXT: (local $2 (ref (exact $desc)))
933+
;; CHECK-NEXT: (drop
934+
;; CHECK-NEXT: (block (result nullref)
935+
;; CHECK-NEXT: (local.set $2
936+
;; CHECK-NEXT: (ref.as_non_null
937+
;; CHECK-NEXT: (local.get $desc)
938+
;; CHECK-NEXT: )
939+
;; CHECK-NEXT: )
940+
;; CHECK-NEXT: (local.set $1
941+
;; CHECK-NEXT: (local.get $2)
942+
;; CHECK-NEXT: )
943+
;; CHECK-NEXT: (ref.null none)
944+
;; CHECK-NEXT: )
945+
;; CHECK-NEXT: )
946+
;; CHECK-NEXT: (local.get $1)
947+
;; CHECK-NEXT: )
948+
(func $nullable-local (result (ref (exact $desc)))
949+
(local $desc (ref null (exact $desc)))
950+
;; Read a null descriptor from a nullable local.
951+
(ref.get_desc $struct
952+
(struct.new_default $struct
953+
(local.get $desc)
954+
)
955+
)
956+
)
899957
)
900958

901959
;; A definitely-failing descriptor cast. We have two pairs of descriptor/

0 commit comments

Comments
 (0)