Skip to content
1 change: 0 additions & 1 deletion Examples/Sources/WASI-Hello/Hello.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import WasmKit
import WasmKitWASI
import WAT
import Foundation

@main
Expand Down
6 changes: 1 addition & 5 deletions Sources/WasmKit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@ add_wasmkit_library(WasmKit
Component/CanonicalCall.swift
Component/CanonicalOptions.swift
Component/ComponentTypes.swift
Execution/Instructions/Reference.swift
Execution/Instructions/Control.swift
Execution/Instructions/Expression.swift
Execution/Instructions/Instruction.swift
Execution/Instructions/Parametric.swift
Execution/Instructions/Table.swift
Execution/Instructions/Memory.swift
Execution/Instructions/Misc.swift
Execution/Instructions/InstructionSupport.swift
Execution/Instructions/Numeric.swift
Execution/Instructions/Variable.swift
Execution/DispatchInstruction.swift
Execution/Errors.swift
Execution/Execution.swift
Expand Down
830 changes: 176 additions & 654 deletions Sources/WasmKit/Execution/DispatchInstruction.swift

Large diffs are not rendered by default.

19 changes: 8 additions & 11 deletions Sources/WasmKit/Execution/Execution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,9 @@ func executeWasm(
}

try withUnsafeTemporaryAllocation(of: CodeSlot.self, capacity: 2) { rootISeq in
switch runtime.value.configuration.threadingModel {
case .direct:
rootISeq[0] = Instruction.endOfExecution.handler
case .token:
rootISeq[0] = UInt64(Instruction.endOfExecution.rawIndex)
}
rootISeq[0] = Instruction.endOfExecution.headSlot(
threadingModel: runtime.value.configuration.threadingModel
)
try stack.execute(
sp: sp,
pc: rootISeq.baseAddress!,
Expand Down Expand Up @@ -381,8 +378,8 @@ extension Execution {
private var buffer = CircularBuffer<UInt64>(capacity: 3)

/// Tracks the given instruction index. This function is called for each instruction execution.
mutating func track(_ rawIndex: UInt64) {
buffer.append(rawIndex)
mutating func track(_ opcode: UInt64) {
buffer.append(opcode)
if let a = buffer[0], let b = buffer[1], let c = buffer[2] {
let trigram = Trigram(a: a, b: b, c: c)
countByTrigram[trigram, default: 0] += 1
Expand All @@ -392,7 +389,7 @@ extension Execution {
func dump<TargetStream: TextOutputStream>(target: inout TargetStream, limit: Int) {
print("Instruction statistics:", to: &target)
for (trigram, count) in countByTrigram.sorted(by: { $0.value > $1.value }).prefix(limit) {
print(" \(Instruction.name(rawIndex: trigram.a)) -> \(Instruction.name(rawIndex: trigram.b)) -> \(Instruction.name(rawIndex: trigram.c)) = \(count)", to: &target)
print(" \(Instruction.name(opcode: trigram.a)) -> \(Instruction.name(opcode: trigram.b)) -> \(Instruction.name(opcode: trigram.c)) = \(count)", to: &target)
}
}

Expand All @@ -412,12 +409,12 @@ extension Execution {
var stats = StatsCollector()
defer { stats.dump() }
#endif
var inst = pc.read(UInt64.self)
var opcode = pc.read(OpcodeID.self)
while true {
#if EngineStats
stats.track(inst)
#endif
inst = try doExecute(inst, sp: &sp, pc: &pc, md: &md, ms: &ms)
opcode = try doExecute(opcode, sp: &sp, pc: &pc, md: &md, ms: &ms)
}
}

Expand Down
22 changes: 22 additions & 0 deletions Sources/WasmKit/Execution/Function.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,28 @@ struct WasmFunctionEntity {

typealias InternalUncompiledCode = EntityHandle<Code>

/// A compiled instruction sequence.
struct InstructionSequence {
let instructions: UnsafeMutableBufferPointer<CodeSlot>
/// The maximum height of the value stack during execution of this function.
/// This height does not count the locals.
let maxStackHeight: Int

/// The constant value pool associated with this instruction sequence.
/// See ``FrameHeaderLayout`` for how they are laid out on the stack.
let constants: UnsafeBufferPointer<UntypedValue>

init(instructions: UnsafeMutableBufferPointer<CodeSlot>, maxStackHeight: Int, constants: UnsafeBufferPointer<UntypedValue>) {
self.instructions = instructions
self.maxStackHeight = maxStackHeight
self.constants = constants
}

var baseAddress: UnsafeMutablePointer<CodeSlot> {
self.instructions.baseAddress!
}
}

enum CodeBody {
case uncompiled(InternalUncompiledCode)
case compiled(InstructionSequence)
Expand Down
9 changes: 2 additions & 7 deletions Sources/WasmKit/Execution/Instructions/Control.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,11 @@ extension Execution {
mutating func compilingCall(sp: inout Sp, pc: Pc, immediate: Instruction.CallOperand) throws -> (Pc, CodeSlot) {
var pc = pc
// NOTE: `CompilingCallOperand` consumes 2 slots, discriminator is at -3
let discriminatorPc = pc.advanced(by: -3)
let headSlotPc = pc.advanced(by: -3)
let callee = immediate.callee
try callee.ensureCompiled(runtime: runtime)
let replaced = Instruction.internalCall(immediate)
switch runtime.value.configuration.threadingModel {
case .direct:
discriminatorPc.pointee = replaced.handler
case .token:
discriminatorPc.pointee = UInt64(replaced.rawIndex)
}
headSlotPc.pointee = replaced.headSlot(threadingModel: runtime.value.configuration.threadingModel)
try _internalCall(sp: &sp, pc: &pc, callee: callee, internalCallOperand: immediate)
return pc.next()
}
Expand Down
47 changes: 0 additions & 47 deletions Sources/WasmKit/Execution/Instructions/Expression.swift

This file was deleted.

17 changes: 9 additions & 8 deletions Sources/WasmKit/Execution/Instructions/Instruction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,8 @@ extension Instruction {


extension Instruction {
var rawIndex: Int {
/// The opcode ID of the instruction.
var opcodeID: OpcodeID {
switch self {
case .copyStack: return 0
case .globalGet: return 1
Expand Down Expand Up @@ -1227,8 +1228,8 @@ extension Instruction {
/// - Returns: The instruction read from the program counter.
/// - Precondition: The instruction sequence must be compiled with token threading model.
static func load(from pc: inout Pc) -> Instruction {
let rawIndex = pc.read(UInt64.self)
switch rawIndex {
let opcode = pc.read(UInt64.self)
switch opcode {
case 0: return .copyStack(Instruction.CopyStackOperand.load(from: &pc))
case 1: return .globalGet(Instruction.GlobalAndVRegOperand.load(from: &pc))
case 2: return .globalSet(Instruction.GlobalAndVRegOperand.load(from: &pc))
Expand Down Expand Up @@ -1425,20 +1426,20 @@ extension Instruction {
case 193: return .tableElementDrop(Instruction.TableElementDropOperand.load(from: &pc))
case 194: return .onEnter(Instruction.OnEnterOperand.load(from: &pc))
case 195: return .onExit(Instruction.OnExitOperand.load(from: &pc))
default: fatalError("Unknown instruction index: \(rawIndex)")
default: fatalError("Unknown instruction opcode: \(opcode)")
}
}
}

#if EngineStats
extension Instruction {
/// The name of the instruction.
/// - Parameter rawIndex: The raw index of the instruction.
/// - Parameter opcode: The opcode ID of the instruction.
/// - Returns: The name of the instruction.
///
/// NOTE: This function is used for debugging purposes.
static func name(rawIndex: UInt64) -> String {
switch rawIndex {
static func name(opcode: OpcodeID) -> String {
switch opcode {
case 0: return "copyStack"
case 1: return "globalGet"
case 2: return "globalSet"
Expand Down Expand Up @@ -1635,7 +1636,7 @@ extension Instruction {
case 193: return "tableElementDrop"
case 194: return "onEnter"
case 195: return "onExit"
default: fatalError("Unknown instruction index: \(rawIndex)")
default: fatalError("Unknown instruction index: \(opcode)")
}
}
}
Expand Down
Loading