diff --git a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index aba652cb..4e3edf03 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -45,7 +45,7 @@ public void beforeALl() { System.setProperty("jextract.trace.downcalls", "false"); arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(1, 2, arena); + obj = MySwiftClass.init(1, 2, arena); } @TearDown(Level.Trial) diff --git a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java index 42aa1d0c..cd8af700 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java @@ -44,7 +44,7 @@ static void examples() { // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { - MySwiftClass obj = new MySwiftClass(2222, 7777, arena); + MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work SwiftKit.retain(obj); diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java index 47416f06..bb46ef3d 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java @@ -43,7 +43,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { checkPaths(throwable); @@ -53,7 +53,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); } @@ -63,7 +63,7 @@ void test_MySwiftClass_makeIntMethod() { @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.getLen(); assertEquals(12, got); } diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 3d9a360b..78da5a64 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -25,7 +25,7 @@ public class MySwiftClassTest { @Test void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); assertEquals(1, SwiftKit.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index 43c03808..e8b1ac04 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -39,7 +39,7 @@ static boolean isAmd64() { @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); retain(obj); assertEquals(2, retainCount(obj)); diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index 70f8102c..ff313fc6 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -37,7 +37,7 @@ public static class BenchmarkState { @Setup(Level.Trial) public void beforeAll() { arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(1, 2, arena); + obj = MySwiftClass.init(1, 2, arena); } @TearDown(Level.Trial) diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java index b7cb45ff..0e686fb4 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java @@ -46,7 +46,7 @@ public class StringPassingBenchmark { @Setup(Level.Trial) public void beforeAll() { arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(1, 2, arena); + obj = MySwiftClass.init(1, 2, arena); string = makeString(stringLen); } diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 56ac4d21..e20ac378 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -47,7 +47,7 @@ static void examples() { // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { - MySwiftClass obj = new MySwiftClass(2222, 7777, arena); + MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); @@ -65,7 +65,7 @@ static void examples() { MySwiftClass otherObj = MySwiftClass.factory(12, 42, arena); otherObj.voidMethod(); - MySwiftStruct swiftValue = new MySwiftStruct(2222, 1111, arena); + MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena); SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity()); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 71598eed..6c0ceb1e 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -42,7 +42,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { checkPaths(throwable); @@ -52,7 +52,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); } @@ -62,7 +62,7 @@ void test_MySwiftClass_makeIntMethod() { @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.getLen(); assertEquals(12, got); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 3d9a360b..78da5a64 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -25,7 +25,7 @@ public class MySwiftClassTest { @Test void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); assertEquals(1, SwiftKit.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java index 53390da7..843551a5 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java @@ -26,7 +26,7 @@ void create_struct() { try (var arena = SwiftArena.ofConfined()) { long cap = 12; long len = 34; - var struct = new MySwiftStruct(cap, len, arena); + var struct = MySwiftStruct.init(cap, len, arena); assertEquals(cap, struct.getCapacity()); assertEquals(len, struct.getLength()); diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index f7832b48..0d900a62 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -40,7 +40,7 @@ static boolean isAmd64() { @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); retain(obj); assertEquals(2, retainCount(obj)); @@ -57,7 +57,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_class() { MySwiftClass unsafelyEscapedOutsideArenaScope = null; try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); unsafelyEscapedOutsideArenaScope = obj; } @@ -76,7 +76,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_struct() { MySwiftStruct unsafelyEscapedOutsideArenaScope = null; try (var arena = SwiftArena.ofConfined()) { - var s = new MySwiftStruct(1, 2, arena); + var s = MySwiftStruct.init(1, 2, arena); unsafelyEscapedOutsideArenaScope = s; } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift index f96d3904..27869695 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift @@ -15,18 +15,6 @@ import JavaTypes extension Swift2JavaTranslator { - public func printInitializerDowncallConstructors( - _ printer: inout CodePrinter, - _ decl: ImportedFunc - ) { - printer.printSeparator(decl.displayName) - - printJavaBindingDescriptorClass(&printer, decl) - - // Render the "make the downcall" functions. - printInitializerDowncallConstructor(&printer, decl) - } - public func printFunctionDowncallMethods( _ printer: inout CodePrinter, _ decl: ImportedFunc @@ -86,43 +74,6 @@ extension Swift2JavaTranslator { printer.print(");") } - public func printInitializerDowncallConstructor( - _ printer: inout CodePrinter, - _ decl: ImportedFunc - ) { - guard let className = decl.parentType?.asNominalTypeDeclaration?.name else { - return - } - let modifiers = "public" - - var paramDecls = decl.translatedSignature.parameters - .flatMap(\.javaParameters) - .map { "\($0.type) \($0.name)" } - - assert(decl.translatedSignature.requiresSwiftArena, "constructor always require the SwiftArena") - paramDecls.append("SwiftArena swiftArena$") - - printer.printBraceBlock( - """ - /** - * Create an instance of {@code \(className)}. - * - * {@snippet lang=swift : - * \(decl.signatureString) - * } - */ - \(modifiers) \(className)(\(paramDecls.joined(separator: ", "))) - """ - ) { printer in - // Call super constructor `SwiftValue(Supplier , SwiftArena)`. - printer.print("super(() -> {") - printer.indent() - printDowncall(&printer, decl, isConstructor: true) - printer.outdent() - printer.print("}, swiftArena$);") - } - } - /// Print the calling body that forwards all the parameters to the `methodName`, /// with adding `SwiftArena.ofAuto()` at the end. public func printFuncDowncallMethod( @@ -131,13 +82,12 @@ extension Swift2JavaTranslator { let methodName: String = switch decl.kind { case .getter: "get\(decl.name.toCamelCase)" case .setter: "set\(decl.name.toCamelCase)" - case .function: decl.name - case .initializer: fatalError("initializers must use printInitializerDowncallConstructor()") + case .function, .initializer: decl.name } var modifiers = "public" switch decl.swiftSignature.selfParameter { - case .staticMethod(_), nil: + case .staticMethod, .initializer, nil: modifiers.append(" static") default: break @@ -178,8 +128,7 @@ extension Swift2JavaTranslator { /// This assumes that all the parameters are passed-in with appropriate names. package func printDowncall( _ printer: inout CodePrinter, - _ decl: ImportedFunc, - isConstructor: Bool = false + _ decl: ImportedFunc ) { //=== Part 1: MethodHandle let descriptorClassIdentifier = thunkNameRegistry.functionThunkName(decl: decl) @@ -252,11 +201,7 @@ extension Swift2JavaTranslator { let downCall = "mh$.invokeExact(\(downCallArguments.joined(separator: ", ")))" //=== Part 4: Convert the return value. - if isConstructor { - // For constructors, the caller expects the "self" memory segment. - printer.print("\(downCall);") - printer.print("return _result;") - } else if decl.translatedSignature.result.javaResultType == .void { + if decl.translatedSignature.result.javaResultType == .void { printer.print("\(downCall);") } else { let placeholder: String diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 98b3c767..13e337e0 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -125,7 +125,7 @@ extension Swift2JavaTranslator { // Initializers for initDecl in decl.initializers { - printInitializerDowncallConstructors(&printer, initDecl) + printFunctionDowncallMethods(&printer, initDecl) } // Properties diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java index 2725966d..5b8ff700 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java @@ -66,19 +66,6 @@ protected SwiftInstance(MemorySegment segment, SwiftArena arena) { arena.register(this); } - /** - * Convenience constructor subclasses can call like: - * {@snippet : - * super(() -> { ...; return segment; }, swiftArena$) - * } - * - * @param segmentSupplier Should return the memory segment of the value - * @param arena the arena where the supplied segment belongs to. When the arena goes out of scope, this value is destroyed. - */ - protected SwiftInstance(Supplier segmentSupplier, SwiftArena arena) { - this(segmentSupplier.get(), arena); - } - /** * Ensures that this instance has not been destroyed. *

diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 34fda1d4..bad1025e 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -334,7 +334,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printInitializerDowncallConstructor(&printer, initDecl) + st.printFuncDowncallMethod(&printer, initDecl) } assertOutput( @@ -342,26 +342,23 @@ final class MethodImportTests { expected: """ /** - * Create an instance of {@code MySwiftClass}. - * + * Downcall to Swift: * {@snippet lang=swift : * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftClass(long len, long cap, SwiftArena swiftArena$) { - super(() -> { - var mh$ = swiftjava___FakeModule_MySwiftClass_init_len_cap.HANDLE; - try { - MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(len, cap, _result); - } - mh$.invokeExact(len, cap, _result); - return _result; - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + public static MySwiftClass init(long len, long cap, SwiftArena swiftArena$) { + var mh$ = swiftjava___FakeModule_MySwiftClass_init_len_cap.HANDLE; + try { + MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(len, cap, _result); } - }, swiftArena$); + mh$.invokeExact(len, cap, _result); + return new MySwiftClass(_result, swiftArena$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } """ ) @@ -382,7 +379,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printInitializerDowncallConstructor(&printer, initDecl) + st.printFuncDowncallMethod(&printer, initDecl) } assertOutput( @@ -390,26 +387,23 @@ final class MethodImportTests { expected: """ /** - * Create an instance of {@code MySwiftStruct}. - * + * Downcall to Swift: * {@snippet lang=swift : * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftStruct(long len, long cap, SwiftArena swiftArena$) { - super(() -> { - var mh$ = swiftjava___FakeModule_MySwiftStruct_init_len_cap.HANDLE; - try { - MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); - if (SwiftKit.TRACE_DOWNCALLS) { + public static MySwiftStruct init(long len, long cap, SwiftArena swiftArena$) { + var mh$ = swiftjava___FakeModule_MySwiftStruct_init_len_cap.HANDLE; + try { + MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); + if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(len, cap, _result); - } - mh$.invokeExact(len, cap, _result); - return _result; - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); } - }, swiftArena$); + mh$.invokeExact(len, cap, _result); + return new MySwiftStruct(_result, swiftArena$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } """ )