@@ -39,7 +39,39 @@ struct Execution {
3939 /// Gets the current instance from the stack pointer.
4040 @inline ( __always)
4141 func currentInstance( sp: Sp ) -> InternalInstance {
42- InternalInstance ( bitPattern: UInt ( sp [ - 3 ] . i64) ) . unsafelyUnwrapped
42+ sp. currentInstance. unsafelyUnwrapped
43+ }
44+
45+ /// An iterator for the call frames in the VM stack.
46+ struct FrameIterator : IteratorProtocol {
47+ struct Element {
48+ let pc : Pc
49+ }
50+
51+ /// The stack pointer currently traversed.
52+ private var sp : Sp ?
53+
54+ init ( sp: Sp ) {
55+ self . sp = sp
56+ }
57+
58+ mutating func next( ) -> Element ? {
59+ guard let sp = self . sp else {
60+ // Reached the root frame, whose stack pointer is nil.
61+ return nil
62+ }
63+ let pc = sp. returnPC
64+ self . sp = sp. previousSP
65+ return Element ( pc: pc)
66+ }
67+ }
68+
69+ /// Returns an iterator for the call frames in the VM stack.
70+ ///
71+ /// - Parameter sp: The stack pointer of the current frame.
72+ /// - Returns: An iterator for the call frames in the VM stack.
73+ static func frames( sp: Sp ) -> FrameIterator {
74+ return FrameIterator ( sp: sp)
4375 }
4476
4577 /// Pushes a new call frame to the VM stack.
@@ -63,20 +95,20 @@ struct Execution {
6395 $0. initialize ( from: constants, count: count)
6496 }
6597 }
66- newSp [ - 1 ] = UInt64 ( UInt ( bitPattern : sp ) )
67- newSp [ - 2 ] = UInt64 ( UInt ( bitPattern : returnPC) )
68- newSp [ - 3 ] = UInt64 ( UInt ( bitPattern : instance. bitPattern ) )
98+ newSp. previousSP = sp
99+ newSp. returnPC = returnPC
100+ newSp. currentInstance = instance
69101 return newSp
70102 }
71103
72104 /// Pops the current frame from the VM stack.
73105 @inline ( __always)
74106 mutating func popFrame( sp: inout Sp , pc: inout Pc , md: inout Md , ms: inout Ms ) {
75107 let oldSp = sp
76- sp = Sp ( bitPattern : UInt ( oldSp [ - 1 ] ) ) . unsafelyUnwrapped
77- pc = Pc ( bitPattern : UInt ( oldSp [ - 2 ] ) ) . unsafelyUnwrapped
78- let toInstance = InternalInstance ( bitPattern : UInt ( oldSp [ - 3 ] ) ) . unsafelyUnwrapped
79- let fromInstance = InternalInstance ( bitPattern : UInt ( sp [ - 3 ] ) )
108+ sp = oldSp. previousSP . unsafelyUnwrapped
109+ pc = oldSp. returnPC
110+ let toInstance = oldSp. currentInstance . unsafelyUnwrapped
111+ let fromInstance = sp . currentInstance
80112 CurrentMemory . mayUpdateCurrentInstance ( instance: toInstance, from: fromInstance, md: & md, ms: & ms)
81113 }
82114}
@@ -187,6 +219,26 @@ extension Sp {
187219 get { return Float64 ( bitPattern: read ( index) ) }
188220 nonmutating set { write ( index, . f64( newValue) ) }
189221 }
222+
223+ // MARK: - Special slots
224+
225+ /// The current instance of the execution context.
226+ fileprivate var currentInstance : InternalInstance ? {
227+ get { return InternalInstance ( bitPattern: UInt ( self [ - 3 ] . i64) ) }
228+ nonmutating set { self [ - 3 ] = UInt64 ( UInt ( bitPattern: newValue? . bitPattern ?? 0 ) ) }
229+ }
230+
231+ /// The return program counter of the current frame.
232+ fileprivate var returnPC : Pc {
233+ get { return Pc ( bitPattern: UInt ( self [ - 2 ] ) ) ! }
234+ nonmutating set { self [ - 2 ] = UInt64 ( UInt ( bitPattern: newValue) ) }
235+ }
236+
237+ /// The previous stack pointer of the current frame.
238+ fileprivate var previousSP : Sp ? {
239+ get { return Sp ( bitPattern: UInt ( self [ - 1 ] ) ) }
240+ nonmutating set { self [ - 1 ] = UInt64 ( UInt ( bitPattern: newValue) ) }
241+ }
190242}
191243
192244extension Pc {
@@ -226,6 +278,7 @@ func executeWasm(
226278 // Advance the stack pointer to be able to reference negative indices
227279 // for saving slots.
228280 let sp = sp. advanced ( by: FrameHeaderLayout . numberOfSavingSlots)
281+ sp. previousSP = nil // Mark root stack pointer as nil.
229282 for (index, argument) in arguments. enumerated ( ) {
230283 sp [ VReg ( index) ] = UntypedValue ( argument)
231284 }
0 commit comments