Skip to content

Commit 5d58ecc

Browse files
authored
Merge pull request #245 from rintaro/jextract-init-as-method
[JExtract] Import initializers as static methods
2 parents 3b850e0 + a8fa302 commit 5d58ecc

File tree

16 files changed

+49
-123
lines changed

16 files changed

+49
-123
lines changed

Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void beforeALl() {
4545
System.setProperty("jextract.trace.downcalls", "false");
4646

4747
arena = SwiftArena.ofConfined();
48-
obj = new MySwiftClass(1, 2, arena);
48+
obj = MySwiftClass.init(1, 2, arena);
4949
}
5050

5151
@TearDown(Level.Trial)

Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static void examples() {
4444

4545
// Example of using an arena; MyClass.deinit is run at end of scope
4646
try (var arena = SwiftArena.ofConfined()) {
47-
MySwiftClass obj = new MySwiftClass(2222, 7777, arena);
47+
MySwiftClass obj = MySwiftClass.init(2222, 7777, arena);
4848

4949
// just checking retains/releases work
5050
SwiftKit.retain(obj);

Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void checkPaths(Throwable throwable) {
4343
@Test
4444
void test_MySwiftClass_voidMethod() {
4545
try(var arena = SwiftArena.ofConfined()) {
46-
MySwiftClass o = new MySwiftClass(12, 42, arena);
46+
MySwiftClass o = MySwiftClass.init(12, 42, arena);
4747
o.voidMethod();
4848
} catch (Throwable throwable) {
4949
checkPaths(throwable);
@@ -53,7 +53,7 @@ void test_MySwiftClass_voidMethod() {
5353
@Test
5454
void test_MySwiftClass_makeIntMethod() {
5555
try(var arena = SwiftArena.ofConfined()) {
56-
MySwiftClass o = new MySwiftClass(12, 42, arena);
56+
MySwiftClass o = MySwiftClass.init(12, 42, arena);
5757
var got = o.makeIntMethod();
5858
assertEquals(12, got);
5959
}
@@ -63,7 +63,7 @@ void test_MySwiftClass_makeIntMethod() {
6363
@Disabled // TODO: Need var mangled names in interfaces
6464
void test_MySwiftClass_property_len() {
6565
try(var arena = SwiftArena.ofConfined()) {
66-
MySwiftClass o = new MySwiftClass(12, 42, arena);
66+
MySwiftClass o = MySwiftClass.init(12, 42, arena);
6767
var got = o.getLen();
6868
assertEquals(12, got);
6969
}

Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class MySwiftClassTest {
2525
@Test
2626
void call_retain_retainCount_release() {
2727
var arena = SwiftArena.ofConfined();
28-
var obj = new MySwiftClass(1, 2, arena);
28+
var obj = MySwiftClass.init(1, 2, arena);
2929

3030
assertEquals(1, SwiftKit.retainCount(obj));
3131
// TODO: test directly on SwiftHeapObject inheriting obj

Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static boolean isAmd64() {
3939
@DisabledIf("isAmd64")
4040
public void arena_releaseClassOnClose_class_ok() {
4141
try (var arena = SwiftArena.ofConfined()) {
42-
var obj = new MySwiftClass(1, 2, arena);
42+
var obj = MySwiftClass.init(1, 2, arena);
4343

4444
retain(obj);
4545
assertEquals(2, retainCount(obj));

Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public static class BenchmarkState {
3737
@Setup(Level.Trial)
3838
public void beforeAll() {
3939
arena = SwiftArena.ofConfined();
40-
obj = new MySwiftClass(1, 2, arena);
40+
obj = MySwiftClass.init(1, 2, arena);
4141
}
4242

4343
@TearDown(Level.Trial)

Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public class StringPassingBenchmark {
4646
@Setup(Level.Trial)
4747
public void beforeAll() {
4848
arena = SwiftArena.ofConfined();
49-
obj = new MySwiftClass(1, 2, arena);
49+
obj = MySwiftClass.init(1, 2, arena);
5050
string = makeString(stringLen);
5151
}
5252

Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static void examples() {
4747

4848
// Example of using an arena; MyClass.deinit is run at end of scope
4949
try (var arena = SwiftArena.ofConfined()) {
50-
MySwiftClass obj = new MySwiftClass(2222, 7777, arena);
50+
MySwiftClass obj = MySwiftClass.init(2222, 7777, arena);
5151

5252
// just checking retains/releases work
5353
SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj));
@@ -65,7 +65,7 @@ static void examples() {
6565
MySwiftClass otherObj = MySwiftClass.factory(12, 42, arena);
6666
otherObj.voidMethod();
6767

68-
MySwiftStruct swiftValue = new MySwiftStruct(2222, 1111, arena);
68+
MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena);
6969
SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity());
7070
}
7171

Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void checkPaths(Throwable throwable) {
4242
@Test
4343
void test_MySwiftClass_voidMethod() {
4444
try(var arena = SwiftArena.ofConfined()) {
45-
MySwiftClass o = new MySwiftClass(12, 42, arena);
45+
MySwiftClass o = MySwiftClass.init(12, 42, arena);
4646
o.voidMethod();
4747
} catch (Throwable throwable) {
4848
checkPaths(throwable);
@@ -52,7 +52,7 @@ void test_MySwiftClass_voidMethod() {
5252
@Test
5353
void test_MySwiftClass_makeIntMethod() {
5454
try(var arena = SwiftArena.ofConfined()) {
55-
MySwiftClass o = new MySwiftClass(12, 42, arena);
55+
MySwiftClass o = MySwiftClass.init(12, 42, arena);
5656
var got = o.makeIntMethod();
5757
assertEquals(12, got);
5858
}
@@ -62,7 +62,7 @@ void test_MySwiftClass_makeIntMethod() {
6262
@Disabled // TODO: Need var mangled names in interfaces
6363
void test_MySwiftClass_property_len() {
6464
try(var arena = SwiftArena.ofConfined()) {
65-
MySwiftClass o = new MySwiftClass(12, 42, arena);
65+
MySwiftClass o = MySwiftClass.init(12, 42, arena);
6666
var got = o.getLen();
6767
assertEquals(12, got);
6868
}

Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class MySwiftClassTest {
2525
@Test
2626
void call_retain_retainCount_release() {
2727
var arena = SwiftArena.ofConfined();
28-
var obj = new MySwiftClass(1, 2, arena);
28+
var obj = MySwiftClass.init(1, 2, arena);
2929

3030
assertEquals(1, SwiftKit.retainCount(obj));
3131
// TODO: test directly on SwiftHeapObject inheriting obj

Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ void create_struct() {
2626
try (var arena = SwiftArena.ofConfined()) {
2727
long cap = 12;
2828
long len = 34;
29-
var struct = new MySwiftStruct(cap, len, arena);
29+
var struct = MySwiftStruct.init(cap, len, arena);
3030

3131
assertEquals(cap, struct.getCapacity());
3232
assertEquals(len, struct.getLength());

Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ static boolean isAmd64() {
4040
@DisabledIf("isAmd64")
4141
public void arena_releaseClassOnClose_class_ok() {
4242
try (var arena = SwiftArena.ofConfined()) {
43-
var obj = new MySwiftClass(1, 2, arena);
43+
var obj = MySwiftClass.init(1, 2, arena);
4444

4545
retain(obj);
4646
assertEquals(2, retainCount(obj));
@@ -57,7 +57,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_class() {
5757
MySwiftClass unsafelyEscapedOutsideArenaScope = null;
5858

5959
try (var arena = SwiftArena.ofConfined()) {
60-
var obj = new MySwiftClass(1, 2, arena);
60+
var obj = MySwiftClass.init(1, 2, arena);
6161
unsafelyEscapedOutsideArenaScope = obj;
6262
}
6363

@@ -76,7 +76,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_struct() {
7676
MySwiftStruct unsafelyEscapedOutsideArenaScope = null;
7777

7878
try (var arena = SwiftArena.ofConfined()) {
79-
var s = new MySwiftStruct(1, 2, arena);
79+
var s = MySwiftStruct.init(1, 2, arena);
8080
unsafelyEscapedOutsideArenaScope = s;
8181
}
8282

Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,6 @@
1515
import JavaTypes
1616

1717
extension Swift2JavaTranslator {
18-
public func printInitializerDowncallConstructors(
19-
_ printer: inout CodePrinter,
20-
_ decl: ImportedFunc
21-
) {
22-
printer.printSeparator(decl.displayName)
23-
24-
printJavaBindingDescriptorClass(&printer, decl)
25-
26-
// Render the "make the downcall" functions.
27-
printInitializerDowncallConstructor(&printer, decl)
28-
}
29-
3018
public func printFunctionDowncallMethods(
3119
_ printer: inout CodePrinter,
3220
_ decl: ImportedFunc
@@ -86,43 +74,6 @@ extension Swift2JavaTranslator {
8674
printer.print(");")
8775
}
8876

89-
public func printInitializerDowncallConstructor(
90-
_ printer: inout CodePrinter,
91-
_ decl: ImportedFunc
92-
) {
93-
guard let className = decl.parentType?.asNominalTypeDeclaration?.name else {
94-
return
95-
}
96-
let modifiers = "public"
97-
98-
var paramDecls = decl.translatedSignature.parameters
99-
.flatMap(\.javaParameters)
100-
.map { "\($0.type) \($0.name)" }
101-
102-
assert(decl.translatedSignature.requiresSwiftArena, "constructor always require the SwiftArena")
103-
paramDecls.append("SwiftArena swiftArena$")
104-
105-
printer.printBraceBlock(
106-
"""
107-
/**
108-
* Create an instance of {@code \(className)}.
109-
*
110-
* {@snippet lang=swift :
111-
* \(decl.signatureString)
112-
* }
113-
*/
114-
\(modifiers) \(className)(\(paramDecls.joined(separator: ", ")))
115-
"""
116-
) { printer in
117-
// Call super constructor `SwiftValue(Supplier <MemorySegment>, SwiftArena)`.
118-
printer.print("super(() -> {")
119-
printer.indent()
120-
printDowncall(&printer, decl, isConstructor: true)
121-
printer.outdent()
122-
printer.print("}, swiftArena$);")
123-
}
124-
}
125-
12677
/// Print the calling body that forwards all the parameters to the `methodName`,
12778
/// with adding `SwiftArena.ofAuto()` at the end.
12879
public func printFuncDowncallMethod(
@@ -131,13 +82,12 @@ extension Swift2JavaTranslator {
13182
let methodName: String = switch decl.kind {
13283
case .getter: "get\(decl.name.toCamelCase)"
13384
case .setter: "set\(decl.name.toCamelCase)"
134-
case .function: decl.name
135-
case .initializer: fatalError("initializers must use printInitializerDowncallConstructor()")
85+
case .function, .initializer: decl.name
13686
}
13787

13888
var modifiers = "public"
13989
switch decl.swiftSignature.selfParameter {
140-
case .staticMethod(_), nil:
90+
case .staticMethod, .initializer, nil:
14191
modifiers.append(" static")
14292
default:
14393
break
@@ -178,8 +128,7 @@ extension Swift2JavaTranslator {
178128
/// This assumes that all the parameters are passed-in with appropriate names.
179129
package func printDowncall(
180130
_ printer: inout CodePrinter,
181-
_ decl: ImportedFunc,
182-
isConstructor: Bool = false
131+
_ decl: ImportedFunc
183132
) {
184133
//=== Part 1: MethodHandle
185134
let descriptorClassIdentifier = thunkNameRegistry.functionThunkName(decl: decl)
@@ -252,11 +201,7 @@ extension Swift2JavaTranslator {
252201
let downCall = "mh$.invokeExact(\(downCallArguments.joined(separator: ", ")))"
253202

254203
//=== Part 4: Convert the return value.
255-
if isConstructor {
256-
// For constructors, the caller expects the "self" memory segment.
257-
printer.print("\(downCall);")
258-
printer.print("return _result;")
259-
} else if decl.translatedSignature.result.javaResultType == .void {
204+
if decl.translatedSignature.result.javaResultType == .void {
260205
printer.print("\(downCall);")
261206
} else {
262207
let placeholder: String

Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ extension Swift2JavaTranslator {
125125

126126
// Initializers
127127
for initDecl in decl.initializers {
128-
printInitializerDowncallConstructors(&printer, initDecl)
128+
printFunctionDowncallMethods(&printer, initDecl)
129129
}
130130

131131
// Properties

SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,6 @@ protected SwiftInstance(MemorySegment segment, SwiftArena arena) {
6666
arena.register(this);
6767
}
6868

69-
/**
70-
* Convenience constructor subclasses can call like:
71-
* {@snippet :
72-
* super(() -> { ...; return segment; }, swiftArena$)
73-
* }
74-
*
75-
* @param segmentSupplier Should return the memory segment of the value
76-
* @param arena the arena where the supplied segment belongs to. When the arena goes out of scope, this value is destroyed.
77-
*/
78-
protected SwiftInstance(Supplier<MemorySegment> segmentSupplier, SwiftArena arena) {
79-
this(segmentSupplier.get(), arena);
80-
}
81-
8269
/**
8370
* Ensures that this instance has not been destroyed.
8471
* <p/>

Tests/JExtractSwiftTests/MethodImportTests.swift

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -334,34 +334,31 @@ final class MethodImportTests {
334334
}!
335335

336336
let output = CodePrinter.toString { printer in
337-
st.printInitializerDowncallConstructor(&printer, initDecl)
337+
st.printFuncDowncallMethod(&printer, initDecl)
338338
}
339339

340340
assertOutput(
341341
output,
342342
expected:
343343
"""
344344
/**
345-
* Create an instance of {@code MySwiftClass}.
346-
*
345+
* Downcall to Swift:
347346
* {@snippet lang=swift :
348347
* public init(len: Swift.Int, cap: Swift.Int)
349348
* }
350349
*/
351-
public MySwiftClass(long len, long cap, SwiftArena swiftArena$) {
352-
super(() -> {
353-
var mh$ = swiftjava___FakeModule_MySwiftClass_init_len_cap.HANDLE;
354-
try {
355-
MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT);
356-
if (SwiftKit.TRACE_DOWNCALLS) {
357-
SwiftKit.traceDowncall(len, cap, _result);
358-
}
359-
mh$.invokeExact(len, cap, _result);
360-
return _result;
361-
} catch (Throwable ex$) {
362-
throw new AssertionError("should not reach here", ex$);
350+
public static MySwiftClass init(long len, long cap, SwiftArena swiftArena$) {
351+
var mh$ = swiftjava___FakeModule_MySwiftClass_init_len_cap.HANDLE;
352+
try {
353+
MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT);
354+
if (SwiftKit.TRACE_DOWNCALLS) {
355+
SwiftKit.traceDowncall(len, cap, _result);
363356
}
364-
}, swiftArena$);
357+
mh$.invokeExact(len, cap, _result);
358+
return new MySwiftClass(_result, swiftArena$);
359+
} catch (Throwable ex$) {
360+
throw new AssertionError("should not reach here", ex$);
361+
}
365362
}
366363
"""
367364
)
@@ -382,34 +379,31 @@ final class MethodImportTests {
382379
}!
383380

384381
let output = CodePrinter.toString { printer in
385-
st.printInitializerDowncallConstructor(&printer, initDecl)
382+
st.printFuncDowncallMethod(&printer, initDecl)
386383
}
387384

388385
assertOutput(
389386
output,
390387
expected:
391388
"""
392389
/**
393-
* Create an instance of {@code MySwiftStruct}.
394-
*
390+
* Downcall to Swift:
395391
* {@snippet lang=swift :
396392
* public init(len: Swift.Int, cap: Swift.Int)
397393
* }
398394
*/
399-
public MySwiftStruct(long len, long cap, SwiftArena swiftArena$) {
400-
super(() -> {
401-
var mh$ = swiftjava___FakeModule_MySwiftStruct_init_len_cap.HANDLE;
402-
try {
403-
MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT);
404-
if (SwiftKit.TRACE_DOWNCALLS) {
395+
public static MySwiftStruct init(long len, long cap, SwiftArena swiftArena$) {
396+
var mh$ = swiftjava___FakeModule_MySwiftStruct_init_len_cap.HANDLE;
397+
try {
398+
MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT);
399+
if (SwiftKit.TRACE_DOWNCALLS) {
405400
SwiftKit.traceDowncall(len, cap, _result);
406-
}
407-
mh$.invokeExact(len, cap, _result);
408-
return _result;
409-
} catch (Throwable ex$) {
410-
throw new AssertionError("should not reach here", ex$);
411401
}
412-
}, swiftArena$);
402+
mh$.invokeExact(len, cap, _result);
403+
return new MySwiftStruct(_result, swiftArena$);
404+
} catch (Throwable ex$) {
405+
throw new AssertionError("should not reach here", ex$);
406+
}
413407
}
414408
"""
415409
)

0 commit comments

Comments
 (0)