Skip to content

Runtime Performance Optimization #207

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

Merged
merged 20 commits into from
Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8d17f5c
Allocate function call argument buffer on stack
kateinoigakukun Aug 16, 2022
d684978
Revert "Allocate function call argument buffer on stack"
kateinoigakukun Aug 16, 2022
7f6e3d8
Reduce memory store for returned value kind
kateinoigakukun Aug 16, 2022
50fd47b
Add NODEJS_FLAGS to perform profiling by passing --prof
kateinoigakukun Aug 16, 2022
4f850a0
Revert "Revert "Allocate function call argument buffer on stack""
kateinoigakukun Aug 16, 2022
e66296f
Revert "Revert "Revert "Allocate function call argument buffer on sta…
kateinoigakukun Aug 16, 2022
0f53ca5
Reduce retain/release dance caused by Optional<this>
kateinoigakukun Aug 16, 2022
adfe1e8
Don't escape JSFunction self
kateinoigakukun Aug 16, 2022
78b442d
Add fast path for empty JSValue array
kateinoigakukun Aug 16, 2022
bffe009
Skip re-creating DataView in decodeArray
kateinoigakukun Aug 16, 2022
2a8146b
make regenerate_swiftpm_resources
kateinoigakukun Aug 16, 2022
43d9a2a
Apply the same techniques to call families
kateinoigakukun Aug 17, 2022
2b86b41
Reuse DataView as much as possible
kateinoigakukun Aug 17, 2022
5a3ecf2
npm run format
kateinoigakukun Aug 17, 2022
8184119
Optimize swjs_get_prop to reduce memory store
kateinoigakukun Aug 18, 2022
a1b690e
Optimize _get_subscript to reduce memory store
kateinoigakukun Aug 18, 2022
4110f7f
Rename writeV2 -> writeAndReturnKindBits
kateinoigakukun Aug 18, 2022
d4c45b4
Improve doc comment style
kateinoigakukun Aug 18, 2022
7532e6a
Use writeAndReturnKindBits in write
kateinoigakukun Aug 18, 2022
a9843ee
Add rationale comments for write
kateinoigakukun Aug 18, 2022
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
3 changes: 2 additions & 1 deletion IntegrationTests/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
CONFIGURATION ?= debug
SWIFT_BUILD_FLAGS ?=
NODEJS_FLAGS ?=

NODEJS = node --experimental-wasi-unstable-preview1
NODEJS = node --experimental-wasi-unstable-preview1 $(NODEJS_FLAGS)

