Skip to content

Commit a0cd63c

Browse files
committed
Make InstructionTranslator non-copyable
This avoids unintentional possible ARC traffic if `InstructionTranslator` is accidentally copied, as it stores references to classes like `ISeqAllocator`.
1 parent 5adf1c6 commit a0cd63c

File tree

5 files changed

+24
-25
lines changed

5 files changed

+24
-25
lines changed

Sources/WasmKit/Execution/Function.swift

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -253,19 +253,18 @@ struct WasmFunctionEntity {
253253
let store = store.value
254254
let engine = store.engine
255255
let type = self.type
256-
var translator = try InstructionTranslator(
257-
allocator: store.allocator.iseqAllocator,
258-
engineConfiguration: engine.configuration,
259-
funcTypeInterner: engine.funcTypeInterner,
260-
module: instance,
261-
type: engine.resolveType(type),
262-
locals: code.locals,
263-
functionIndex: index,
264-
codeSize: code.expression.count,
265-
isIntercepting: engine.interceptor != nil
266-
)
267256
let iseq = try code.withValue { code in
268-
try translator.translate(code: code)
257+
try InstructionTranslator(
258+
allocator: store.allocator.iseqAllocator,
259+
engineConfiguration: engine.configuration,
260+
funcTypeInterner: engine.funcTypeInterner,
261+
module: instance,
262+
type: engine.resolveType(type),
263+
locals: code.locals,
264+
functionIndex: index,
265+
codeSize: code.expression.count,
266+
isIntercepting: engine.interceptor != nil
267+
).translate(code: code)
269268
}
270269
self.code = .compiled(iseq)
271270
return iseq

Sources/WasmKit/Translator.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ struct StackLayout {
293293
}
294294
}
295295

296-
struct InstructionTranslator: InstructionVisitor {
296+
struct InstructionTranslator: ~Copyable, InstructionVisitor {
297297
typealias Output = Void
298298

299299
typealias LabelRef = Int
@@ -526,15 +526,15 @@ struct InstructionTranslator: InstructionVisitor {
526526
}
527527
}
528528

529-
fileprivate struct ISeqBuilder {
529+
fileprivate struct ISeqBuilder: ~Copyable {
530530
typealias InstructionFactoryWithLabel = (
531-
ISeqBuilder,
531+
borrowing ISeqBuilder,
532532
// The position of the next slot of the creating instruction
533533
_ source: MetaProgramCounter,
534534
// The position of the resolved label
535535
_ target: MetaProgramCounter
536536
) -> (WasmKit.Instruction)
537-
typealias BrTableEntryFactory = (ISeqBuilder, MetaProgramCounter) -> Instruction.BrTableOperand.Entry
537+
typealias BrTableEntryFactory = (borrowing ISeqBuilder, MetaProgramCounter) -> Instruction.BrTableOperand.Entry
538538
typealias BuildingBrTable = UnsafeMutableBufferPointer<Instruction.BrTableOperand.Entry>
539539

540540
enum OnPinAction {
@@ -639,7 +639,7 @@ struct InstructionTranslator: InstructionVisitor {
639639
}
640640
}
641641

642-
func finalize() -> [UInt64] {
642+
consuming func finalize() -> [UInt64] {
643643
return instructions
644644
}
645645

@@ -707,7 +707,7 @@ struct InstructionTranslator: InstructionVisitor {
707707
line: UInt = #line,
708708
make:
709709
@escaping (
710-
ISeqBuilder,
710+
borrowing ISeqBuilder,
711711
// The position of the next slot of the creating instruction
712712
_ source: MetaProgramCounter,
713713
// The position of the resolved label
@@ -1077,7 +1077,7 @@ struct InstructionTranslator: InstructionVisitor {
10771077
try valueStack.truncate(height: currentFrame.stackHeight)
10781078
}
10791079

1080-
private mutating func finalize() throws -> InstructionSequence {
1080+
private consuming func finalize() throws -> InstructionSequence {
10811081
if controlStack.numberOfFrames > 1 {
10821082
throw ValidationError(.expectedMoreEndInstructions(count: controlStack.numberOfFrames - 1))
10831083
}
@@ -1102,7 +1102,7 @@ struct InstructionTranslator: InstructionVisitor {
11021102
// MARK: Main entry point
11031103

11041104
/// Translate a Wasm expression into a sequence of instructions.
1105-
mutating func translate(code: Code) throws -> InstructionSequence {
1105+
consuming func translate(code: Code) throws -> InstructionSequence {
11061106
if isIntercepting {
11071107
// Emit `onEnter` instruction at the beginning of the function
11081108
emit(.onEnter(functionIndex))

Sources/WasmParser/BinaryInstructionDecoder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ protocol BinaryInstructionDecoder {
9090
}
9191

9292
@inlinable
93-
func parseBinaryInstruction(visitor: inout some InstructionVisitor, decoder: inout some BinaryInstructionDecoder) throws -> Bool {
93+
func parseBinaryInstruction(visitor: inout some InstructionVisitor & ~Copyable, decoder: inout some BinaryInstructionDecoder) throws -> Bool {
9494
let opcode0 = try decoder.claimNextByte()
9595
switch opcode0 {
9696
case 0x00:

Sources/WasmParser/InstructionVisitor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ extension AnyInstructionVisitor {
309309
///
310310
/// The visitor pattern is used while parsing WebAssembly expressions to allow for easy extensibility.
311311
/// See the expression parsing method ``Code/parseExpression(visitor:)``
312-
public protocol InstructionVisitor {
312+
public protocol InstructionVisitor: ~Copyable {
313313
/// Visiting `unreachable` instruction.
314314
mutating func visitUnreachable() throws
315315
/// Visiting `nop` instruction.
@@ -482,7 +482,7 @@ extension InstructionVisitor {
482482
}
483483

484484
// MARK: - Placeholder implementations
485-
extension InstructionVisitor {
485+
extension InstructionVisitor where Self: ~Copyable {
486486
public mutating func visitUnreachable() throws {}
487487
public mutating func visitNop() throws {}
488488
public mutating func visitBlock(blockType: BlockType) throws {}

Sources/WasmParser/WasmParser.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public struct ExpressionParser {
160160
}
161161

162162
@inlinable
163-
public mutating func visit<V: InstructionVisitor>(visitor: inout V) throws -> Bool {
163+
public mutating func visit(visitor: inout some InstructionVisitor & ~Copyable) throws -> Bool {
164164
isLastEnd = try parser.parseInstruction(visitor: &visitor)
165165
let shouldContinue = try !parser.stream.hasReachedEnd()
166166
if !shouldContinue {
@@ -751,7 +751,7 @@ extension Parser: BinaryInstructionDecoder {
751751
/// Returns: `true` if the parsed instruction is the block end instruction.
752752
@inline(__always)
753753
@inlinable
754-
mutating func parseInstruction<V: InstructionVisitor>(visitor v: inout V) throws -> Bool {
754+
mutating func parseInstruction(visitor v: inout some InstructionVisitor & ~Copyable) throws -> Bool {
755755
return try parseBinaryInstruction(visitor: &v, decoder: &self)
756756
}
757757

0 commit comments

Comments
 (0)