@@ -64,8 +64,14 @@ unsafe impl Sync for EmptyParametersList {}
6464pub ( crate ) enum ExecutionResult {
6565 Return ( Value ) ,
6666 Throw ( JsError ) ,
67- Await { vm : Vm , awaited_value : Value } ,
68- Yield { vm : Vm , yielded_value : Value } ,
67+ Await {
68+ vm : SuspendedVm ,
69+ awaited_value : Value ,
70+ } ,
71+ Yield {
72+ vm : SuspendedVm ,
73+ yielded_value : Value ,
74+ } ,
6975}
7076impl ExecutionResult {
7177 pub ( crate ) fn into_js_result ( self ) -> JsResult < Value > {
@@ -113,6 +119,55 @@ pub(crate) struct Vm {
113119 reference : Option < Reference > ,
114120}
115121
122+ #[ derive( Debug ) ]
123+ pub ( crate ) struct SuspendedVm {
124+ ip : usize ,
125+ /// Note: Stack is non-empty only if the code awaits inside a call
126+ /// expression. This is reasonably rare that we can expect the stack to
127+ /// usually be empty. In this case this Box is an empty dangling pointer
128+ /// and no heap data clone is required.
129+ stack : Box < [ Value ] > ,
130+ /// Note: Reference stack is non-empty only if the code awaits inside a
131+ /// call expression. This means that usually no heap data clone is
132+ /// required.
133+ reference_stack : Box < [ Reference ] > ,
134+ /// Note: Iterator stack is non-empty only if the code awaits inside a
135+ /// for-in or for-of loop. This means that often no heap data clone is
136+ /// required.
137+ iterator_stack : Box < [ VmIterator ] > ,
138+ /// Note: Exception jump stack is non-empty only if the code awaits inside
139+ /// a try block. This means that often no heap data clone is required.
140+ exception_jump_target_stack : Box < [ ExceptionJumpTarget ] > ,
141+ }
142+
143+ impl SuspendedVm {
144+ pub ( crate ) fn resume (
145+ self ,
146+ agent : & mut Agent ,
147+ executable : & Executable ,
148+ value : Value ,
149+ ) -> ExecutionResult {
150+ let vm = Vm :: from_suspended ( self ) ;
151+ vm. resume ( agent, executable, value)
152+ }
153+
154+ pub ( crate ) fn resume_throw (
155+ self ,
156+ agent : & mut Agent ,
157+ executable : & Executable ,
158+ err : Value ,
159+ ) -> ExecutionResult {
160+ // Optimisation: Avoid unsuspending the Vm if we're just going to throw
161+ // out of it immediately.
162+ if self . exception_jump_target_stack . is_empty ( ) {
163+ let err = JsError :: new ( err) ;
164+ return ExecutionResult :: Throw ( err) ;
165+ }
166+ let vm = Vm :: from_suspended ( self ) ;
167+ vm. resume_throw ( agent, executable, err)
168+ }
169+ }
170+
116171impl Vm {
117172 fn new ( ) -> Self {
118173 Self {
@@ -127,6 +182,29 @@ impl Vm {
127182 }
128183 }
129184
185+ fn suspend ( self ) -> SuspendedVm {
186+ SuspendedVm {
187+ ip : self . ip ,
188+ stack : self . stack . into_boxed_slice ( ) ,
189+ reference_stack : self . reference_stack . into_boxed_slice ( ) ,
190+ iterator_stack : self . iterator_stack . into_boxed_slice ( ) ,
191+ exception_jump_target_stack : self . exception_jump_target_stack . into_boxed_slice ( ) ,
192+ }
193+ }
194+
195+ fn from_suspended ( suspended : SuspendedVm ) -> Self {
196+ Self {
197+ ip : suspended. ip ,
198+ stack : suspended. stack . into_vec ( ) ,
199+ reference_stack : suspended. reference_stack . into_vec ( ) ,
200+ iterator_stack : suspended. iterator_stack . into_vec ( ) ,
201+ exception_jump_target_stack : suspended. exception_jump_target_stack . into_vec ( ) ,
202+ result : None ,
203+ exception : None ,
204+ reference : None ,
205+ }
206+ }
207+
130208 fn fetch_identifier ( & self , exe : & Executable , index : usize ) -> String {
131209 String :: try_from ( exe. constants [ index] )
132210 . expect ( "Invalid identifier index: Value was not a String" )
@@ -183,7 +261,7 @@ impl Vm {
183261 vm. inner_execute ( agent, executable)
184262 }
185263
186- pub ( crate ) fn resume (
264+ pub fn resume (
187265 mut self ,
188266 agent : & mut Agent ,
189267 executable : & Executable ,
@@ -193,7 +271,7 @@ impl Vm {
193271 self . inner_execute ( agent, executable)
194272 }
195273
196- pub ( crate ) fn resume_throw (
274+ pub fn resume_throw (
197275 mut self ,
198276 agent : & mut Agent ,
199277 executable : & Executable ,
@@ -217,14 +295,14 @@ impl Vm {
217295 Ok ( ContinuationKind :: Yield ) => {
218296 let yielded_value = self . result . take ( ) . unwrap ( ) ;
219297 return ExecutionResult :: Yield {
220- vm : self ,
298+ vm : self . suspend ( ) ,
221299 yielded_value,
222300 } ;
223301 }
224302 Ok ( ContinuationKind :: Await ) => {
225303 let awaited_value = self . result . take ( ) . unwrap ( ) ;
226304 return ExecutionResult :: Await {
227- vm : self ,
305+ vm : self . suspend ( ) ,
228306 awaited_value,
229307 } ;
230308 }
@@ -2205,30 +2283,18 @@ impl HeapMarkAndSweep for ExceptionJumpTarget {
22052283 }
22062284}
22072285
2208- impl HeapMarkAndSweep for Vm {
2286+ impl HeapMarkAndSweep for SuspendedVm {
22092287 fn mark_values ( & self , queues : & mut WorkQueues ) {
2210- self . stack . as_slice ( ) . mark_values ( queues) ;
2211- self . reference_stack . as_slice ( ) . mark_values ( queues) ;
2212- self . iterator_stack . as_slice ( ) . mark_values ( queues) ;
2213- self . exception_jump_target_stack
2214- . as_slice ( )
2215- . mark_values ( queues) ;
2216- self . result . mark_values ( queues) ;
2217- self . exception . mark_values ( queues) ;
2218- self . reference . mark_values ( queues) ;
2288+ self . stack . mark_values ( queues) ;
2289+ self . reference_stack . mark_values ( queues) ;
2290+ self . iterator_stack . mark_values ( queues) ;
2291+ self . exception_jump_target_stack . mark_values ( queues) ;
22192292 }
22202293
22212294 fn sweep_values ( & mut self , compactions : & CompactionLists ) {
2222- self . stack . as_mut_slice ( ) . sweep_values ( compactions) ;
2223- self . reference_stack
2224- . as_mut_slice ( )
2225- . sweep_values ( compactions) ;
2226- self . iterator_stack . as_mut_slice ( ) . sweep_values ( compactions) ;
2227- self . exception_jump_target_stack
2228- . as_mut_slice ( )
2229- . sweep_values ( compactions) ;
2230- self . result . sweep_values ( compactions) ;
2231- self . exception . sweep_values ( compactions) ;
2232- self . reference . sweep_values ( compactions) ;
2295+ self . stack . sweep_values ( compactions) ;
2296+ self . reference_stack . sweep_values ( compactions) ;
2297+ self . iterator_stack . sweep_values ( compactions) ;
2298+ self . exception_jump_target_stack . sweep_values ( compactions) ;
22332299 }
22342300}
0 commit comments