Skip to content

Commit 8bf6849

Browse files
committed
Allocate and modify Pc directly as Debugger property
1 parent f64bf23 commit 8bf6849

File tree

3 files changed

+78
-17
lines changed

3 files changed

+78
-17
lines changed

Sources/WasmKit/Execution/Debugger.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
case noInstructionMappingAvailable(Int)
4747
}
4848

49-
private let valueStack: Sp
50-
private let execution: Execution
49+
private var valueStack: Sp
50+
private var execution: Execution
5151
private let store: Store
5252

5353
/// Parsed in-memory representation of a Wasm module instantiated for debugging.
@@ -62,7 +62,8 @@
6262
/// Threading model of the Wasm engine configuration cached for a potentially hot path.
6363
private let threadingModel: EngineConfiguration.ThreadingModel
6464

65-
private var breakpoints = [Int: CodeSlot]()
65+
private(set) var breakpoints = [Int: CodeSlot]()
66+
private var pc: Pc
6667

6768
package init(module: Module, store: Store, imports: Imports) throws {
6869
let limit = store.engine.configuration.stackSize / MemoryLayout<StackSlot>.stride
@@ -79,6 +80,13 @@
7980
self.store = store
8081
self.execution = Execution(store: StoreRef(store), stackEnd: valueStack.advanced(by: limit))
8182
self.threadingModel = store.engine.configuration.threadingModel
83+
let endOfExecution = Instruction.endOfExecution.headSlot(
84+
threadingModel: threadingModel
85+
)
86+
// TODO: clarify why `func executeWasm` allocates 2 Pc slots on the native stack
87+
self.pc = Pc.allocate(capacity: 2)
88+
self.pc[0] = endOfExecution
89+
8290
}
8391

8492
package mutating func stopAtEntrypoint() throws {
@@ -121,21 +129,32 @@
121129
iseq.pointee = oldCodeSlot
122130
}
123131

