Skip to content

Commit de061e2

Browse files
Add Int64/UInt64 to Bigint slow conversion
1 parent 8478665 commit de061e2

File tree

6 files changed

+53
-3
lines changed

6 files changed

+53
-3
lines changed

IntegrationTests/TestSuites/Sources/PrimaryTests/I64.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ func testI64() throws {
66
func expectPassesThrough(signed value: Int64) throws {
77
let bigInt = JSBigInt(value)
88
try expectEqual(bigInt.description, value.description)
9+
let bigInt2 = JSBigInt(_slowBridge: value)
10+
try expectEqual(bigInt2.description, value.description)
911
}
1012

1113
func expectPassesThrough(unsigned value: UInt64) throws {
1214
let bigInt = JSBigInt(unsigned: value)
1315
try expectEqual(bigInt.description, value.description)
16+
let bigInt2 = JSBigInt(_slowBridge: value)
17+
try expectEqual(bigInt2.description, value.description)
1418
}
1519

1620
try expectPassesThrough(signed: 0)

Runtime/src/index.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,12 @@ export class SwiftRuntime {
7676
return this._closureDeallocator;
7777
}
7878

79-
private callHostFunction(host_func_id: number, line: number, file: string, args: any[]) {
79+
private callHostFunction(
80+
host_func_id: number,
81+
line: number,
82+
file: string,
83+
args: any[]
84+
) {
8085
const argc = args.length;
8186
const argv = this.exports.swjs_prepare_host_function_call(argc);
8287
for (let index = 0; index < args.length; index++) {
@@ -103,7 +108,9 @@ export class SwiftRuntime {
103108
callback_func_ref
104109
);
105110
if (alreadyReleased) {
106-
throw new Error(`The JSClosure has been already released by Swift side. The closure is created at ${file}:${line}`);
111+
throw new Error(
112+
`The JSClosure has been already released by Swift side. The closure is created at ${file}:${line}`
113+
);
107114
}
108115
this.exports.swjs_cleanup_host_function_call(argv);
109116
return output;
@@ -382,7 +389,11 @@ export class SwiftRuntime {
382389
return obj instanceof constructor;
383390
},
384391

385-
swjs_create_function: (host_func_id: number, line: number, file: ref) => {
392+
swjs_create_function: (
393+
host_func_id: number,
394+
line: number,
395+
file: ref
396+
) => {
386397
const fileString = this.memory.getObject(file) as string;
387398
const func = (...args: any[]) =>
388399
this.callHostFunction(host_func_id, line, fileString, args);
@@ -436,5 +447,13 @@ export class SwiftRuntime {
436447
return BigInt.asIntN(64, object);
437448
}
438449
},
450+
swjs_i64_to_bigint_slow: (lower, upper, signed) => {
451+
const value =
452+
BigInt.asUintN(32, BigInt(lower)) +
453+
(BigInt.asUintN(32, BigInt(upper)) << BigInt(32));
454+
return this.memory.retain(
455+
signed ? BigInt.asIntN(64, value) : BigInt.asUintN(64, value)
456+
);
457+
},
439458
};
440459
}

Runtime/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export interface ImportedFunctions {
105105
swjs_release(ref: number): void;
106106
swjs_i64_to_bigint(value: bigint, signed: bool): ref;
107107
swjs_bigint_to_i64(ref: ref, signed: bool): bigint;
108+
swjs_i64_to_bigint_slow(lower: number, upper: number, signed: bool): ref;
108109
}
109110

110111
export const enum LibraryFeatures {

Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ public final class JSBigInt: JSObject {
77
override public init(id: JavaScriptObjectRef) {
88
super.init(id: id)
99
}
10+
11+
/// Instantiate a new `JSBigInt` with given Int64 value in a slow path
12+
/// This doesn't require [JS-BigInt-integration](https://github.com/WebAssembly/JS-BigInt-integration) feature.
13+
public init(_slowBridge value: Int64) {
14+
let value = UInt64(bitPattern: value)
15+
super.init(id: _i64_to_bigint_slow(UInt32(value & 0xffffffff), UInt32(value >> 32), true))
16+
}
17+
18+
/// Instantiate a new `JSBigInt` with given UInt64 value in a slow path
19+
/// This doesn't require [JS-BigInt-integration](https://github.com/WebAssembly/JS-BigInt-integration) feature.
20+
public init(_slowBridge value: UInt64) {
21+
super.init(id: _i64_to_bigint_slow(UInt32(value & 0xffffffff), UInt32(value >> 32), false))
22+
}
1023

1124
override public class func construct(from value: JSValue) -> Self? {
1225
value.bigInt as? Self

Sources/JavaScriptKit/XcodeSupport.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ import _CJavaScriptKit
4646
_: JavaScriptObjectRef,
4747
_: UnsafeMutablePointer<UInt8>!
4848
) { fatalError() }
49+
func _i64_to_bigint_slow(
50+
_: UInt32, _: UInt32, _: Bool
51+
) -> JavaScriptObjectRef { fatalError() }
4952
func _call_function(
5053
_: JavaScriptObjectRef,
5154
_: UnsafePointer<RawJSValue>!, _: Int32,

Sources/_CJavaScriptKit/include/_CJavaScriptKit.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ __attribute__((__import_module__("javascript_kit"),
160160
__import_name__("swjs_load_string")))
161161
extern void _load_string(const JavaScriptObjectRef bytes, unsigned char *buffer);
162162

163+
/// Converts the provided Int64 or UInt64 to a BigInt in slow path by splitting 64bit integer to two 32bit integers
164+
/// to avoid depending on [JS-BigInt-integration](https://github.com/WebAssembly/JS-BigInt-integration) feature
165+
///
166+
/// @param lower The lower 32bit of the value to convert.
167+
/// @param upper The upper 32bit of the value to convert.
168+
/// @param is_signed Whether to treat the value as a signed integer or not.
169+
__attribute__((__import_module__("javascript_kit"),
170+
__import_name__("swjs_i64_to_bigint_slow")))
171+
extern JavaScriptObjectRef _i64_to_bigint_slow(unsigned int lower, unsigned int upper, bool is_signed);
172+
163173
/// `_call_function` calls JavaScript function with given arguments list.
164174
///
165175
/// @param ref The target JavaScript function to call.

0 commit comments

Comments
 (0)