@@ -554,6 +554,10 @@ def_instruction! {
554
554
blocks: usize ,
555
555
} : [ 1 ] => [ 0 ] ,
556
556
557
+ /// Deallocates the language-specific handle representation on the top
558
+ /// of the stack. Used for async imports.
559
+ DropHandle { ty: & ' a Type } : [ 1 ] => [ 0 ] ,
560
+
557
561
/// Call `task.return` for an async-lifted export.
558
562
///
559
563
/// This will call core wasm import `name` which will be mapped to
@@ -783,33 +787,37 @@ pub fn post_return(resolve: &Resolve, func: &Function, bindgen: &mut impl Bindge
783
787
/// a list or a string primarily.
784
788
pub fn guest_export_needs_post_return ( resolve : & Resolve , func : & Function ) -> bool {
785
789
func. result
786
- . map ( |t| needs_post_return ( resolve, & t) )
790
+ . map ( |t| needs_deallocate ( resolve, & t, Deallocate :: Lists ) )
787
791
. unwrap_or ( false )
788
792
}
789
793
790
- fn needs_post_return ( resolve : & Resolve , ty : & Type ) -> bool {
794
+ fn needs_deallocate ( resolve : & Resolve , ty : & Type , what : Deallocate ) -> bool {
791
795
match ty {
792
796
Type :: String => true ,
793
797
Type :: ErrorContext => true ,
794
798
Type :: Id ( id) => match & resolve. types [ * id] . kind {
795
799
TypeDefKind :: List ( _) => true ,
796
- TypeDefKind :: Type ( t) => needs_post_return ( resolve, t) ,
797
- TypeDefKind :: Handle ( _) => false ,
800
+ TypeDefKind :: Type ( t) => needs_deallocate ( resolve, t, what) ,
801
+ TypeDefKind :: Handle ( Handle :: Own ( _) ) => what. handles ( ) ,
802
+ TypeDefKind :: Handle ( Handle :: Borrow ( _) ) => false ,
798
803
TypeDefKind :: Resource => false ,
799
- TypeDefKind :: Record ( r) => r. fields . iter ( ) . any ( |f| needs_post_return ( resolve, & f. ty ) ) ,
800
- TypeDefKind :: Tuple ( t) => t. types . iter ( ) . any ( |t| needs_post_return ( resolve, t) ) ,
804
+ TypeDefKind :: Record ( r) => r
805
+ . fields
806
+ . iter ( )
807
+ . any ( |f| needs_deallocate ( resolve, & f. ty , what) ) ,
808
+ TypeDefKind :: Tuple ( t) => t. types . iter ( ) . any ( |t| needs_deallocate ( resolve, t, what) ) ,
801
809
TypeDefKind :: Variant ( t) => t
802
810
. cases
803
811
. iter ( )
804
812
. filter_map ( |t| t. ty . as_ref ( ) )
805
- . any ( |t| needs_post_return ( resolve, t) ) ,
806
- TypeDefKind :: Option ( t) => needs_post_return ( resolve, t) ,
813
+ . any ( |t| needs_deallocate ( resolve, t, what ) ) ,
814
+ TypeDefKind :: Option ( t) => needs_deallocate ( resolve, t, what ) ,
807
815
TypeDefKind :: Result ( t) => [ & t. ok , & t. err ]
808
816
. iter ( )
809
817
. filter_map ( |t| t. as_ref ( ) )
810
- . any ( |t| needs_post_return ( resolve, t) ) ,
818
+ . any ( |t| needs_deallocate ( resolve, t, what ) ) ,
811
819
TypeDefKind :: Flags ( _) | TypeDefKind :: Enum ( _) => false ,
812
- TypeDefKind :: Future ( _) | TypeDefKind :: Stream ( _) => false ,
820
+ TypeDefKind :: Future ( _) | TypeDefKind :: Stream ( _) => what . handles ( ) ,
813
821
TypeDefKind :: Unknown => unreachable ! ( ) ,
814
822
} ,
815
823
@@ -836,7 +844,18 @@ pub fn deallocate_lists_in_types<B: Bindgen>(
836
844
ptr : B :: Operand ,
837
845
bindgen : & mut B ,
838
846
) {
839
- Generator :: new ( resolve, bindgen) . deallocate_lists_in_types ( types, ptr) ;
847
+ Generator :: new ( resolve, bindgen) . deallocate_in_types ( types, ptr, Deallocate :: Lists ) ;
848
+ }
849
+
850
+ /// Generate instructions in `bindgen` to deallocate all lists in `ptr` where
851
+ /// that's a pointer to a sequence of `types` stored in linear memory.
852
+ pub fn deallocate_lists_and_own_in_types < B : Bindgen > (
853
+ resolve : & Resolve ,
854
+ types : & [ Type ] ,
855
+ ptr : B :: Operand ,
856
+ bindgen : & mut B ,
857
+ ) {
858
+ Generator :: new ( resolve, bindgen) . deallocate_in_types ( types, ptr, Deallocate :: ListsAndOwn ) ;
840
859
}
841
860
842
861
#[ derive( Copy , Clone ) ]
@@ -845,6 +864,25 @@ pub enum Realloc {
845
864
Export ( & ' static str ) ,
846
865
}
847
866
867
+ /// What to deallocate in various `deallocate_*` methods.
868
+ #[ derive( Copy , Clone ) ]
869
+ enum Deallocate {
870
+ /// Only deallocate lists.
871
+ Lists ,
872
+ /// Deallocate lists and owned resources such as `own<T>` and
873
+ /// futures/streams.
874
+ ListsAndOwn ,
875
+ }
876
+
877
+ impl Deallocate {
878
+ fn handles ( & self ) -> bool {
879
+ match self {
880
+ Deallocate :: Lists => false ,
881
+ Deallocate :: ListsAndOwn => true ,
882
+ }
883
+ }
884
+ }
885
+
848
886
struct Generator < ' a , B : Bindgen > {
849
887
bindgen : & ' a mut B ,
850
888
resolve : & ' a Resolve ,
@@ -1166,14 +1204,14 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1166
1204
1167
1205
let mut types = Vec :: new ( ) ;
1168
1206
types. extend ( func. result ) ;
1169
- self . deallocate_lists_in_types ( & types, addr) ;
1207
+ self . deallocate_in_types ( & types, addr, Deallocate :: Lists ) ;
1170
1208
1171
1209
self . emit ( & Instruction :: Return { func, amt : 0 } ) ;
1172
1210
}
1173
1211
1174
- fn deallocate_lists_in_types ( & mut self , types : & [ Type ] , addr : B :: Operand ) {
1212
+ fn deallocate_in_types ( & mut self , types : & [ Type ] , addr : B :: Operand , what : Deallocate ) {
1175
1213
for ( offset, ty) in self . bindgen . sizes ( ) . field_offsets ( types) {
1176
- self . deallocate ( ty, addr. clone ( ) , offset) ;
1214
+ self . deallocate ( ty, addr. clone ( ) , offset, what ) ;
1177
1215
}
1178
1216
1179
1217
assert ! (
@@ -1973,12 +2011,18 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1973
2011
} ) ;
1974
2012
}
1975
2013
1976
- fn deallocate ( & mut self , ty : & Type , addr : B :: Operand , offset : ArchitectureSize ) {
2014
+ fn deallocate (
2015
+ & mut self ,
2016
+ ty : & Type ,
2017
+ addr : B :: Operand ,
2018
+ offset : ArchitectureSize ,
2019
+ what : Deallocate ,
2020
+ ) {
1977
2021
use Instruction :: * ;
1978
2022
1979
2023
// No need to execute any instructions if this type itself doesn't
1980
2024
// require any form of post-return.
1981
- if !needs_post_return ( self . resolve , ty) {
2025
+ if !needs_deallocate ( self . resolve , ty, what ) {
1982
2026
return ;
1983
2027
}
1984
2028
@@ -2008,7 +2052,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
2008
2052
| Type :: ErrorContext => { }
2009
2053
2010
2054
Type :: Id ( id) => match & self . resolve . types [ id] . kind {
2011
- TypeDefKind :: Type ( t) => self . deallocate ( t, addr, offset) ,
2055
+ TypeDefKind :: Type ( t) => self . deallocate ( t, addr, offset, what ) ,
2012
2056
2013
2057
TypeDefKind :: List ( element) => {
2014
2058
self . stack . push ( addr. clone ( ) ) ;
@@ -2021,30 +2065,36 @@ impl<'a, B: Bindgen> Generator<'a, B> {
2021
2065
self . push_block ( ) ;
2022
2066
self . emit ( & IterBasePointer ) ;
2023
2067
let elemaddr = self . stack . pop ( ) . unwrap ( ) ;
2024
- self . deallocate ( element, elemaddr, Default :: default ( ) ) ;
2068
+ self . deallocate ( element, elemaddr, Default :: default ( ) , what ) ;
2025
2069
self . finish_block ( 0 ) ;
2026
2070
2027
2071
self . emit ( & Instruction :: GuestDeallocateList { element } ) ;
2028
2072
}
2029
2073
2030
- TypeDefKind :: Handle ( _) => {
2031
- todo ! ( )
2074
+ TypeDefKind :: Handle ( Handle :: Own ( _) )
2075
+ | TypeDefKind :: Future ( _)
2076
+ | TypeDefKind :: Stream ( _)
2077
+ if what. handles ( ) =>
2078
+ {
2079
+ self . read_from_memory ( ty, addr, offset) ;
2080
+ self . emit ( & DropHandle { ty } ) ;
2032
2081
}
2033
2082
2034
- TypeDefKind :: Resource => {
2035
- todo ! ( )
2036
- }
2083
+ TypeDefKind :: Handle ( Handle :: Own ( _ ) ) => unreachable ! ( ) ,
2084
+ TypeDefKind :: Handle ( Handle :: Borrow ( _ ) ) => unreachable ! ( ) ,
2085
+ TypeDefKind :: Resource => unreachable ! ( ) ,
2037
2086
2038
2087
TypeDefKind :: Record ( record) => {
2039
2088
self . deallocate_fields (
2040
2089
& record. fields . iter ( ) . map ( |f| f. ty ) . collect :: < Vec < _ > > ( ) ,
2041
2090
addr,
2042
2091
offset,
2092
+ what,
2043
2093
) ;
2044
2094
}
2045
2095
2046
2096
TypeDefKind :: Tuple ( tuple) => {
2047
- self . deallocate_fields ( & tuple. types , addr, offset) ;
2097
+ self . deallocate_fields ( & tuple. types , addr, offset, what ) ;
2048
2098
}
2049
2099
2050
2100
TypeDefKind :: Flags ( _) => { }
@@ -2055,26 +2105,33 @@ impl<'a, B: Bindgen> Generator<'a, B> {
2055
2105
addr,
2056
2106
variant. tag ( ) ,
2057
2107
variant. cases . iter ( ) . map ( |c| c. ty . as_ref ( ) ) ,
2108
+ what,
2058
2109
) ;
2059
2110
self . emit ( & GuestDeallocateVariant {
2060
2111
blocks : variant. cases . len ( ) ,
2061
2112
} ) ;
2062
2113
}
2063
2114
2064
2115
TypeDefKind :: Option ( t) => {
2065
- self . deallocate_variant ( offset, addr, Int :: U8 , [ None , Some ( t) ] ) ;
2116
+ self . deallocate_variant ( offset, addr, Int :: U8 , [ None , Some ( t) ] , what ) ;
2066
2117
self . emit ( & GuestDeallocateVariant { blocks : 2 } ) ;
2067
2118
}
2068
2119
2069
2120
TypeDefKind :: Result ( e) => {
2070
- self . deallocate_variant ( offset, addr, Int :: U8 , [ e. ok . as_ref ( ) , e. err . as_ref ( ) ] ) ;
2121
+ self . deallocate_variant (
2122
+ offset,
2123
+ addr,
2124
+ Int :: U8 ,
2125
+ [ e. ok . as_ref ( ) , e. err . as_ref ( ) ] ,
2126
+ what,
2127
+ ) ;
2071
2128
self . emit ( & GuestDeallocateVariant { blocks : 2 } ) ;
2072
2129
}
2073
2130
2074
2131
TypeDefKind :: Enum ( _) => { }
2075
2132
2076
- TypeDefKind :: Future ( _) => todo ! ( "read future from memory" ) ,
2077
- TypeDefKind :: Stream ( _) => todo ! ( "read stream from memory" ) ,
2133
+ TypeDefKind :: Future ( _) => unreachable ! ( ) ,
2134
+ TypeDefKind :: Stream ( _) => unreachable ! ( ) ,
2078
2135
TypeDefKind :: Unknown => unreachable ! ( ) ,
2079
2136
} ,
2080
2137
}
@@ -2086,22 +2143,29 @@ impl<'a, B: Bindgen> Generator<'a, B> {
2086
2143
addr : B :: Operand ,
2087
2144
tag : Int ,
2088
2145
cases : impl IntoIterator < Item = Option < & ' b Type > > + Clone ,
2146
+ what : Deallocate ,
2089
2147
) {
2090
2148
self . stack . push ( addr. clone ( ) ) ;
2091
2149
self . load_intrepr ( offset, tag) ;
2092
2150
let payload_offset = offset + ( self . bindgen . sizes ( ) . payload_offset ( tag, cases. clone ( ) ) ) ;
2093
2151
for ty in cases {
2094
2152
self . push_block ( ) ;
2095
2153
if let Some ( ty) = ty {
2096
- self . deallocate ( ty, addr. clone ( ) , payload_offset) ;
2154
+ self . deallocate ( ty, addr. clone ( ) , payload_offset, what ) ;
2097
2155
}
2098
2156
self . finish_block ( 0 ) ;
2099
2157
}
2100
2158
}
2101
2159
2102
- fn deallocate_fields ( & mut self , tys : & [ Type ] , addr : B :: Operand , offset : ArchitectureSize ) {
2160
+ fn deallocate_fields (
2161
+ & mut self ,
2162
+ tys : & [ Type ] ,
2163
+ addr : B :: Operand ,
2164
+ offset : ArchitectureSize ,
2165
+ what : Deallocate ,
2166
+ ) {
2103
2167
for ( field_offset, ty) in self . bindgen . sizes ( ) . field_offsets ( tys) {
2104
- self . deallocate ( ty, addr. clone ( ) , offset + ( field_offset) ) ;
2168
+ self . deallocate ( ty, addr. clone ( ) , offset + ( field_offset) , what ) ;
2105
2169
}
2106
2170
}
2107
2171
}
0 commit comments