@@ -97,10 +97,10 @@ impl Frame {
97
97
}
98
98
}
99
99
100
- /// Walk through a contiguous sequence of Wasm frames starting with
101
- /// the frame at the given PC and FP and ending at
102
- /// `trampoline_fp`. This FP should correspond to that of a trampoline
103
- /// that was used to enter the Wasm code.
100
+ /// Provide an iterator that walks through a contiguous sequence of
101
+ /// Wasm frames starting with the frame at the given PC and FP and
102
+ /// ending at `trampoline_fp`. This FP should correspond to that of a
103
+ /// trampoline that was used to enter the Wasm code.
104
104
///
105
105
/// We require that the initial PC, FP, and `trampoline_fp` values are
106
106
/// non-null (non-zero).
@@ -112,13 +112,12 @@ impl Frame {
112
112
/// then this method may segfault. These values must point to valid Wasmtime
113
113
/// compiled code which respects the frame pointers that Wasmtime currently
114
114
/// requires.
115
- pub unsafe fn visit_frames < R > (
115
+ pub unsafe fn frame_iterator (
116
116
unwind : & dyn Unwind ,
117
117
mut pc : usize ,
118
118
mut fp : usize ,
119
119
trampoline_fp : usize ,
120
- mut f : impl FnMut ( Frame ) -> ControlFlow < R > ,
121
- ) -> ControlFlow < R > {
120
+ ) -> impl Iterator < Item = Frame > {
122
121
log:: trace!( "=== Tracing through contiguous sequence of Wasm frames ===" ) ;
123
122
log:: trace!( "trampoline_fp = 0x{trampoline_fp:016x}" ) ;
124
123
log:: trace!( " initial pc = 0x{pc:016x}" ) ;
@@ -170,7 +169,12 @@ pub unsafe fn visit_frames<R>(
170
169
// which `return_call`'d an exit trampoline, then `fp ==
171
170
// trampoline_fp` on the entry of this function, meaning the loop
172
171
// won't actually execute anything.
173
- while fp != trampoline_fp {
172
+ core:: iter:: from_fn ( move || {
173
+ if fp == trampoline_fp {
174
+ log:: trace!( "=== Done tracing contiguous sequence of Wasm frames ===" ) ;
175
+ return None ;
176
+ }
177
+
174
178
// At the start of each iteration of the loop, we know that
175
179
// `fp` is a frame pointer from Wasm code. Therefore, we know
176
180
// it is not being used as an extra general-purpose register,
@@ -188,7 +192,7 @@ pub unsafe fn visit_frames<R>(
188
192
log:: trace!( "pc = {:p}" , pc as * const ( ) ) ;
189
193
log:: trace!( "fp = {:p}" , fp as * const ( ) ) ;
190
194
191
- f ( Frame { pc, fp } ) ? ;
195
+ let frame = Frame { pc, fp } ;
192
196
193
197
// SAFETY: this unsafe traversal of the linked list on the stack is
194
198
// reflected in the contract of this function where `pc`, `fp`,
@@ -212,8 +216,37 @@ pub unsafe fn visit_frames<R>(
212
216
assert ! ( next_older_fp > fp, "{next_older_fp:#x} > {fp:#x}" ) ;
213
217
fp = next_older_fp;
214
218
}
219
+
220
+ Some ( frame)
221
+ } )
222
+ }
223
+
224
+ /// Walk through a contiguous sequence of Wasm frames starting with
225
+ /// the frame at the given PC and FP and ending at
226
+ /// `trampoline_fp`. This FP should correspond to that of a trampoline
227
+ /// that was used to enter the Wasm code.
228
+ ///
229
+ /// We require that the initial PC, FP, and `trampoline_fp` values are
230
+ /// non-null (non-zero).
231
+ ///
232
+ /// # Safety
233
+ ///
234
+ /// This function is not safe as `unwind`, `pc`, `fp`, and `trampoline_fp` must
235
+ /// all be "correct" in that if they're wrong or mistakenly have the wrong value
236
+ /// then this method may segfault. These values must point to valid Wasmtime
237
+ /// compiled code which respects the frame pointers that Wasmtime currently
238
+ /// requires.
239
+ pub unsafe fn visit_frames < R > (
240
+ unwind : & dyn Unwind ,
241
+ pc : usize ,
242
+ fp : usize ,
243
+ trampoline_fp : usize ,
244
+ mut f : impl FnMut ( Frame ) -> ControlFlow < R > ,
245
+ ) -> ControlFlow < R > {
246
+ let iter = unsafe { frame_iterator ( unwind, pc, fp, trampoline_fp) } ;
247
+ for frame in iter {
248
+ f ( frame) ?;
215
249
}
216
250
217
- log:: trace!( "=== Done tracing contiguous sequence of Wasm frames ===" ) ;
218
251
ControlFlow :: Continue ( ( ) )
219
252
}
0 commit comments