Skip to content

Commit 7759293

Browse files
committed
Simplify and optimize the way that enums are passed in fused adapters
instead of treating them like variants that don't have payloads, just check that the discriminant is in bounds.
1 parent e471433 commit 7759293

File tree

2 files changed

+159
-23
lines changed

2 files changed

+159
-23
lines changed

crates/environ/src/fact/trampoline.rs

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
//! can be somewhat arbitrary, an intentional decision.
1717
1818
use crate::component::{
19-
CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, FixedEncoding as FE,
20-
FlatType, InterfaceType, MAX_FLAT_PARAMS, StringEncoding, Transcode,
21-
TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFlagsIndex, TypeFutureTableIndex,
22-
TypeListIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex,
23-
TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex, VariantInfo,
19+
CanonicalAbiInfo, ComponentTypesBuilder, FixedEncoding as FE, FlatType, InterfaceType,
20+
StringEncoding, Transcode, TypeComponentLocalErrorContextTableIndex, TypeEnumIndex,
21+
TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex,
22+
TypeResourceTableIndex, TypeResultIndex, TypeStreamTableIndex, TypeTupleIndex,
23+
TypeVariantIndex, VariantInfo, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, MAX_FLAT_PARAMS,
2424
};
2525
use crate::fact::signature::Signature;
2626
use crate::fact::transcode::Transcoder;
@@ -2679,26 +2679,50 @@ impl<'a, 'b> Compiler<'a, 'b> {
26792679
InterfaceType::Enum(t) => &self.types[*t],
26802680
_ => panic!("expected an option"),
26812681
};
2682-
let src_info = variant_info(self.types, src_ty.names.iter().map(|_| None));
2683-
let dst_info = variant_info(self.types, dst_ty.names.iter().map(|_| None));
26842682

2685-
self.convert_variant(
2686-
src,
2687-
&src_info,
2688-
dst,
2689-
&dst_info,
2690-
src_ty.names.iter().enumerate().map(|(src_i, src_name)| {
2691-
let dst_i = dst_ty.names.iter().position(|n| n == src_name).unwrap();
2692-
let src_i = u32::try_from(src_i).unwrap();
2693-
let dst_i = u32::try_from(dst_i).unwrap();
2694-
VariantCase {
2695-
src_i,
2696-
dst_i,
2697-
src_ty: None,
2698-
dst_ty: None,
2683+
debug_assert_eq!(src_ty.info.size, dst_ty.info.size);
2684+
debug_assert_eq!(src_ty.names.len(), dst_ty.names.len());
2685+
debug_assert!(src_ty
2686+
.names
2687+
.iter()
2688+
.zip(dst_ty.names.iter())
2689+
.all(|(a, b)| a == b));
2690+
2691+
// Get the discriminant.
2692+
match src {
2693+
Source::Stack(s) => self.stack_get(&s.slice(0..1), ValType::I32),
2694+
Source::Memory(mem) => match src_ty.info.size {
2695+
DiscriminantSize::Size1 => self.i32_load8u(mem),
2696+
DiscriminantSize::Size2 => self.i32_load16u(mem),
2697+
DiscriminantSize::Size4 => self.i32_load(mem),
2698+
},
2699+
}
2700+
let tmp = self.local_tee_new_tmp(ValType::I32);
2701+
2702+
// Assert that the discriminant is valid.
2703+
self.instruction(I32Const(i32::try_from(src_ty.names.len()).unwrap()));
2704+
self.instruction(I32GtU);
2705+
self.instruction(If(BlockType::Empty));
2706+
self.trap(Trap::InvalidDiscriminant);
2707+
self.instruction(End);
2708+
2709+
// Save the discriminant to the destination.
2710+
match dst {
2711+
Destination::Stack(stack, _) => {
2712+
self.local_get_tmp(&tmp);
2713+
self.stack_set(&stack[..1], ValType::I32)
2714+
}
2715+
Destination::Memory(mem) => {
2716+
self.push_dst_addr(dst);
2717+
self.local_get_tmp(&tmp);
2718+
match dst_ty.info.size {
2719+
DiscriminantSize::Size1 => self.i32_store8(mem),
2720+
DiscriminantSize::Size2 => self.i32_store16(mem),
2721+
DiscriminantSize::Size4 => self.i32_store(mem),
26992722
}
2700-
}),
2701-
);
2723+
}
2724+
}
2725+
self.free_temp_local(tmp);
27022726
}
27032727

