Skip to content

Commit 1afbfaf

Browse files
authoredAug 18, 2022
Runtime Performance Optimization (#207)
* Allocate function call argument buffer on stack * Revert "Allocate function call argument buffer on stack" This reverts commit 8d17f5c. * Reduce memory store for returned value kind * Add NODEJS_FLAGS to perform profiling by passing --prof * Revert "Revert "Allocate function call argument buffer on stack"" This reverts commit d684978. * Revert "Revert "Revert "Allocate function call argument buffer on stack""" This reverts commit 4f850a0. * Reduce retain/release dance caused by Optional<this> * Don't escape JSFunction self * Add fast path for empty JSValue array * Skip re-creating DataView in decodeArray * make regenerate_swiftpm_resources * Apply the same techniques to call families * Reuse DataView as much as possible * npm run format * Optimize swjs_get_prop to reduce memory store * Optimize _get_subscript to reduce memory store * Rename writeV2 -> writeAndReturnKindBits * Improve doc comment style * Use writeAndReturnKindBits in write * Add rationale comments for write
1 parent 24a5698 commit 1afbfaf

File tree

13 files changed

+456
-426
lines changed

13 files changed

+456
-426
lines changed
 

Diff for: ‎IntegrationTests/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
CONFIGURATION ?= debug
22
SWIFT_BUILD_FLAGS ?=
3+
NODEJS_FLAGS ?=
34

4-
NODEJS = node --experimental-wasi-unstable-preview1
5+
NODEJS = node --experimental-wasi-unstable-preview1 $(NODEJS_FLAGS)
56

67
FORCE:
78
TestSuites/.build/$(CONFIGURATION)/%.wasm: FORCE

Diff for: ‎Runtime/src/index.ts

+77-113
Original file line numberDiff line numberDiff line change
@@ -84,21 +84,15 @@ export class SwiftRuntime {
8484
) {
8585
const argc = args.length;
8686
const argv = this.exports.swjs_prepare_host_function_call(argc);
87+
const memory = this.memory;
8788
for (let index = 0; index < args.length; index++) {
8889
const argument = args[index];
8990
const base = argv + 16 * index;
90-
JSValue.write(
91-
argument,
92-
base,
93-
base + 4,
94-
base + 8,
95-
false,
96-
this.memory
97-
);
91+
JSValue.write(argument, base, base + 4, base + 8, false, memory);
9892
}
9993
let output: any;
10094
// This ref is released by the swjs_call_host_function implementation
101-
const callback_func_ref = this.memory.retain((result: any) => {
95+
const callback_func_ref = memory.retain((result: any) => {
10296
output = result;
10397
});
10498
const alreadyReleased = this.exports.swjs_call_host_function(
@@ -127,28 +121,28 @@ export class SwiftRuntime {
127121
payload1: number,
128122
payload2: number
129123
) => {
130-
const obj = this.memory.getObject(ref);
131-
const key = this.memory.getObject(name);
132-
const value = JSValue.decode(kind, payload1, payload2, this.memory);
124+
const memory = this.memory;
125+
const obj = memory.getObject(ref);
126+
const key = memory.getObject(name);
127+
const value = JSValue.decode(kind, payload1, payload2, memory);
133128
obj[key] = value;
134129
},
135130
swjs_get_prop: (
136131
ref: ref,
137132
name: ref,
138-
kind_ptr: pointer,
139133
payload1_ptr: pointer,
140134
payload2_ptr: pointer
141135
) => {
142-
const obj = this.memory.getObject(ref);
143-
const key = this.memory.getObject(name);
136+
const memory = this.memory;
137+
const obj = memory.getObject(ref);
138+
const key = memory.getObject(name);
144139
const result = obj[key];
145-
JSValue.write(
140+
return JSValue.writeAndReturnKindBits(
146141
result,
147-
kind_ptr,
148142
payload1_ptr,
149143
payload2_ptr,
150144
false,
151-
this.memory
145+
memory
152146
);
153147
},
154148

@@ -159,22 +153,21 @@ export class SwiftRuntime {
159153
payload1: number,
160154
payload2: number
161155
) => {
162-
const obj = this.memory.getObject(ref);
163-
const value = JSValue.decode(kind, payload1, payload2, this.memory);
156+
const memory = this.memory;
157+
const obj = memory.getObject(ref);
158+
const value = JSValue.decode(kind, payload1, payload2, memory);
164159
obj[index] = value;
165160
},
166161
swjs_get_subscript: (
167162
ref: ref,
168163
index: number,
169-
kind_ptr: pointer,
170164
payload1_ptr: pointer,
171165
payload2_ptr: pointer
172166
) => {
173167
const obj = this.memory.getObject(ref);
174168
const result = obj[index];
175-
JSValue.write(
169+
return JSValue.writeAndReturnKindBits(
176170
result,
177-
kind_ptr,
178171
payload1_ptr,
179172
payload2_ptr,
180173
false,
@@ -183,50 +176,50 @@ export class SwiftRuntime {
183176
},
184177

185178
swjs_encode_string: (ref: ref, bytes_ptr_result: pointer) => {
186-
const bytes = this.textEncoder.encode(this.memory.getObject(ref));
187-
const bytes_ptr = this.memory.retain(bytes);
188-
this.memory.writeUint32(bytes_ptr_result, bytes_ptr);
179+
const memory = this.memory;
180+
const bytes = this.textEncoder.encode(memory.getObject(ref));
181+
const bytes_ptr = memory.retain(bytes);
182+
memory.writeUint32(bytes_ptr_result, bytes_ptr);
189183
return bytes.length;
190184
},
191185
swjs_decode_string: (bytes_ptr: pointer, length: number) => {
192-
const bytes = this.memory
186+
const memory = this.memory;
187+
const bytes = memory
193188
.bytes()
194189
.subarray(bytes_ptr, bytes_ptr + length);
195190
const string = this.textDecoder.decode(bytes);
196-
return this.memory.retain(string);
191+
return memory.retain(string);
197192
},
198193
swjs_load_string: (ref: ref, buffer: pointer) => {
199-
const bytes = this.memory.getObject(ref);
200-
this.memory.writeBytes(buffer, bytes);
194+
const memory = this.memory;
195+
const bytes = memory.getObject(ref);
196+
memory.writeBytes(buffer, bytes);
201197
},
202198

203199
swjs_call_function: (
204200
ref: ref,
205201
argv: pointer,
206202
argc: number,
207-
kind_ptr: pointer,
208203
payload1_ptr: pointer,
209204
payload2_ptr: pointer
210205
) => {
211-
const func = this.memory.getObject(ref);
212-
let result: any;
206+
const memory = this.memory;
207+
const func = memory.getObject(ref);
208+
let result = undefined;
213209
try {
214-
const args = JSValue.decodeArray(argv, argc, this.memory);
210+
const args = JSValue.decodeArray(argv, argc, memory);
215211
result = func(...args);
216212
} catch (error) {
217-
JSValue.write(
213+
return JSValue.writeAndReturnKindBits(
218214
error,
219-
kind_ptr,
220215
payload1_ptr,
221216
payload2_ptr,
222217
true,
223218
this.memory
224219
);
225-
return;
226220
}
227-
JSValue.write(
221+
return JSValue.writeAndReturnKindBits(
228222
result,
229-
kind_ptr,
230223
payload1_ptr,
231224
payload2_ptr,
232225
false,
@@ -237,67 +230,48 @@ export class SwiftRuntime {
237230
ref: ref,
238231
argv: pointer,
239232
argc: number,
240-
kind_ptr: pointer,
241233
payload1_ptr: pointer,
242234
payload2_ptr: pointer
243235
) => {
244-
const func = this.memory.getObject(ref);
245-
let isException = true;
246-
try {
247-
const args = JSValue.decodeArray(argv, argc, this.memory);
248-
const result = func(...args);
249-
JSValue.write(
250-
result,
251-
kind_ptr,
252-
payload1_ptr,
253-
payload2_ptr,
254-
false,
255-
this.memory
256-
);
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-
}
269-
}
236+
const memory = this.memory;
237+
const func = memory.getObject(ref);
238+
const args = JSValue.decodeArray(argv, argc, memory);
239+
const result = func(...args);
240+
return JSValue.writeAndReturnKindBits(
241+
result,
242+
payload1_ptr,
243+
payload2_ptr,
244+
false,
245+
this.memory
246+
);
270247
},
271248

272249
swjs_call_function_with_this: (
273250
obj_ref: ref,
274251
func_ref: ref,
275252
argv: pointer,
276253
argc: number,
277-
kind_ptr: pointer,
278254
payload1_ptr: pointer,
279255
payload2_ptr: pointer
280256
) => {
281-
const obj = this.memory.getObject(obj_ref);
282-
const func = this.memory.getObject(func_ref);
257+
const memory = this.memory;
258+
const obj = memory.getObject(obj_ref);
259+
const func = memory.getObject(func_ref);
283260
let result: any;
284261
try {
285-
const args = JSValue.decodeArray(argv, argc, this.memory);
262+
const args = JSValue.decodeArray(argv, argc, memory);
286263
result = func.apply(obj, args);
287264
} catch (error) {
288-
JSValue.write(
265+
return JSValue.writeAndReturnKindBits(
289266
error,
290-
kind_ptr,
291267
payload1_ptr,
292268
payload2_ptr,
293269
true,
294270
this.memory
295271
);
296-
return;
297272
}
298-
JSValue.write(
273+
return JSValue.writeAndReturnKindBits(
299274
result,
300-
kind_ptr,
301275
payload1_ptr,
302276
payload2_ptr,
303277
false,
@@ -309,42 +283,28 @@ export class SwiftRuntime {
309283
func_ref: ref,
310284
argv: pointer,
311285
argc: number,
312-
kind_ptr: pointer,
313286
payload1_ptr: pointer,
314287
payload2_ptr: pointer
315288
) => {
316-
const obj = this.memory.getObject(obj_ref);
317-
const func = this.memory.getObject(func_ref);
318-
let isException = true;
319-
try {
320-
const args = JSValue.decodeArray(argv, argc, this.memory);
321-
const result = func.apply(obj, args);
322-
JSValue.write(
323-
result,
324-
kind_ptr,
325-
payload1_ptr,
326-
payload2_ptr,
327-
false,
328-
this.memory
329-
);
330-
isException = false;
331-
} finally {
332-
if (isException) {
333-
JSValue.write(
334-
undefined,
335-
kind_ptr,
336-
payload1_ptr,
337-
payload2_ptr,
338-
true,
339-
this.memory
340-
);
341-
}
342-
}
289+
const memory = this.memory;
290+
const obj = memory.getObject(obj_ref);
291+
const func = memory.getObject(func_ref);
292+
let result = undefined;
293+
const args = JSValue.decodeArray(argv, argc, memory);
294+
result = func.apply(obj, args);
295+
return JSValue.writeAndReturnKindBits(
296+
result,
297+
payload1_ptr,
298+
payload2_ptr,
299+
false,
300+
this.memory
301+
);
343302
},
344303

345304
swjs_call_new: (ref: ref, argv: pointer, argc: number) => {
346-
const constructor = this.memory.getObject(ref);
347-
const args = JSValue.decodeArray(argv, argc, this.memory);
305+
const memory = this.memory;
306+
const constructor = memory.getObject(ref);
307+
const args = JSValue.decodeArray(argv, argc, memory);
348308
const instance = new constructor(...args);
349309
return this.memory.retain(instance);
350310
},
@@ -356,10 +316,11 @@ export class SwiftRuntime {
356316
exception_payload1_ptr: pointer,
357317
exception_payload2_ptr: pointer
358318
) => {
359-
const constructor = this.memory.getObject(ref);
319+
let memory = this.memory;
320+
const constructor = memory.getObject(ref);
360321
let result: any;
361322
try {
362-
const args = JSValue.decodeArray(argv, argc, this.memory);
323+
const args = JSValue.decodeArray(argv, argc, memory);
363324
result = new constructor(...args);
364325
} catch (error) {
365326
JSValue.write(
@@ -372,20 +333,22 @@ export class SwiftRuntime {
372333
);
373334
return -1;
374335
}
336+
memory = this.memory;
375337
JSValue.write(
376338
null,
377339
exception_kind_ptr,
378340
exception_payload1_ptr,
379341
exception_payload2_ptr,
380342
false,
381-
this.memory
343+
memory
382344
);
383-
return this.memory.retain(result);
345+
return memory.retain(result);
384346
},
385347

386348
swjs_instanceof: (obj_ref: ref, constructor_ref: ref) => {
387-
const obj = this.memory.getObject(obj_ref);
388-
const constructor = this.memory.getObject(constructor_ref);
349+
const memory = this.memory;
350+
const obj = memory.getObject(obj_ref);
351+
const constructor = memory.getObject(constructor_ref);
389352
return obj instanceof constructor;
390353
},
391354

@@ -419,9 +382,10 @@ export class SwiftRuntime {
419382
},
420383

421384
swjs_load_typed_array: (ref: ref, buffer: pointer) => {
422-
const typedArray = this.memory.getObject(ref);
385+
const memory = this.memory;
386+
const typedArray = memory.getObject(ref);
423387
const bytes = new Uint8Array(typedArray.buffer);
424-
this.memory.writeBytes(buffer, bytes);
388+
memory.writeBytes(buffer, bytes);
425389
},
426390

427391
swjs_release: (ref: ref) => {

0 commit comments

Comments
 (0)
Please sign in to comment.