Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Int64/UInt64 to Bigint slow conversion #204

Merged
merged 1 commit into from
Aug 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions IntegrationTests/TestSuites/Sources/PrimaryTests/I64.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ func testI64() throws {
func expectPassesThrough(signed value: Int64) throws {
let bigInt = JSBigInt(value)
try expectEqual(bigInt.description, value.description)
let bigInt2 = JSBigInt(_slowBridge: value)
try expectEqual(bigInt2.description, value.description)
}

func expectPassesThrough(unsigned value: UInt64) throws {
let bigInt = JSBigInt(unsigned: value)
try expectEqual(bigInt.description, value.description)
let bigInt2 = JSBigInt(_slowBridge: value)
try expectEqual(bigInt2.description, value.description)
}

try expectPassesThrough(signed: 0)
Expand Down
25 changes: 22 additions & 3 deletions Runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ export class SwiftRuntime {
return this._closureDeallocator;
}

private callHostFunction(host_func_id: number, line: number, file: string, args: any[]) {
private callHostFunction(
host_func_id: number,
line: number,
file: string,
args: any[]
) {
const argc = args.length;
const argv = this.exports.swjs_prepare_host_function_call(argc);
for (let index = 0; index < args.length; index++) {
Expand All @@ -103,7 +108,9 @@ export class SwiftRuntime {
callback_func_ref
);
if (alreadyReleased) {
throw new Error(`The JSClosure has been already released by Swift side. The closure is created at ${file}:${line}`);
throw new Error(
`The JSClosure has been already released by Swift side. The closure is created at ${file}:${line}`
);
}
this.exports.swjs_cleanup_host_function_call(argv);
return output;
Expand Down Expand Up @@ -382,7 +389,11 @@ export class SwiftRuntime {
return obj instanceof constructor;
},

swjs_create_function: (host_func_id: number, line: number, file: ref) => {
swjs_create_function: (
host_func_id: number,
line: number,
file: ref
) => {
const fileString = this.memory.getObject(file) as string;
const func = (...args: any[]) =>
this.callHostFunction(host_func_id, line, fileString, args);
Expand Down Expand Up @@ -436,5 +447,13 @@ export class SwiftRuntime {
return BigInt.asIntN(64, object);
}
},
swjs_i64_to_bigint_slow: (lower, upper, signed) => {
const value =
BigInt.asUintN(32, BigInt(lower)) +
(BigInt.asUintN(32, BigInt(upper)) << BigInt(32));
return this.memory.retain(
signed ? BigInt.asIntN(64, value) : BigInt.asUintN(64, value)
);
},
};
}
1 change: 1 addition & 0 deletions Runtime/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export interface ImportedFunctions {
swjs_release(ref: number): void;
swjs_i64_to_bigint(value: bigint, signed: bool): ref;
swjs_bigint_to_i64(ref: ref, signed: bool): bigint;
swjs_i64_to_bigint_slow(lower: number, upper: number, signed: bool): ref;
}

export const enum LibraryFeatures {
Expand Down
13 changes: 13 additions & 0 deletions Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ public final class JSBigInt: JSObject {
override public init(id: JavaScriptObjectRef) {
super.init(id: id)
}

/// Instantiate a new `JSBigInt` with given Int64 value in a slow path
/// This doesn't require [JS-BigInt-integration](https://github.com/WebAssembly/JS-BigInt-integration) feature.
public init(_slowBridge value: Int64) {
let value = UInt64(bitPattern: value)
super.init(id: _i64_to_bigint_slow(UInt32(value & 0xffffffff), UInt32(value >> 32), true))
}

/// Instantiate a new `JSBigInt` with given UInt64 value in a slow path
/// This doesn't require [JS-BigInt-integration](https://github.com/WebAssembly/JS-BigInt-integration) feature.
public init(_slowBridge value: UInt64) {
super.init(id: _i64_to_bigint_slow(UInt32(value & 0xffffffff), UInt32(value >> 32), false))
}

override public class func construct(from value: JSValue) -> Self? {
value.bigInt as? Self
Expand Down
5 changes: 5 additions & 0 deletions Sources/JavaScriptKit/Runtime/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Sources/JavaScriptKit/Runtime/index.mjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Sources/JavaScriptKit/XcodeSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ import _CJavaScriptKit
_: JavaScriptObjectRef,
_: UnsafeMutablePointer<UInt8>!
) { fatalError() }
func _i64_to_bigint_slow(
_: UInt32, _: UInt32, _: Bool
) -> JavaScriptObjectRef { fatalError() }
func _call_function(
_: JavaScriptObjectRef,
_: UnsafePointer<RawJSValue>!, _: Int32,
Expand Down
10 changes: 10 additions & 0 deletions Sources/_CJavaScriptKit/include/_CJavaScriptKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,16 @@ __attribute__((__import_module__("javascript_kit"),
__import_name__("swjs_load_string")))
extern void _load_string(const JavaScriptObjectRef bytes, unsigned char *buffer);

/// Converts the provided Int64 or UInt64 to a BigInt in slow path by splitting 64bit integer to two 32bit integers
/// to avoid depending on [JS-BigInt-integration](https://github.com/WebAssembly/JS-BigInt-integration) feature
///
/// @param lower The lower 32bit of the value to convert.
/// @param upper The upper 32bit of the value to convert.
/// @param is_signed Whether to treat the value as a signed integer or not.
__attribute__((__import_module__("javascript_kit"),
__import_name__("swjs_i64_to_bigint_slow")))
extern JavaScriptObjectRef _i64_to_bigint_slow(unsigned int lower, unsigned int upper, bool is_signed);

/// `_call_function` calls JavaScript function with given arguments list.
///
/// @param ref The target JavaScript function to call.
Expand Down