Skip to content

Commit cbfb56d

Browse files
committed
Add CallTraces to swiftkit core and use it while downcalling
1 parent 97c9a26 commit cbfb56d

File tree

12 files changed

+157
-86
lines changed

12 files changed

+157
-86
lines changed

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

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
// Import javakit/swiftkit support libraries
2020

21+
import org.swift.swiftkit.core.CallTraces;
2122
import org.swift.swiftkit.core.SwiftLibraries;
2223
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
2324
import org.swift.swiftkit.ffm.SwiftRuntime;
@@ -40,30 +41,30 @@ static void examples() {
4041

4142
long cnt = MySwiftLibrary.globalWriteString("String from Java");
4243

43-
SwiftRuntime.trace("count = " + cnt);
44+
CallTraces.trace("count = " + cnt);
4445

4546
MySwiftLibrary.globalCallMeRunnable(() -> {
46-
SwiftRuntime.trace("running runnable");
47+
CallTraces.trace("running runnable");
4748
});
4849

49-
SwiftRuntime.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize());
50+
CallTraces.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize());
5051

5152
MySwiftLibrary.withBuffer((buf) -> {
52-
SwiftRuntime.trace("withBuffer{$0.byteSize()}=" + buf.byteSize());
53+
CallTraces.trace("withBuffer{$0.byteSize()}=" + buf.byteSize());
5354
});
5455
// Example of using an arena; MyClass.deinit is run at end of scope
5556
try (var arena = AllocatingSwiftArena.ofConfined()) {
5657
MySwiftClass obj = MySwiftClass.init(2222, 7777, arena);
5758

5859
// just checking retains/releases work
59-
SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj));
60+
CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj));
6061
SwiftRuntime.retain(obj);
61-
SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj));
62+
CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj));
6263
SwiftRuntime.release(obj);
63-
SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj));
64+
CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj));
6465

6566
obj.setCounter(12);
66-
SwiftRuntime.trace("obj.counter = " + obj.getCounter());
67+
CallTraces.trace("obj.counter = " + obj.getCounter());
6768

6869
obj.voidMethod();
6970
obj.takeIntMethod(42);
@@ -72,22 +73,22 @@ static void examples() {
7273
otherObj.voidMethod();
7374

7475
MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena);
75-
SwiftRuntime.trace("swiftValue.capacity = " + swiftValue.getCapacity());
76+
CallTraces.trace("swiftValue.capacity = " + swiftValue.getCapacity());
7677
swiftValue.withCapLen((cap, len) -> {
77-
SwiftRuntime.trace("withCapLenCallback: cap=" + cap + ", len=" + len);
78+
CallTraces.trace("withCapLenCallback: cap=" + cap + ", len=" + len);
7879
});
7980
}
8081