FORCE:
TestSuites/.build/$(CONFIGURATION)/%.wasm: FORCE
Expand Down
190 changes: 77 additions & 113 deletions Runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,15 @@ export class SwiftRuntime {
) {
const argc = args.length;
const argv = this.exports.swjs_prepare_host_function_call(argc);
const memory = this.memory;
for (let index = 0; index < args.length; index++) {
const argument = args[index];
const base = argv + 16 * index;
JSValue.write(
argument,
base,
base + 4,
base + 8,
false,
this.memory
);
JSValue.write(argument, base, base + 4, base + 8, false, memory);
}
let output: any;
// This ref is released by the swjs_call_host_function implementation
const callback_func_ref = this.memory.retain((result: any) => {
const callback_func_ref = memory.retain((result: any) => {
output = result;
});
const alreadyReleased = this.exports.swjs_call_host_function(
Expand Down Expand Up @@ -127,28 +121,28 @@ export class SwiftRuntime {
payload1: number,
payload2: number
) => {
const obj = this.memory.getObject(ref);
const key = this.memory.getObject(name);
const value = JSValue.decode(kind, payload1, payload2, this.memory);
const memory = this.memory;
const obj = memory.getObject(ref);
const key = memory.getObject(name);
const value = JSValue.decode(kind, payload1, payload2, memory);
obj[key] = value;
},
swjs_get_prop: (
ref: ref,
name: ref,
kind_ptr: pointer,
payload1_ptr: pointer,
payload2_ptr: pointer
) => {
const obj = this.memory.getObject(ref);
const key = this.memory.getObject(name);
const memory = this.memory;
const obj = memory.getObject(ref);
const key = memory.getObject(name);
const result = obj[key];
JSValue.write(
return JSValue.writeV2(
result,
kind_ptr,
payload1_ptr,
payload2_ptr,
false,
this.memory
memory
);
},

Expand All @@ -159,22 +153,21 @@ export class SwiftRuntime {
payload1: number,
payload2: number
) => {
const obj = this.memory.getObject(ref);
const value = JSValue.decode(kind, payload1, payload2, this.memory);
const memory = this.memory;
const obj = memory.getObject(ref);
const value = JSValue.decode(kind, payload1, payload2, memory);
obj[index] = value;
},
swjs_get_subscript: (
ref: ref,
index: number,
kind_ptr: pointer,
payload1_ptr: pointer,
payload2_ptr: pointer
) => {
const obj = this.memory.getObject(ref);
const result = obj[index];
JSValue.write(
return JSValue.writeV2(
result,
kind_ptr,
payload1_ptr,
payload2_ptr,
false,
Expand All @@ -183,50 +176,50 @@ export class SwiftRuntime {
},

swjs_encode_string: (ref: ref, bytes_ptr_result: pointer) => {
const bytes = this.textEncoder.encode(this.memory.getObject(ref));
const bytes_ptr = this.memory.retain(bytes);
this.memory.writeUint32(bytes_ptr_result, bytes_ptr);
const memory = this.memory;
const bytes = this.textEncoder.encode(memory.getObject(ref));
const bytes_ptr = memory.retain(bytes);
memory.writeUint32(bytes_ptr_result, bytes_ptr);
return bytes.length;
},
swjs_decode_string: (bytes_ptr: pointer, length: number) => {
const bytes = this.memory
const memory = this.memory;
const bytes = memory
.bytes()
.subarray(bytes_ptr, bytes_ptr + length);
const string = this.textDecoder.decode(bytes);
return this.memory.retain(string);
return memory.retain(string);
},
swjs_load_string: (ref: ref, buffer: pointer) => {
const bytes = this.memory.getObject(ref);
this.memory.writeBytes(buffer, bytes);
const memory = this.memory;
const bytes = memory.getObject(ref);
memory.writeBytes(buffer, bytes);
},

swjs_call_function: (
ref: ref,
argv: pointer,
argc: number,
kind_ptr: pointer,
payload1_ptr: pointer,
payload2_ptr: pointer
) => {
const func = this.memory.getObject(ref);
let result: any;
const memory = this.memory;
const func = memory.getObject(ref);
let result = undefined;
try {
const args = JSValue.decodeArray(argv, argc, this.memory);
const args = JSValue.decodeArray(argv, argc, memory);
result = func(...args);
} catch (error) {
JSValue.write(
return JSValue.writeV2(
error,
kind_ptr,
payload1_ptr,
payload2_ptr,
true,
this.memory
);
return;
}
JSValue.write(
return JSValue.writeV2(
result,
kind_ptr,
payload1_ptr,
payload2_ptr,
false,
Expand All @@ -237,67 +230,48 @@ export class SwiftRuntime {
ref: ref,
argv: pointer,
argc: number,
kind_ptr: pointer,
payload1_ptr: pointer,
payload2_ptr: pointer
) => {
const func = this.memory.getObject(ref);
let isException = true;
try {
const args = JSValue.decodeArray(argv, argc, this.memory);
const result = func(...args);
JSValue.write(
result,
kind_ptr,
payload1_ptr,
payload2_ptr,
false,
this.memory
);
isException = false;
} finally {
if (isException) {
JSValue.write(
undefined,
kind_ptr,
payload1_ptr,
payload2_ptr,
true,
this.memory
);
}
}
const memory = this.memory;
const func = memory.getObject(ref);
const args = JSValue.decodeArray(argv, argc, memory);
const result = func(...args);
return JSValue.writeV2(
result,
payload1_ptr,
payload2_ptr,
false,
this.memory
);
},

swjs_call_function_with_this: (
obj_ref: ref,
func_ref: ref,
argv: pointer,
argc: number,
kind_ptr: pointer,
payload1_ptr: pointer,
payload2_ptr: pointer
) => {
const obj = this.memory.getObject(obj_ref);
const func = this.memory.getObject(func_ref);
const memory = this.memory;
const obj = memory.getObject(obj_ref);
const func = memory.getObject(func_ref);
let result: any;
try {
const args = JSValue.decodeArray(argv, argc, this.memory);
const args = JSValue.decodeArray(argv, argc, memory);
result = func.apply(obj, args);
} catch (error) {
JSValue.write(
return JSValue.writeV2(
error,
kind_ptr,
payload1_ptr,
payload2_ptr,
true,
this.memory
);
return;
}
JSValue.write(
return JSValue.writeV2(
result,
kind_ptr,
payload1_ptr,
payload2_ptr,
false,
Expand All @@ -309,42 +283,28 @@ export class SwiftRuntime {
func_ref: ref,
argv: pointer,
argc: number,
kind_ptr: pointer,
payload1_ptr: pointer,
payload2_ptr: pointer
) => {
const obj = this.memory.getObject(obj_ref);
const func = this.memory.getObject(func_ref);
let isException = true;
try {
const args = JSValue.decodeArray(argv, argc, this.memory);
const result = func.apply(obj, args);
JSValue.write(
result,
kind_ptr,
payload1_ptr,
payload2_ptr,
false,
this.memory
);
isException = false;
} finally {
if (isException) {
JSValue.write(
undefined,
kind_ptr,
payload1_ptr,
payload2_ptr,
true,
this.memory
);
}
}
const memory = this.memory;
const obj = memory.getObject(obj_ref);
const func = memory.getObject(func_ref);
let result = undefined;
const args = JSValue.decodeArray(argv, argc, memory);
result = func.apply(obj, args);
return JSValue.writeV2(
result,
payload1_ptr,
payload2_ptr,
false,
this.memory
);
},

swjs_call_new: (ref: ref, argv: pointer, argc: number) => {
const constructor = this.memory.getObject(ref);
const args = JSValue.decodeArray(argv, argc, this.memory);
const memory = this.memory;
const constructor = memory.getObject(ref);
const args = JSValue.decodeArray(argv, argc, memory);
const instance = new constructor(...args);
return this.memory.retain(instance);
},
Expand All @@ -356,10 +316,11 @@ export class SwiftRuntime {
exception_payload1_ptr: pointer,
exception_payload2_ptr: pointer
) => {
const constructor = this.memory.getObject(ref);
let memory = this.memory;
const constructor = memory.getObject(ref);
let result: any;
try {
const args = JSValue.decodeArray(argv, argc, this.memory);
const args = JSValue.decodeArray(argv, argc, memory);
result = new constructor(...args);
} catch (error) {
JSValue.write(
Expand All @@ -372,20 +333,22 @@ export class SwiftRuntime {
);
return -1;
}
memory = this.memory;
JSValue.write(
null,
exception_kind_ptr,
exception_payload1_ptr,
exception_payload2_ptr,
false,
this.memory
memory
);
return this.memory.retain(result);
return memory.retain(result);
},

swjs_instanceof: (obj_ref: ref, constructor_ref: ref) => {
const obj = this.memory.getObject(obj_ref);
const constructor = this.memory.getObject(constructor_ref);
const memory = this.memory;
const obj = memory.getObject(obj_ref);
const constructor = memory.getObject(constructor_ref);
return obj instanceof constructor;
},

Expand Down Expand Up @@ -419,9 +382,10 @@ export class SwiftRuntime {
},

swjs_load_typed_array: (ref: ref, buffer: pointer) => {
const typedArray = this.memory.getObject(ref);
const memory = this.memory;
const typedArray = memory.getObject(ref);
const bytes = new Uint8Array(typedArray.buffer);
this.memory.writeBytes(buffer, bytes);
memory.writeBytes(buffer, bytes);
},

swjs_release: (ref: ref) => {
Expand Down
Loading