124-
package func run() throws {
125-
try self.entrypointFunction()
132+
package mutating func run() throws {
133+
try self.execution.executeWasm(
134+
threadingModel: self.threadingModel,
135+
function: self.entrypointFunction.handle,
136+
type: self.entrypointFunction.type,
137+
arguments: [],
138+
sp: &self.valueStack,
139+
pc: &self.pc
140+
)
126141
}
127142

128143
/// Array of addresses in the Wasm binary of executed instructions on the call stack.
129144
package var currentCallStack: [Int] {
130145
let isDebuggable = self.instance.handle.isDebuggable
131146

132-
return Execution.captureBacktrace(sp: self.valueStack, store: self.store).symbols.map {
133-
self.instance.handle.iseqToWasmMapping[$0.address]!
147+
print(self.pc)
148+
return Execution.captureBacktrace(sp: self.valueStack, store: self.store).symbols.compactMap {
149+
print(self.instance.handle.iseqToWasmMapping)
150+
print(self.instance.handle.wasmToIseqMapping)
151+
return self.instance.handle.iseqToWasmMapping[$0.address]
134152
}
135153
}
136154

137155
deinit {
138-
valueStack.deallocate()
156+
self.valueStack.deallocate()
157+
self.pc.deallocate()
139158
}
140159
}
141160

Sources/WasmKit/Execution/Execution.swift

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ func executeWasm(
293293
return try Execution.with(store: store) { (stack, sp) in
294294
// Advance the stack pointer to be able to reference negative indices
295295
// for saving slots.
296-
let sp = sp.advanced(by: FrameHeaderLayout.numberOfSavingSlots)
296+
var sp = sp.advanced(by: FrameHeaderLayout.numberOfSavingSlots)
297297
// Mark root stack pointer and current function as nil.
298298
sp.previousSP = nil
299299
sp.currentFunction = nil
@@ -305,9 +305,10 @@ func executeWasm(
305305
rootISeq[0] = Instruction.endOfExecution.headSlot(
306306
threadingModel: store.value.engine.configuration.threadingModel
307307
)
308+
var pc = rootISeq.baseAddress!
308309
try stack.execute(
309-
sp: sp,
310-
pc: rootISeq.baseAddress!,
310+
sp: &sp,
311+
pc: &pc,
311312
handle: handle,
312313
type: type
313314
)
@@ -318,6 +319,46 @@ func executeWasm(
318319
}
319320
}
320321

322+
#if WasmDebuggingSupport
323+
extension Execution {
324+
@inline(never)
325+
mutating func executeWasm(
326+
threadingModel: EngineConfiguration.ThreadingModel,
327+
function handle: InternalFunction,
328+
type: FunctionType,
329+
arguments: [Value],
330+
sp: inout Sp,
331+
pc: inout Pc
332+
) throws -> [Value] {
333+
// Advance the stack pointer to be able to reference negative indices
334+
// for saving slots.
335+
sp = sp.advanced(by: FrameHeaderLayout.numberOfSavingSlots)
336+
// Mark root stack pointer and current function as nil.
337+
sp.previousSP = nil
338+
sp.currentFunction = nil
339+
for (index, argument) in arguments.enumerated() {
340+
sp[VReg(index)] = UntypedValue(argument)
341+
}
342+
343+
try withUnsafeTemporaryAllocation(of: CodeSlot.self, capacity: 2) { rootISeq in
344+
rootISeq[0] = Instruction.endOfExecution.headSlot(
345+
threadingModel: threadingModel
346+
)
347+
pc = rootISeq.baseAddress!
348+
try self.execute(
349+
sp: &sp,
350+
pc: &pc,
351+
handle: handle,
352+
type: type
353+
)
354+
}
355+
return type.results.enumerated().map { (i, type) in
356+
sp[VReg(i)].cast(to: type)
357+
}
358+
}
359+
}
360+
#endif
361+
321362
extension Execution {
322363
/// A namespace for the "current memory" (Md and Ms) management.
323364
enum CurrentMemory {
@@ -373,14 +414,12 @@ extension Execution {
373414
/// The entry point for the execution of the WebAssembly function.
374415
@inline(never)
375416
mutating func execute(
376-
sp: Sp, pc: Pc,
417+
sp: inout Sp, pc: inout Pc,
377418
handle: InternalFunction,
378419
type: FunctionType
379420
) throws {
380-
var sp: Sp = sp
381421
var md: Md = nil
382422
var ms: Ms = 0
383-
var pc = pc
384423
(pc, sp) = try invoke(
385424
function: handle,
386425
callerInstance: nil,
@@ -390,7 +429,7 @@ extension Execution {
390429
do {
391430
switch self.store.value.engine.configuration.threadingModel {
392431
case .direct:
393-
try runDirectThreaded(sp: sp, pc: pc, md: md, ms: ms)
432+
try runDirectThreaded(sp: sp, pc: &pc, md: md, ms: ms)
394433
case .token:
395434
try runTokenThreaded(sp: &sp, pc: &pc, md: &md, ms: &ms)
396435
}
@@ -402,12 +441,11 @@ extension Execution {
402441
/// Starts the main execution loop using the direct threading model.
403442
@inline(never)
404443
mutating func runDirectThreaded(
405-
sp: Sp, pc: Pc, md: Md, ms: Ms
444+
sp: Sp, pc: inout Pc, md: Md, ms: Ms
406445
) throws {
407446
#if os(WASI)
408447
fatalError("Direct threading is not supported on WASI")
409448
#else
410-
var pc = pc
411449
let handler = pc.read(wasmkit_tc_exec.self)
412450
wasmkit_tc_start(handler, sp, pc, md, ms, &self)
413451
if let (rawError, trappingSp) = self.trap {

Tests/WasmKitTests/DebuggerTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
#expect(throws: Execution.Breakpoint.self) {
3232
try debugger.run()
3333
}
34+
35+
let callStack = debugger.currentCallStack
36+
#expect(callStack.count == 1)
37+
#expect(callStack.first == debugger.breakpoints.keys.first)
3438
}
3539

3640
@Test

0 commit comments

Comments
 (0)