8182
// Example of using 'Data'.
8283
try (var arena = AllocatingSwiftArena.ofConfined()) {
8384
var origBytes = arena.allocateFrom("foobar");
8485
var origDat = Data.init(origBytes, origBytes.byteSize(), arena);
85-
SwiftRuntime.trace("origDat.count = " + origDat.getCount());
86+
CallTraces.trace("origDat.count = " + origDat.getCount());
8687

8788
var retDat = MySwiftLibrary.globalReceiveReturnData(origDat, arena);
8889
retDat.withUnsafeBytes((retBytes) -> {
8990
var str = retBytes.getString(0);
90-
SwiftRuntime.trace("retStr=" + str);
91+
CallTraces.trace("retStr=" + str);
9192
});
9293
}
9394

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ extension FFMSwift2JavaGenerator {
116116
"""
117117
public static \(returnTy) call(\(paramsStr)) {
118118
try {
119-
if (SwiftRuntime.TRACE_DOWNCALLS) {
120-
SwiftRuntime.traceDowncall(\(argsStr));
119+
if (CallTraces.TRACE_DOWNCALLS) {
120+
CallTraces.traceDowncall(\(argsStr));
121121
}
122122
\(maybeReturn)HANDLE.invokeExact(\(argsStr));
123123
} catch (Throwable ex$) {

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,25 @@ extension JNISwift2JavaGenerator {
262262
private func printDestroyFunction(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
263263
printer.print("private static native void $destroy(long selfPointer);")
264264

265+
let funcName = "$createDestroyFunction"
265266
printer.print("@Override")
266-
printer.printBraceBlock("protected Runnable $createDestroyFunction()") { printer in
267+
printer.printBraceBlock("protected Runnable \(funcName)()") { printer in
267268
printer.print(
268269
"""
269-
long $selfPointer = this.pointer();
270+
if (CallTraces.TRACE_DOWNCALLS) {
271+
CallTraces.traceDowncall("\(type.swiftNominal.name).\(funcName)",
272+
"this", this,
273+
"this.$memoryAddress()", this.$memoryAddress());
274+
}
275+
long self$ = this.$memoryAddress();
276+
assert(self$ > 0);
270277
return new Runnable() {
271278
@Override
272279
public void run() {
273-
\(type.swiftNominal.name).$destroy($selfPointer);
280+
if (CallTraces.TRACE_DOWNCALLS) {
281+
CallTraces.traceDowncall("\(type.swiftNominal.name).$destroy(" + self$ + ")");
282+
}
283+
\(type.swiftNominal.name).$destroy(self$);
274284
}
275285
};
276286
"""
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
package org.swift.swiftkit.core;
16+
17+
public class CallTraces {
18+
public static final boolean TRACE_DOWNCALLS =
19+
Boolean.getBoolean("jextract.trace.downcalls");
20+
21+
// Used to manually debug with complete backtraces on every traceDowncall
22+
public static final boolean TRACE_DOWNCALLS_FULL = false;
23+
24+
public static void traceDowncall(Object... args) {
25+
RuntimeException ex = new RuntimeException();
26+
27+
String traceArgs = joinArgs(args);
28+
System.err.printf("[java][%s:%d] Downcall: %s.%s(%s)\n",
29+
ex.getStackTrace()[1].getFileName(),
30+
ex.getStackTrace()[1].getLineNumber(),
31+
ex.getStackTrace()[1].getClassName(),
32+
ex.getStackTrace()[1].getMethodName(),
33+
traceArgs);
34+
if (TRACE_DOWNCALLS_FULL) {
35+
ex.printStackTrace();
36+
}
37+
}
38+
39+
public static void trace(Object... args) {
40+
RuntimeException ex = new RuntimeException();
41+
42+
String traceArgs = joinArgs(args);
43+
System.err.printf("[java][%s:%d] %s: %s\n",
44+
ex.getStackTrace()[1].getFileName(),
45+
ex.getStackTrace()[1].getLineNumber(),
46+
ex.getStackTrace()[1].getMethodName(),
47+
traceArgs);
48+
}
49+
50+
private static String joinArgs(Object[] args) {
51+
StringBuilder sb = new StringBuilder();
52+
for (int i = 0; i < args.length; i++) {
53+
if (i > 0) {
54+
sb.append(", ");
55+
}
56+
sb.append(args[i].toString());
57+
}
58+
return sb.toString();
59+
}
60+
61+
}

SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ public final class SwiftLibraries {
2626

2727
public static final String STDLIB_DYLIB_NAME = "swiftCore";
2828
public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift";
29-
public static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls");
3029

3130
private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib";
3231

@@ -57,7 +56,7 @@ public static void loadLibrary(String libname) {
5756

5857
public static void loadResourceLibrary(String libname) {
5958
String resourceName = PlatformUtils.dynamicLibraryName(libname);
60-
if (SwiftLibraries.TRACE_DOWNCALLS) {
59+
if (CallTraces.TRACE_DOWNCALLS) {
6160
System.out.println("[swift-java] Loading resource library: " + resourceName);
6261
}
6362

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
package org.swift.swiftkit.core;
16+
17+
/**
18+
* Utility functions, similar to @{link java.util.Objects}
19+
*/
20+
public class SwiftObjects {
21+
public static void requireNonZero(long number, String name) {
22+
if (number == 0) {
23+
throw new IllegalArgumentException(String.format("'%s' must not be zero!", name));
24+
}
25+
}
26+
}

SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package org.swift.swiftkit.ffm;
1616

17+
import org.swift.swiftkit.core.CallTraces;
1718
import org.swift.swiftkit.core.util.PlatformUtils;
1819

1920
import java.lang.foreign.*;
@@ -24,14 +25,14 @@
2425
import java.util.Optional;
2526
import java.util.stream.Collectors;
2627

28+
import static org.swift.swiftkit.core.CallTraces.traceDowncall;
2729
import static org.swift.swiftkit.core.util.StringUtils.stripPrefix;
2830
import static org.swift.swiftkit.core.util.StringUtils.stripSuffix;
2931

3032
public class SwiftRuntime {
3133

3234
public static final String STDLIB_DYLIB_NAME = "swiftCore";
3335
public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift";
34-
public static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls");
3536

3637
private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib";
3738

@@ -65,33 +66,6 @@ private static SymbolLookup getSymbolLookup() {
6566
public SwiftRuntime() {
6667
}
6768

68-
public static void traceDowncall(Object... args) {
69-
var ex = new RuntimeException();
70-
71-
String traceArgs = Arrays.stream(args)
72-
.map(Object::toString)
73-
.collect(Collectors.joining(", "));
74-
System.out.printf("[java][%s:%d] Downcall: %s.%s(%s)\n",
75-
ex.getStackTrace()[1].getFileName(),
76-
ex.getStackTrace()[1].getLineNumber(),
77-
ex.getStackTrace()[1].getClassName(),
78-
ex.getStackTrace()[1].getMethodName(),
79-
traceArgs);
80-
}
81-
82-
public static void trace(Object... args) {
83-
var ex = new RuntimeException();
84-
85-
String traceArgs = Arrays.stream(args)
86-
.map(Object::toString)
87-
.collect(Collectors.joining(", "));
88-
System.out.printf("[java][%s:%d] %s: %s\n",
89-
ex.getStackTrace()[1].getFileName(),
90-
ex.getStackTrace()[1].getLineNumber(),
91-
ex.getStackTrace()[1].getMethodName(),
92-
traceArgs);
93-
}
94-
9569
static MemorySegment findOrThrow(String symbol) {
9670
return SYMBOL_LOOKUP.find(symbol)
9771
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol)));
@@ -152,7 +126,7 @@ private static class swift_retainCount {
152126
public static long retainCount(MemorySegment object) {
153127
var mh$ = swift_retainCount.HANDLE;
154128
try {
155-
if (TRACE_DOWNCALLS) {
129+
if (CallTraces.TRACE_DOWNCALLS) {
156130
traceDowncall("swift_retainCount", object);
157131
}
158132
return (long) mh$.invokeExact(object);
@@ -182,7 +156,7 @@ private static class swift_retain {
182156
public static void retain(MemorySegment object) {
183157
var mh$ = swift_retain.HANDLE;
184158
try {
185-
if (TRACE_DOWNCALLS) {
159+
if (CallTraces.TRACE_DOWNCALLS) {
186160
traceDowncall("swift_retain", object);
187161
}
188162
mh$.invokeExact(object);
@@ -212,7 +186,7 @@ private static class swift_release {
212186
public static void release(MemorySegment object) {
213187
var mh$ = swift_release.HANDLE;
214188
try {
215-
if (TRACE_DOWNCALLS) {
189+
if (CallTraces.TRACE_DOWNCALLS) {
216190
traceDowncall("swift_release", object);
217191
}
218192
mh$.invokeExact(object);
@@ -248,7 +222,7 @@ private static class swift_getTypeByName {
248222
public static MemorySegment getTypeByName(String string) {
249223
var mh$ = swift_getTypeByName.HANDLE;
250224
try {
251-
if (TRACE_DOWNCALLS) {
225+
if (CallTraces.TRACE_DOWNCALLS) {
252226
traceDowncall("_typeByName");
253227
}
254228
// TODO: A bit annoying to generate, we need an arena for the conversion...
@@ -303,7 +277,7 @@ public static Optional<SwiftAnyType> getTypeByMangledNameInEnvironment(String ma
303277
// contain this, but we don't need it for type lookup
304278
mangledName = stripSuffix(mangledName, "Ma");
305279
mangledName = stripSuffix(mangledName, "CN");
306-
if (TRACE_DOWNCALLS) {
280+
if (CallTraces.TRACE_DOWNCALLS) {
307281
traceDowncall("swift_getTypeByMangledNameInEnvironment", mangledName);
308282
}
309283
try (Arena arena = Arena.ofConfined()) {

Tests/JExtractSwiftTests/DataImportTests.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ final class DataImportTests {
108108
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
109109
public static void call(java.lang.foreign.MemorySegment dat) {
110110
try {
111-
if (SwiftRuntime.TRACE_DOWNCALLS) {
112-
SwiftRuntime.traceDowncall(dat);
111+
if (CallTraces.TRACE_DOWNCALLS) {
112+
CallTraces.traceDowncall(dat);
113113
}
114114
HANDLE.invokeExact(dat);
115115
} catch (Throwable ex$) {
@@ -146,8 +146,8 @@ final class DataImportTests {
146146
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
147147
public static void call(java.lang.foreign.MemorySegment _result) {
148148
try {
149-
if (SwiftRuntime.TRACE_DOWNCALLS) {
150-
SwiftRuntime.traceDowncall(_result);
149+
if (CallTraces.TRACE_DOWNCALLS) {
150+
CallTraces.traceDowncall(_result);
151151
}
152152
HANDLE.invokeExact(_result);
153153
} catch (Throwable ex$) {
@@ -189,8 +189,8 @@ final class DataImportTests {
189189
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
190190
public static void call(java.lang.foreign.MemorySegment bytes, long count, java.lang.foreign.MemorySegment _result) {
191191
try {
192-
if (SwiftRuntime.TRACE_DOWNCALLS) {
193-
SwiftRuntime.traceDowncall(bytes, count, _result);
192+
if (CallTraces.TRACE_DOWNCALLS) {
193+
CallTraces.traceDowncall(bytes, count, _result);
194194
}
195195
HANDLE.invokeExact(bytes, count, _result);
196196
} catch (Throwable ex$) {
@@ -230,8 +230,8 @@ final class DataImportTests {
230230
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
231231
public static long call(java.lang.foreign.MemorySegment self) {
232232
try {
233-
if (SwiftRuntime.TRACE_DOWNCALLS) {
234-
SwiftRuntime.traceDowncall(self);
233+
if (CallTraces.TRACE_DOWNCALLS) {
234+
CallTraces.traceDowncall(self);
235235
}
236236
return (long) HANDLE.invokeExact(self);
237237
} catch (Throwable ex$) {
@@ -270,8 +270,8 @@ final class DataImportTests {
270270
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
271271
public static void call(java.lang.foreign.MemorySegment body, java.lang.foreign.MemorySegment self) {
272272
try {
273-
if (SwiftRuntime.TRACE_DOWNCALLS) {
274-
SwiftRuntime.traceDowncall(body, self);
273+
if (CallTraces.TRACE_DOWNCALLS) {
274+
CallTraces.traceDowncall(body, self);
275275
}
276276
HANDLE.invokeExact(body, self);
277277
} catch (Throwable ex$) {
@@ -377,8 +377,8 @@ final class DataImportTests {
377377
private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
378378
public static void call(java.lang.foreign.MemorySegment dat) {
379379
try {
380-
if (SwiftRuntime.TRACE_DOWNCALLS) {
381-
SwiftRuntime.traceDowncall(dat);
380+
if (CallTraces.TRACE_DOWNCALLS) {
381+
CallTraces.traceDowncall(dat);
382382
}
383383
HANDLE.invokeExact(dat);
384384
} catch (Throwable ex$) {

0 commit comments

Comments
 (0)