@@ -554,6 +554,10 @@ def_instruction! {
554554 blocks: usize ,
555555 } : [ 1 ] => [ 0 ] ,
556556
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+
557561 /// Call `task.return` for an async-lifted export.
558562 ///
559563 /// 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
783787/// a list or a string primarily.
784788pub fn guest_export_needs_post_return ( resolve : & Resolve , func : & Function ) -> bool {
785789 func. result
786- . map ( |t| needs_post_return ( resolve, & t) )
790+ . map ( |t| needs_deallocate ( resolve, & t, Deallocate :: Lists ) )
787791 . unwrap_or ( false )
788792}
789793
790- fn needs_post_return ( resolve : & Resolve , ty : & Type ) -> bool {
794+ fn needs_deallocate ( resolve : & Resolve , ty : & Type , what : Deallocate ) -> bool {
791795 match ty {
792796 Type :: String => true ,
793797 Type :: ErrorContext => true ,
794798 Type :: Id ( id) => match & resolve. types [ * id] . kind {
795799 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 ,
798803 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) ) ,
801809 TypeDefKind :: Variant ( t) => t
802810 . cases
803811 . iter ( )
804812 . 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 ) ,
807815 TypeDefKind :: Result ( t) => [ & t. ok , & t. err ]
808816 . iter ( )
809817 . filter_map ( |t| t. as_ref ( ) )
810- . any ( |t| needs_post_return ( resolve, t) ) ,
818+ . any ( |t| needs_deallocate ( resolve, t, what ) ) ,
811819 TypeDefKind :: Flags ( _) | TypeDefKind :: Enum ( _) => false ,
812- TypeDefKind :: Future ( _) | TypeDefKind :: Stream ( _) => false ,
820+ TypeDefKind :: Future ( _) | TypeDefKind :: Stream ( _) => what . handles ( ) ,
813821 TypeDefKind :: Unknown => unreachable ! ( ) ,
814822 } ,
815823
@@ -836,7 +844,18 @@ pub fn deallocate_lists_in_types<B: Bindgen>(
836844 ptr : B :: Operand ,
837845 bindgen : & mut B ,
838846) {
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 ) ;
840859}
841860
842861#[ derive( Copy , Clone ) ]
@@ -845,6 +864,25 @@ pub enum Realloc {
845864 Export ( & ' static str ) ,
846865}
847866
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+
848886struct Generator < ' a , B : Bindgen > {
849887 bindgen : & ' a mut B ,
850888 resolve : & ' a Resolve ,
@@ -1166,14 +1204,14 @@ impl<'a, B: Bindgen> Generator<'a, B> {
11661204
11671205 let mut types = Vec :: new ( ) ;
11681206 types. extend ( func. result ) ;
1169- self . deallocate_lists_in_types ( & types, addr) ;
1207+ self . deallocate_in_types ( & types, addr, Deallocate :: Lists ) ;
11701208
11711209 self . emit ( & Instruction :: Return { func, amt : 0 } ) ;
11721210 }
11731211
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 ) {
11751213 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 ) ;
11771215 }
11781216
11791217 assert ! (
@@ -1973,12 +2011,18 @@ impl<'a, B: Bindgen> Generator<'a, B> {
19732011 } ) ;
19742012 }
19752013
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+ ) {
19772021 use Instruction :: * ;
19782022
19792023 // No need to execute any instructions if this type itself doesn't
19802024 // require any form of post-return.
1981- if !needs_post_return ( self . resolve , ty) {
2025+ if !needs_deallocate ( self . resolve , ty, what ) {
19822026 return ;
19832027 }
19842028
@@ -2008,7 +2052,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
20082052 | Type :: ErrorContext => { }
20092053
20102054 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 ) ,
20122056
20132057 TypeDefKind :: List ( element) => {
20142058 self . stack . push ( addr. clone ( ) ) ;
@@ -2021,30 +2065,36 @@ impl<'a, B: Bindgen> Generator<'a, B> {
20212065 self . push_block ( ) ;
20222066 self . emit ( & IterBasePointer ) ;
20232067 let elemaddr = self . stack . pop ( ) . unwrap ( ) ;
2024- self . deallocate ( element, elemaddr, Default :: default ( ) ) ;
2068+ self . deallocate ( element, elemaddr, Default :: default ( ) , what ) ;
20252069 self . finish_block ( 0 ) ;
20262070
20272071 self . emit ( & Instruction :: GuestDeallocateList { element } ) ;
20282072 }
20292073
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 } ) ;
20322081 }
20332082
2034- TypeDefKind :: Resource => {
2035- todo ! ( )
2036- }
2083+ TypeDefKind :: Handle ( Handle :: Own ( _ ) ) => unreachable ! ( ) ,
2084+ TypeDefKind :: Handle ( Handle :: Borrow ( _ ) ) => unreachable ! ( ) ,
2085+ TypeDefKind :: Resource => unreachable ! ( ) ,
20372086
20382087 TypeDefKind :: Record ( record) => {
20392088 self . deallocate_fields (
20402089 & record. fields . iter ( ) . map ( |f| f. ty ) . collect :: < Vec < _ > > ( ) ,
20412090 addr,
20422091 offset,
2092+ what,
20432093 ) ;
20442094 }
20452095
20462096 TypeDefKind :: Tuple ( tuple) => {
2047- self . deallocate_fields ( & tuple. types , addr, offset) ;
2097+ self . deallocate_fields ( & tuple. types , addr, offset, what ) ;
20482098 }
20492099
20502100 TypeDefKind :: Flags ( _) => { }
@@ -2055,26 +2105,33 @@ impl<'a, B: Bindgen> Generator<'a, B> {
20552105 addr,
20562106 variant. tag ( ) ,
20572107 variant. cases . iter ( ) . map ( |c| c. ty . as_ref ( ) ) ,
2108+ what,
20582109 ) ;
20592110 self . emit ( & GuestDeallocateVariant {
20602111 blocks : variant. cases . len ( ) ,
20612112 } ) ;
20622113 }
20632114
20642115 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 ) ;
20662117 self . emit ( & GuestDeallocateVariant { blocks : 2 } ) ;
20672118 }
20682119
20692120 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+ ) ;
20712128 self . emit ( & GuestDeallocateVariant { blocks : 2 } ) ;
20722129 }
20732130
20742131 TypeDefKind :: Enum ( _) => { }
20752132
2076- TypeDefKind :: Future ( _) => todo ! ( "read future from memory" ) ,
2077- TypeDefKind :: Stream ( _) => todo ! ( "read stream from memory" ) ,
2133+ TypeDefKind :: Future ( _) => unreachable ! ( ) ,
2134+ TypeDefKind :: Stream ( _) => unreachable ! ( ) ,
20782135 TypeDefKind :: Unknown => unreachable ! ( ) ,
20792136 } ,
20802137 }
@@ -2086,22 +2143,29 @@ impl<'a, B: Bindgen> Generator<'a, B> {
20862143 addr : B :: Operand ,
20872144 tag : Int ,
20882145 cases : impl IntoIterator < Item = Option < & ' b Type > > + Clone ,
2146+ what : Deallocate ,
20892147 ) {
20902148 self . stack . push ( addr. clone ( ) ) ;
20912149 self . load_intrepr ( offset, tag) ;
20922150 let payload_offset = offset + ( self . bindgen . sizes ( ) . payload_offset ( tag, cases. clone ( ) ) ) ;
20932151 for ty in cases {
20942152 self . push_block ( ) ;
20952153 if let Some ( ty) = ty {
2096- self . deallocate ( ty, addr. clone ( ) , payload_offset) ;
2154+ self . deallocate ( ty, addr. clone ( ) , payload_offset, what ) ;
20972155 }
20982156 self . finish_block ( 0 ) ;
20992157 }
21002158 }
21012159
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+ ) {
21032167 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 ) ;
21052169 }
21062170 }
21072171}
0 commit comments