27042728
fn translate_option(
@@ -3118,6 +3142,10 @@ impl<'a, 'b> Compiler<'a, 'b> {
31183142
self.gen_temp_local(ty, LocalSet)
31193143
}
31203144

3145+
fn local_get_tmp(&mut self, local: &TempLocal) {
3146+
self.instruction(LocalGet(local.idx));
3147+
}
3148+
31213149
fn gen_temp_local(&mut self, ty: ValType, insn: fn(u32) -> Instruction<'static>) -> TempLocal {
31223150
// First check to see if any locals are available in this function which
31233151
// were previously generated but are no longer in use.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
;;! target = "riscv64"
2+
;;! test = 'optimize'
3+
;;! filter = 'wasm_func_1'
4+
5+
(component
6+
(type $a (enum "a" "b" "c"))
7+
(type $func_ty (func (param "x" $a)))
8+
9+
(component $c1
10+
(import "a" (type $a' (eq $a)))
11+
(core module $m1
12+
(func (export "f") (result i32)
13+
(i32.const 0)))
14+
(core instance $ci1 (instantiate $m1))
15+
(func (export "f") (result $a') (canon lift (core func $ci1 "f"))))
16+
17+
(component $c2
18+
(import "a" (type $a' (eq $a)))
19+
(import "f" (func $f (result $a')))
20+
(core func $g (canon lower (func $f)))
21+
(core module $m2
22+
(import "" "f" (func (result i32)))
23+
(func (export "f") (result i32) (call 0)))
24+
(core instance $ci2
25+
(instantiate $m2 (with "" (instance (export "f" (func $g))))))
26+
(func (export "f") (result $a') (canon lift (core func $ci2 "f"))))
27+
28+
(instance $i1 (instantiate $c1 (with "a" (type $a))))
29+
(instance $i2 (instantiate $c2
30+
(with "a" (type $a))
31+
(with "f" (func $i1 "f"))))
32+
)
33+
34+
;; function u0:1(i64 vmctx, i64) -> i32 tail {
35+
;; gv0 = vmctx
36+
;; gv1 = load.i64 notrap aligned readonly gv0+8
37+
;; gv2 = load.i64 notrap aligned gv1+16
38+
;; gv3 = vmctx
39+
;; gv4 = load.i64 notrap aligned readonly can_move gv3+104
40+
;; gv5 = load.i64 notrap aligned readonly can_move gv3+80
41+
;; sig0 = (i64 vmctx, i64) -> i32 tail
42+
;; fn0 = u0:0 sig0
43+
;; stack_limit = gv2
44+
;;
45+
;; block0(v0: i64, v1: i64):
46+
;; @0063 v4 = load.i64 notrap aligned readonly can_move v0+104
47+
;; @0063 v5 = load.i32 notrap aligned table v4
48+
;; @0065 v6 = iconst.i32 1
49+
;; @0067 v7 = band v5, v6 ; v6 = 1
50+
;; @0061 v3 = iconst.i32 0
51+
;; @0068 v8 = icmp eq v7, v3 ; v3 = 0
52+
;; @0068 v9 = uextend.i32 v8
53+
;; @0069 brif v9, block2, block3
54+
;;
55+
;; block2:
56+
;; @006b trap user11
57+
;;
58+
;; block3:
59+
;; @006d v10 = load.i64 notrap aligned readonly can_move v0+80
60+
;; @006d v11 = load.i32 notrap aligned table v10
61+
;; @006f v12 = iconst.i32 2
62+
;; @0071 v13 = band v11, v12 ; v12 = 2
63+
;; v82 = iconst.i32 0
64+
;; v83 = icmp eq v13, v82 ; v82 = 0
65+
;; @0072 v15 = uextend.i32 v83
66+
;; @0073 brif v15, block4, block5
67+
;;
68+
;; block4:
69+
;; @0075 trap user11
70+
;;
71+
;; block5:
72+
;; @0079 v18 = iconst.i32 -3
73+
;; @007b v19 = band.i32 v11, v18 ; v18 = -3
74+
;; @007c store notrap aligned table v19, v10
75+
;; v70 = iconst.i32 -4
76+
;; v76 = band.i32 v11, v70 ; v70 = -4
77+
;; @0083 store notrap aligned table v76, v10
78+
;; v84 = iconst.i32 1
79+
;; v85 = bor v19, v84 ; v84 = 1
80+
;; @008a store notrap aligned table v85, v10
81+
;; @008c v32 = load.i64 notrap aligned readonly can_move v0+56
82+
;; @008c v33 = load.i64 notrap aligned readonly can_move v0+72
83+
;; @008c v34 = call_indirect sig0, v32(v33, v0)
84+
;; @0090 v36 = load.i32 notrap aligned table v4
85+
;; @0080 v23 = iconst.i32 -2
86+
;; @0094 v38 = band v36, v23 ; v23 = -2
87+
;; @0095 store notrap aligned table v38, v4
88+
;; @009b v40 = iconst.i32 3
89+
;; @009d v41 = icmp ugt v34, v40 ; v40 = 3
90+
;; @009d v42 = uextend.i32 v41
91+
;; @009e brif v42, block6, block7
92+
;;
93+
;; block6:
94+
;; @00a0 trap user11
95+
;;
96+
;; block7:
97+
;; v86 = iconst.i32 1
98+
;; v87 = bor.i32 v36, v86 ; v86 = 1
99+
;; @00a9 store notrap aligned table v87, v4
100+
;; @00ab v49 = load.i32 notrap aligned table v10
101+
;; v88 = iconst.i32 2
102+
;; v89 = bor v49, v88 ; v88 = 2
103+
;; @00b0 store notrap aligned table v89, v10
104+
;; @00b2 jump block1
105+
;;
106+
;; block1:
107+
;; @00b2 return v34
108+
;; }

0 commit comments

Comments
 (0)