Skip to content

Commit 7f40d0e

Browse files
committed
PR feedback
1 parent 89825ad commit 7f40d0e

File tree

9 files changed

+33
-96
lines changed

9 files changed

+33
-96
lines changed

Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,6 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
114114
outputSwiftDirectory.appending(path: "\(sourceModule.name)Module+SwiftJava.swift")
115115
]
116116

117-
// Append any JNI cache files
118-
if configuration?.mode == .jni {
119-
outputSwiftFiles += [
120-
outputSwiftDirectory.appending(path: "\(sourceModule.name)+JNICaches.swift")
121-
]
122-
}
123-
124117
// If the module uses 'Data' type, the thunk file is emitted as if 'Data' is declared
125118
// in that module. Declare the thunk file as the output.
126119
// FIXME: Make this conditional.

Sources/JExtractSwiftLib/JNI/JNICaching.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,19 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
enum JNICaching {
16-
static func cacheName(for enumCase: ImportedEnumCase) -> String {
16+
static func cacheName(for type: ImportedNominalType) -> String {
17+
cacheName(for: type.swiftNominal.name)
18+
}
19+
20+
static func cacheName(for type: SwiftNominalType) -> String {
21+
cacheName(for: type.nominalTypeDecl.name)
22+
}
23+
24+
private static func cacheName(for name: String) -> String {
25+
"_JNI_\(name)"
26+
}
27+
28+
static func cacheMemberName(for enumCase: ImportedEnumCase) -> String {
1729
"\(enumCase.enumType.nominalTypeDecl.name.firstCharacterLowercased)\(enumCase.name.firstCharacterUppercased)Cache"
1830
}
1931
}

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -259,31 +259,14 @@ extension JNISwift2JavaGenerator {
259259

260260
// Print record
261261
printer.printBraceBlock("public record \(caseName)(\(members.joined(separator: ", "))) implements Case") { printer in
262-
printer.printBraceBlock("static class $JNI") { printer in
263-
printer.print("private static native void $nativeInit();")
264-
}
265-
266-
// Used to ensure static initializer has been calling to trigger caching.
267-
printer.print("static void $ensureInitialized() {}")
268-
269-
printer.printBraceBlock("static") { printer in
270-
printer.print("$JNI.$nativeInit();")
271-
}
272-
273262
let nativeParameters = zip(translatedCase.translatedValues, translatedCase.parameterConversions).flatMap { value, conversion in
274263
["\(conversion.native.javaType) \(value.parameter.name)"]
275264
}
276265

277266
printer.print("record $NativeParameters(\(nativeParameters.joined(separator: ", "))) {}")
278267
}
279268

280-
self.printJavaBindingWrapperMethod(
281-
&printer,
282-
translatedCase.getAsCaseFunction,
283-
prefix: { printer in
284-
printer.print("\(caseName).$ensureInitialized();")
285-
}
286-
)
269+
self.printJavaBindingWrapperMethod(&printer, translatedCase.getAsCaseFunction)
287270
printer.println()
288271
}
289272
}
@@ -355,8 +338,7 @@ extension JNISwift2JavaGenerator {
355338
private func printJavaBindingWrapperMethod(
356339
_ printer: inout CodePrinter,
357340
_ translatedDecl: TranslatedFunctionDecl,
358-
importedFunc: ImportedFunc? = nil,
359-
prefix: (inout CodePrinter) -> Void = { _ in }
341+
importedFunc: ImportedFunc? = nil
360342
) {
361343
var modifiers = ["public"]
362344
if translatedDecl.isStatic {
@@ -402,7 +384,6 @@ extension JNISwift2JavaGenerator {
402384
printer.printBraceBlock(
403385
"\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)"
404386
) { printer in
405-
prefix(&printer)
406387
printDowncall(&printer, translatedDecl)
407388
}
408389

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ extension JNISwift2JavaGenerator {
5656
self.expectedOutputSwiftFiles.remove(moduleFilename)
5757
}
5858

59-
try self.writeJNICacheSource(&printer)
60-
6159
for (_, ty) in self.analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) {
6260
let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava"
6361
let filename = "\(fileNameBase).swift"
@@ -82,38 +80,13 @@ extension JNISwift2JavaGenerator {
8280
}
8381
}
8482

85-
private func writeJNICacheSource(_ printer: inout CodePrinter) throws {
86-
printer.print("import JavaKit")
87-
printer.println()
88-
printer.printBraceBlock("enum JNICaches") { printer in
89-
let enumCases = self.analysis.importedTypes.values.filter { $0.swiftNominal.kind == .enum }.flatMap(\.cases)
90-
for enumCase in enumCases {
91-
printer.print("static var \(JNICaching.cacheName(for: enumCase)): _JNICache!")
92-
}
93-
printer.println()
94-
printer.printBraceBlock("static func cleanup()") { printer in
95-
for enumCase in enumCases {
96-
printer.print("JNICaches.\(JNICaching.cacheName(for: enumCase)) = nil")
97-
}
83+
private func printJNICache(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
84+
printer.printBraceBlock("enum \(JNICaching.cacheName(for: type))") { printer in
85+
for enumCase in type.cases {
86+
guard let translatedCase = translatedEnumCase(for: enumCase) else { continue }
87+
printer.print("static let \(JNICaching.cacheMemberName(for: enumCase)) = \(renderEnumCaseCacheInit(translatedCase))")
9888
}
9989
}
100-
101-
printer.println()
102-
printer.print(#"@_cdecl("JNI_OnUnload")"#)
103-
printer.printBraceBlock("func JNI_OnUnload(javaVM: UnsafeMutablePointer<JavaVM?>!, reserved: UnsafeMutableRawPointer!)") { printer in
104-
printer.print("JNICaches.cleanup()")
105-
}
106-
107-
let fileName = "\(self.swiftModuleName)+JNICaches.swift"
108-
109-
if let outputFile = try printer.writeContents(
110-
outputDirectory: self.swiftOutputDirectory,
111-
javaPackagePath: nil,
112-
filename: fileName
113-
) {
114-
print("[swift-java] Generated: \(fileName.bold) (at \(outputFile))")
115-
self.expectedOutputSwiftFiles.remove(fileName)
116-
}
11790
}
11891

11992
private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws {
@@ -133,6 +106,9 @@ extension JNISwift2JavaGenerator {
133106
private func printNominalTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) throws {
134107
printHeader(&printer)
135108

109+
printJNICache(&printer, type)
110+
printer.println()
111+
136112
for initializer in type.initializers {
137113
printSwiftFunctionThunk(&printer, initializer)
138114
printer.println()
@@ -192,30 +168,18 @@ extension JNISwift2JavaGenerator {
192168
printSwiftFunctionThunk(&printer, enumCase.caseFunction)
193169
printer.println()
194170

195-
// Print enum case native init
196-
printEnumNativeInit(&printer, translatedCase)
197-
198171
// Print getAsCase method
199172
if !translatedCase.translatedValues.isEmpty {
200173
printEnumGetAsCaseThunk(&printer, translatedCase)
201174
}
202175
}
203176

204-
private func printEnumNativeInit(_ printer: inout CodePrinter, _ enumCase: TranslatedEnumCase) {
205-
printCDecl(
206-
&printer,
207-
javaMethodName: "$nativeInit",
208-
parentName: "\(enumCase.original.enumType.nominalTypeDecl.name)$\(enumCase.name)$$JNI",
209-
parameters: [],
210-
resultType: .void
211-
) { printer in
212-
// Setup caching
177+
private func renderEnumCaseCacheInit(_ enumCase: TranslatedEnumCase) -> String {
213178
let nativeParametersClassName = "\(javaPackagePath)/\(enumCase.enumName)$\(enumCase.name)$$NativeParameters"
214179
let methodSignature = MethodSignature(resultType: .void, parameterTypes: enumCase.parameterConversions.map(\.native.javaType))
215180
let methods = #"[.init(name: "<init>", signature: "\#(methodSignature.mangledName)")]"#
216181

217-
printer.print(#"JNICaches.\#(JNICaching.cacheName(for: enumCase.original)) = _JNICache(environment: environment, className: "\#(nativeParametersClassName)", methods: \#(methods))"#)
218-
}
182+
return #"_JNIMethodIDCache(environment: try! JavaVirtualMachine.shared().environment(), className: "\#(nativeParametersClassName)", methods: \#(methods))"#
219183
}
220184

221185
private func printEnumGetAsCaseThunk(
@@ -237,9 +201,9 @@ extension JNISwift2JavaGenerator {
237201
guard case .\(enumCase.original.name)(\(caseNamesWithLet.joined(separator: ", "))) = \(selfPointer).pointee else {
238202
fatalError("Expected enum case '\(enumCase.original.name)', but was '\\(\(selfPointer).pointee)'!")
239203
}
240-
let cache$ = JNICaches.\(JNICaching.cacheName(for: enumCase.original))!
204+
let cache$ = \(JNICaching.cacheName(for: enumCase.original.enumType)).\(JNICaching.cacheMemberName(for: enumCase.original))
241205
let class$ = cache$.javaClass
242-
let method$ = _JNICache.Method(name: "<init>", signature: "\(methodSignature.mangledName)")
206+
let method$ = _JNIMethodIDCache.Method(name: "<init>", signature: "\(methodSignature.mangledName)")
243207
let constructorID$ = cache$[method$]
244208
"""
245209
)

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator {
7272
return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift"))
7373
})
7474
self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift")
75-
self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)+JNICaches.swift")
7675

7776
// FIXME: Can we avoid this?
7877
self.expectedOutputSwiftFiles.insert("Data+SwiftJava.swift")

Sources/JavaKit/Helpers/_JNICache.swift renamed to Sources/JavaKit/Helpers/_JNIMethodIDCache.swift

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,7 @@
1616
///
1717
/// This type is used internally in by the outputted JExtract wrappers
1818
/// to improve performance of any JNI lookups.
19-
///
20-
/// - Warning: This type is inherently thread-unsafe.
21-
/// We assume that there exists **at most** one of these
22-
/// per Java `class`, and it must only be initialized and modified in the
23-
/// static initializer of that Java class.
24-
public final class _JNICache: @unchecked Sendable {
19+
public final class _JNIMethodIDCache: Sendable {
2520
public struct Method: Hashable {
2621
public let name: String
2722
public let signature: String
@@ -32,9 +27,8 @@ public final class _JNICache: @unchecked Sendable {
3227
}
3328
}
3429

35-
var _class: jclass?
36-
let environment: JNIEnvironment
37-
let methods: [Method: jmethodID]
30+
nonisolated(unsafe) let _class: jclass?
31+
nonisolated(unsafe) let methods: [Method: jmethodID]
3832

3933
public var javaClass: jclass {
4034
self._class!
@@ -44,7 +38,6 @@ public final class _JNICache: @unchecked Sendable {
4438
guard let clazz = environment.interface.FindClass(environment, className) else {
4539
fatalError("Class \(className) could not be found!")
4640
}
47-
self.environment = environment
4841
self._class = environment.interface.NewGlobalRef(environment, clazz)!
4942
self.methods = methods.reduce(into: [:]) { (result, method) in
5043
if let methodID = environment.interface.GetMethodID(environment, clazz, method.name, method.signature) {
@@ -60,12 +53,7 @@ public final class _JNICache: @unchecked Sendable {
6053
methods[method]
6154
}
6255

63-
func cleanup() {
56+
public func cleanup(environment: UnsafeMutablePointer<JNIEnv?>!) {
6457
environment.interface.DeleteGlobalRef(environment, self._class)
6558
}
66-
67-
deinit {
68-
cleanup()
69-
self._class = nil
70-
}
7159
}

Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ try (var arena = SwiftArena.ofConfined()) {
194194
}
195195
```
196196

197-
#### Switching
197+
#### Switching and pattern matching
198198

199199
If you only need to switch on the case and not access any associated values,
200200
you can use the `getDiscriminator()` method:
@@ -246,7 +246,7 @@ if (case instanceof Vehicle.Bicycle) {
246246
}
247247
```
248248

249-
#### RawRepresentable
249+
#### RawRepresentable enums
250250

251251
JExtract also supports extracting enums that conform to `RawRepresentable`
252252
by giving access to an optional initializer and the `rawValue` variable.

0 commit comments

Comments
 (0)