@@ -39,7 +39,39 @@ struct Execution {
39
39
/// Gets the current instance from the stack pointer.
40
40
@inline ( __always)
41
41
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)
43
75
}
44
76
45
77
/// Pushes a new call frame to the VM stack.
@@ -63,20 +95,20 @@ struct Execution {
63
95
$0. initialize ( from: constants, count: count)
64
96
}
65
97
}
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
69
101
return newSp
70
102
}
71
103
72
104
/// Pops the current frame from the VM stack.
73
105
@inline ( __always)
74
106
mutating func popFrame( sp: inout Sp , pc: inout Pc , md: inout Md , ms: inout Ms ) {
75
107
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
80
112
CurrentMemory . mayUpdateCurrentInstance ( instance: toInstance, from: fromInstance, md: & md, ms: & ms)
81
113
}
82
114
}
@@ -187,6 +219,26 @@ extension Sp {
187
219
get { return Float64 ( bitPattern: read ( index) ) }
188
220
nonmutating set { write ( index, . f64( newValue) ) }
189
221
}
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
+ }
190
242
}
191
243
192
244
extension Pc {
@@ -226,6 +278,7 @@ func executeWasm(
226
278
// Advance the stack pointer to be able to reference negative indices
227
279
// for saving slots.
228
280
let sp = sp. advanced ( by: FrameHeaderLayout . numberOfSavingSlots)
281
+ sp. previousSP = nil // Mark root stack pointer as nil.
229
282
for (index, argument) in arguments. enumerated ( ) {
230
283
sp [ VReg ( index) ] = UntypedValue ( argument)
231
284
}
0 commit comments