@@ -551,6 +551,10 @@ def_instruction! {
551551 blocks: usize ,
552552 } : [ 1 ] => [ 0 ] ,
553553
554+ /// Deallocates the language-specific handle representation on the top
555+ /// of the stack. Used for async imports.
556+ DropHandle { ty: & ' a Type } : [ 1 ] => [ 0 ] ,
557+
554558 /// Generate code to run after `CallInterface` for an async-lifted export.
555559 ///
556560 /// For example, this might include task management for the
@@ -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 ,
@@ -1169,14 +1207,14 @@ impl<'a, B: Bindgen> Generator<'a, B> {
11691207
11701208 let mut types = Vec :: new ( ) ;
11711209 types. extend ( func. result ) ;
1172- self . deallocate_lists_in_types ( & types, addr) ;
1210+ self . deallocate_in_types ( & types, addr, Deallocate :: Lists ) ;
11731211
11741212 self . emit ( & Instruction :: Return { func, amt : 0 } ) ;
11751213 }
11761214
1177- fn deallocate_lists_in_types ( & mut self , types : & [ Type ] , addr : B :: Operand ) {
1215+ fn deallocate_in_types ( & mut self , types : & [ Type ] , addr : B :: Operand , what : Deallocate ) {
11781216 for ( offset, ty) in self . bindgen . sizes ( ) . field_offsets ( types) {
1179- self . deallocate ( ty, addr. clone ( ) , offset) ;
1217+ self . deallocate ( ty, addr. clone ( ) , offset, what ) ;
11801218 }
11811219
11821220 assert ! (
@@ -1976,12 +2014,18 @@ impl<'a, B: Bindgen> Generator<'a, B> {
19762014 } ) ;
19772015 }
19782016
1979- fn deallocate ( & mut self , ty : & Type , addr : B :: Operand , offset : ArchitectureSize ) {
2017+ fn deallocate (
2018+ & mut self ,
2019+ ty : & Type ,
2020+ addr : B :: Operand ,
2021+ offset : ArchitectureSize ,
2022+ what : Deallocate ,
2023+ ) {
19802024 use Instruction :: * ;
19812025
19822026 // No need to execute any instructions if this type itself doesn't
19832027 // require any form of post-return.
1984- if !needs_post_return ( self . resolve , ty) {
2028+ if !needs_deallocate ( self . resolve , ty, what ) {
19852029 return ;
19862030 }
19872031
@@ -2011,7 +2055,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
20112055 | Type :: ErrorContext => { }
20122056
20132057 Type :: Id ( id) => match & self . resolve . types [ id] . kind {
2014- TypeDefKind :: Type ( t) => self . deallocate ( t, addr, offset) ,
2058+ TypeDefKind :: Type ( t) => self . deallocate ( t, addr, offset, what ) ,
20152059
20162060 TypeDefKind :: List ( element) => {
20172061 self . stack . push ( addr. clone ( ) ) ;
@@ -2024,30 +2068,36 @@ impl<'a, B: Bindgen> Generator<'a, B> {
20242068 self . push_block ( ) ;
20252069 self . emit ( & IterBasePointer ) ;
20262070 let elemaddr = self . stack . pop ( ) . unwrap ( ) ;
2027- self . deallocate ( element, elemaddr, Default :: default ( ) ) ;
2071+ self . deallocate ( element, elemaddr, Default :: default ( ) , what ) ;
20282072 self . finish_block ( 0 ) ;
20292073
20302074 self . emit ( & Instruction :: GuestDeallocateList { element } ) ;
20312075 }
20322076
2033- TypeDefKind :: Handle ( _) => {
2034- todo ! ( )
2077+ TypeDefKind :: Handle ( Handle :: Own ( _) )
2078+ | TypeDefKind :: Future ( _)
2079+ | TypeDefKind :: Stream ( _)
2080+ if what. handles ( ) =>
2081+ {
2082+ self . read_from_memory ( ty, addr, offset) ;
2083+ self . emit ( & DropHandle { ty } ) ;
20352084 }
20362085
2037- TypeDefKind :: Resource => {
2038- todo ! ( )
2039- }
2086+ TypeDefKind :: Handle ( Handle :: Own ( _ ) ) => unreachable ! ( ) ,
2087+ TypeDefKind :: Handle ( Handle :: Borrow ( _ ) ) => unreachable ! ( ) ,
2088+ TypeDefKind :: Resource => unreachable ! ( ) ,
20402089
20412090 TypeDefKind :: Record ( record) => {
20422091 self . deallocate_fields (
20432092 & record. fields . iter ( ) . map ( |f| f. ty ) . collect :: < Vec < _ > > ( ) ,
20442093 addr,
20452094 offset,
2095+ what,
20462096 ) ;
20472097 }
20482098
20492099 TypeDefKind :: Tuple ( tuple) => {
2050- self . deallocate_fields ( & tuple. types , addr, offset) ;
2100+ self . deallocate_fields ( & tuple. types , addr, offset, what ) ;
20512101 }
20522102
20532103 TypeDefKind :: Flags ( _) => { }
@@ -2058,26 +2108,33 @@ impl<'a, B: Bindgen> Generator<'a, B> {
20582108 addr,
20592109 variant. tag ( ) ,
20602110 variant. cases . iter ( ) . map ( |c| c. ty . as_ref ( ) ) ,
2111+ what,
20612112 ) ;
20622113 self . emit ( & GuestDeallocateVariant {
20632114 blocks : variant. cases . len ( ) ,
20642115 } ) ;
20652116 }
20662117
20672118 TypeDefKind :: Option ( t) => {
2068- self . deallocate_variant ( offset, addr, Int :: U8 , [ None , Some ( t) ] ) ;
2119+ self . deallocate_variant ( offset, addr, Int :: U8 , [ None , Some ( t) ] , what ) ;
20692120 self . emit ( & GuestDeallocateVariant { blocks : 2 } ) ;
20702121 }
20712122
20722123 TypeDefKind :: Result ( e) => {
2073- self . deallocate_variant ( offset, addr, Int :: U8 , [ e. ok . as_ref ( ) , e. err . as_ref ( ) ] ) ;
2124+ self . deallocate_variant (
2125+ offset,
2126+ addr,
2127+ Int :: U8 ,
2128+ [ e. ok . as_ref ( ) , e. err . as_ref ( ) ] ,
2129+ what,
2130+ ) ;
20742131 self . emit ( & GuestDeallocateVariant { blocks : 2 } ) ;
20752132 }
20762133
20772134 TypeDefKind :: Enum ( _) => { }
20782135
2079- TypeDefKind :: Future ( _) => todo ! ( "read future from memory" ) ,
2080- TypeDefKind :: Stream ( _) => todo ! ( "read stream from memory" ) ,
2136+ TypeDefKind :: Future ( _) => unreachable ! ( ) ,
2137+ TypeDefKind :: Stream ( _) => unreachable ! ( ) ,
20812138 TypeDefKind :: Unknown => unreachable ! ( ) ,
20822139 } ,
20832140 }
@@ -2089,22 +2146,29 @@ impl<'a, B: Bindgen> Generator<'a, B> {
20892146 addr : B :: Operand ,
20902147 tag : Int ,
20912148 cases : impl IntoIterator < Item = Option < & ' b Type > > + Clone ,
2149+ what : Deallocate ,
20922150 ) {
20932151 self . stack . push ( addr. clone ( ) ) ;
20942152 self . load_intrepr ( offset, tag) ;
20952153 let payload_offset = offset + ( self . bindgen . sizes ( ) . payload_offset ( tag, cases. clone ( ) ) ) ;
20962154 for ty in cases {
20972155 self . push_block ( ) ;
20982156 if let Some ( ty) = ty {
2099- self . deallocate ( ty, addr. clone ( ) , payload_offset) ;
2157+ self . deallocate ( ty, addr. clone ( ) , payload_offset, what ) ;
21002158 }
21012159 self . finish_block ( 0 ) ;
21022160 }
21032161 }
21042162
2105- fn deallocate_fields ( & mut self , tys : & [ Type ] , addr : B :: Operand , offset : ArchitectureSize ) {
2163+ fn deallocate_fields (
2164+ & mut self ,
2165+ tys : & [ Type ] ,
2166+ addr : B :: Operand ,
2167+ offset : ArchitectureSize ,
2168+ what : Deallocate ,
2169+ ) {
21062170 for ( field_offset, ty) in self . bindgen . sizes ( ) . field_offsets ( tys) {
2107- self . deallocate ( ty, addr. clone ( ) , offset + ( field_offset) ) ;
2171+ self . deallocate ( ty, addr. clone ( ) , offset + ( field_offset) , what ) ;
21082172 }
21092173 }
21102174}
0 commit comments