-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow multiple instances of WasmInterpreter to have imported functions (
#14) This commit fixes a bug in which deinitializing an instance of `WasmInterpreter` would remove all cached implementations for functions imported by any `WasmInterpreter` instance, not just the one being deinitialized. Now, we generate a unique identifier for each instance of `WasmInterpreter`, and we use that identifier as the key to its cached imported functions. This pull request also increases to 10 the maximum number of Wasm functions that can share the same implementation in the same module. Previously, the limit was 3.
- Loading branch information
Showing
7 changed files
with
147 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import Foundation | ||
import Synchronized | ||
import CWasm3 | ||
|
||
// MARK: - Managing imported functions | ||
|
||
func setImportedFunction( | ||
_ function: @escaping ImportedFunctionSignature, | ||
for context: UnsafeMutableRawPointer, | ||
instanceIdentifier id: UInt64 | ||
) { | ||
lock.locked { | ||
if var functionsForID = importedFunctionCache[id] { | ||
functionsForID[context] = function | ||
importedFunctionCache[id] = functionsForID | ||
} else { | ||
let functionsForID = [context: function] | ||
importedFunctionCache[id] = functionsForID | ||
} | ||
} | ||
} | ||
|
||
func removeImportedFunction( | ||
for context: UnsafeMutableRawPointer, | ||
instanceIdentifier id: UInt64 | ||
) { | ||
lock.locked { | ||
guard var functionsForID = importedFunctionCache[id] else { return } | ||
functionsForID.removeValue(forKey: context) | ||
importedFunctionCache[id] = functionsForID | ||
} | ||
} | ||
|
||
func removeImportedFunctions(forInstanceIdentifier id: UInt64) { | ||
lock.locked { | ||
_ = importedFunctionCache.removeValue(forKey: id) | ||
} | ||
} | ||
|
||
func importedFunction( | ||
for userData: UnsafeMutableRawPointer?, | ||
instanceIdentifier id: UInt64 | ||
) -> ImportedFunctionSignature? { | ||
guard let context = userData else { return nil } | ||
return lock.locked { importedFunctionCache[id]?[context] } | ||
} | ||
|
||
func handleImportedFunction( | ||
_ runtime: UnsafeMutablePointer<M3Runtime>?, | ||
_ context: UnsafeMutablePointer<M3ImportContext>?, | ||
_ stackPointer: UnsafeMutablePointer<UInt64>?, | ||
_ heap: UnsafeMutableRawPointer? | ||
) -> UnsafeRawPointer? { | ||
guard let id = m3_GetUserData(runtime)?.load(as: UInt64.self) | ||
else { return UnsafeRawPointer(m3Err_trapUnreachable) } | ||
|
||
guard let userData = context?.pointee.userdata | ||
else { return UnsafeRawPointer(m3Err_trapUnreachable) } | ||
|
||
guard let function = importedFunction(for: userData, instanceIdentifier: id) | ||
else { return UnsafeRawPointer(m3Err_trapUnreachable) } | ||
|
||
return function(stackPointer, heap) | ||
} | ||
|
||
// MARK: - Generating instance identifiers | ||
|
||
var nextInstanceIdentifier: UInt64 { | ||
lock.locked { | ||
lastInstanceIdentifier += 1 | ||
return lastInstanceIdentifier | ||
} | ||
} | ||
|
||
func makeRawPointer(for id: UInt64) -> UnsafeMutableRawPointer { | ||
let ptr = UnsafeMutableRawPointer.allocate( | ||
byteCount: MemoryLayout<UInt64>.size, | ||
alignment: MemoryLayout<UInt64>.alignment | ||
) | ||
ptr.storeBytes(of: id, as: UInt64.self) | ||
return ptr | ||
} | ||
|
||
// MARK: - Private | ||
|
||
private let lock = Lock() | ||
private var lastInstanceIdentifier: UInt64 = 0 | ||
private var importedFunctionCache = [UInt64: [UnsafeMutableRawPointer: ImportedFunctionSignature]]() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters