Skip to content

Commit 7f6e3d8

Browse files
Reduce memory store for returned value kind
1 parent d684978 commit 7f6e3d8

File tree

6 files changed

+77
-28
lines changed

6 files changed

+77
-28
lines changed

Runtime/src/index.ts

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -237,35 +237,24 @@ export class SwiftRuntime {
237237
ref: ref,
238238
argv: pointer,
239239
argc: number,
240-
kind_ptr: pointer,
241240
payload1_ptr: pointer,
242241
payload2_ptr: pointer
243242
) => {
244243
const func = this.memory.getObject(ref);
244+
let result = undefined;
245245
let isException = true;
246246
try {
247247
const args = JSValue.decodeArray(argv, argc, this.memory);
248-
const result = func(...args);
249-
JSValue.write(
248+
result = func(...args);
249+
isException = false;
250+
} finally {
251+
return JSValue.writeV2(
250252
result,
251-
kind_ptr,
252253
payload1_ptr,
253254
payload2_ptr,
254-
false,
255+
isException,
255256
this.memory
256257
);
257-
isException = false;
258-
} finally {
259-
if (isException) {
260-
JSValue.write(
261-
undefined,
262-
kind_ptr,
263-
payload1_ptr,
264-
payload2_ptr,
265-
true,
266-
this.memory
267-
);
268-
}
269258
}
270259
},
271260

Runtime/src/js-value.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Memory } from "./memory.js";
2-
import { assertNever, pointer } from "./types.js";
2+
import { assertNever, JavaScriptValueKindAndFlags, pointer } from "./types.js";
33

44
export const enum Kind {
55
Boolean = 0,
@@ -121,3 +121,59 @@ export const write = (
121121
assertNever(type, `Type "${type}" is not supported yet`);
122122
}
123123
};
124+
125+
126+
export const writeV2 = (
127+
value: any,
128+
payload1_ptr: pointer,
129+
payload2_ptr: pointer,
130+
is_exception: boolean,
131+
memory: Memory
132+
): JavaScriptValueKindAndFlags => {
133+
if (value === undefined) {
134+
return Kind.Undefined;
135+
}
136+
137+
const exceptionBit = (is_exception ? 1 : 0) << 31;
138+
if (value === null) {
139+
return exceptionBit | Kind.Null;
140+
}
141+
142+
const writeRef = (kind: Kind) => {
143+
memory.writeUint32(payload1_ptr, memory.retain(value));
144+
return exceptionBit | kind
145+
};
146+
147+
const type = typeof value;
148+
switch (type) {
149+
case "boolean": {
150+
memory.writeUint32(payload1_ptr, value ? 1 : 0);
151+
return exceptionBit | Kind.Boolean;
152+
}
153+
case "number": {
154+
memory.writeFloat64(payload2_ptr, value);
155+
return exceptionBit | Kind.Number;
156+
}
157+
case "string": {
158+
return writeRef(Kind.String);
159+
}
160+
case "undefined": {
161+
return exceptionBit | Kind.Undefined;
162+
}
163+
case "object": {
164+
return writeRef(Kind.Object);
165+
}
166+
case "function": {
167+
return writeRef(Kind.Function);
168+
}
169+
case "symbol": {
170+
return writeRef(Kind.Symbol);
171+
}
172+
case "bigint": {
173+
return writeRef(Kind.BigInt);
174+
}
175+
default:
176+
assertNever(type, `Type "${type}" is not supported yet`);
177+
}
178+
throw new Error("Unreachable");
179+
};

Runtime/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as JSValue from "./js-value.js";
33
export type ref = number;
44
export type pointer = number;
55
export type bool = number;
6+
export type JavaScriptValueKindAndFlags = number;
67

78
export interface ExportedFunctions {
89
swjs_library_version(): number;
@@ -63,10 +64,9 @@ export interface ImportedFunctions {
6364
ref: number,
6465
argv: pointer,
6566
argc: number,
66-
kind_ptr: pointer,
6767
payload1_ptr: pointer,
6868
payload2_ptr: pointer
69-
): void;
69+
): JavaScriptValueKindAndFlags;
7070
swjs_call_function_with_this(
7171
obj_ref: ref,
7272
func_ref: ref,

Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,11 @@ func invokeNonThrowingJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleTo
9696
jsFunc.id, argv, Int32(argc),
9797
&kindAndFlags, &payload1, &payload2)
9898
} else {
99-
_call_function_no_catch(
99+
let result = _call_function_no_catch(
100100
jsFunc.id, argv, Int32(argc),
101-
&kindAndFlags, &payload1, &payload2
101+
&payload1, &payload2
102102
)
103+
kindAndFlags = unsafeBitCast(result, to: JavaScriptValueKindAndFlags.self)
103104
}
104105
assert(!kindAndFlags.isException)
105106
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)

Sources/JavaScriptKit/XcodeSupport.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,9 @@ import _CJavaScriptKit
5959
func _call_function_no_catch(
6060
_: JavaScriptObjectRef,
6161
_: UnsafePointer<RawJSValue>!, _: Int32,
62-
_: UnsafeMutablePointer<JavaScriptValueKindAndFlags>!,
6362
_: UnsafeMutablePointer<JavaScriptPayload1>!,
6463
_: UnsafeMutablePointer<JavaScriptPayload2>!
65-
) { fatalError() }
64+
) -> UInt32 { fatalError() }
6665
func _call_function_with_this(
6766
_: JavaScriptObjectRef,
6867
_: JavaScriptObjectRef,

Sources/_CJavaScriptKit/include/_CJavaScriptKit.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <stdlib.h>
55
#include <stdbool.h>
6+
#include <stdint.h>
67

78
/// `JavaScriptObjectRef` represents JavaScript object reference that is referenced by Swift side.
89
/// This value is an address of `SwiftRuntimeHeap`.
@@ -193,12 +194,15 @@ extern void _call_function(const JavaScriptObjectRef ref, const RawJSValue *argv
193194
/// @param result_kind A result pointer of JavaScript value kind of returned result or thrown exception.
194195
/// @param result_payload1 A result pointer of first payload of JavaScript value of returned result or thrown exception.
195196
/// @param result_payload2 A result pointer of second payload of JavaScript value of returned result or thrown exception.
197+
/// @return A JavaScriptValueKindAndFlags bits represented as 32bit integer for the returned value.
196198
__attribute__((__import_module__("javascript_kit"),
197199
__import_name__("swjs_call_function_no_catch")))
198-
extern void _call_function_no_catch(const JavaScriptObjectRef ref, const RawJSValue *argv,
199-
const int argc, JavaScriptValueKindAndFlags *result_kind,
200-
JavaScriptPayload1 *result_payload1,
201-
JavaScriptPayload2 *result_payload2);
200+
extern uint32_t _call_function_no_catch(
201+
const JavaScriptObjectRef ref, const RawJSValue *argv,
202+
const int argc,
203+
JavaScriptPayload1 *result_payload1,
204+
JavaScriptPayload2 *result_payload2
205+
);
202206

203207
/// `_call_function_with_this` calls JavaScript function with given arguments list and given `_this`.
204208
///

0 commit comments

Comments
 (0)