koffi 1.2.0-alpha.3 → 1.2.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/package.json +4 -2
- package/qemu/registry/machines.json +26 -26
- package/src/abi_arm32.cc +63 -73
- package/src/abi_arm32_fwd.S +2 -2
- package/src/abi_arm64.cc +48 -55
- package/src/abi_arm64_fwd.S +2 -2
- package/src/abi_arm64_fwd.asm +2 -2
- package/src/abi_riscv64_fwd.S +2 -2
- package/src/abi_x64_sysv.cc +6 -1
- package/src/abi_x64_sysv_fwd.S +2 -2
- package/src/abi_x64_win.cc +4 -0
- package/src/abi_x64_win_fwd.asm +5 -5
- package/src/abi_x86.cc +2 -0
- package/src/abi_x86_fwd.S +4 -4
- package/src/abi_x86_fwd.asm +4 -4
- package/src/call.cc +49 -46
- package/src/call.hh +6 -6
- package/src/ffi.cc +4 -4
- package/src/util.cc +17 -0
- package/src/util.hh +2 -0
- package/test/async.js +92 -0
- package/test/callbacks.js +87 -0
- package/test/misc.c +25 -5
- package/test/sqlite.js +34 -5
- package/test/sync.js +323 -0
package/README.md
CHANGED
|
@@ -18,13 +18,12 @@
|
|
|
18
18
|
|
|
19
19
|
# Introduction
|
|
20
20
|
|
|
21
|
-
Koffi is a fast and easy-to-use C FFI module for Node.js,
|
|
21
|
+
Koffi is a fast and easy-to-use C FFI module for Node.js, featuring:
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* 1.4: Type parser, unions
|
|
23
|
+
* Low-overhead and fast performance (see [benchmarks](#benchmarks))
|
|
24
|
+
* Support for primitive and aggregate data types (structs and fixed-size arrays), both by reference (pointer) and by value
|
|
25
|
+
* Javascript functions can be used as C callbacks (since 1.2.0)
|
|
26
|
+
* Well-tested code base for popular OS/architecture combinations
|
|
28
27
|
|
|
29
28
|
The following combinations of OS and architectures __are officially supported and tested__ at the moment:
|
|
30
29
|
|
|
@@ -41,7 +40,10 @@ RISC-V 64 [^4] | ⬜️ *N/A* | 🟩 Yes | ⬜️ *N/A* | 🟨 Proba
|
|
|
41
40
|
[^3]: However, we don't provide prebuilt binaries for macOS on Apple M1.
|
|
42
41
|
[^4]: Only the LP64D (double-precision float) ABI gets tested. The LP64 ABI is supported in theory (untested), the LP64F ABI is not supported.
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
The following features are planned in the near future:
|
|
44
|
+
|
|
45
|
+
* 1.3: Real-world examples, optimize passing of structs and arrays
|
|
46
|
+
* 1.4: Type parser, unions
|
|
45
47
|
|
|
46
48
|
# Get started
|
|
47
49
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koffi",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.4",
|
|
4
4
|
"description": "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"foreign",
|
|
@@ -41,12 +41,14 @@
|
|
|
41
41
|
"benchmark/raylib_*",
|
|
42
42
|
"qemu/qemu.js",
|
|
43
43
|
"qemu/registry",
|
|
44
|
+
"test/async.js",
|
|
45
|
+
"test/callbacks.js",
|
|
44
46
|
"test/CMakeLists.txt",
|
|
45
47
|
"test/misc.c",
|
|
46
48
|
"test/misc.def",
|
|
47
|
-
"test/misc.js",
|
|
48
49
|
"test/raylib.js",
|
|
49
50
|
"test/sqlite.js",
|
|
51
|
+
"test/sync.js",
|
|
50
52
|
"vendor",
|
|
51
53
|
"LICENSE.txt",
|
|
52
54
|
"README.md",
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"commands": {
|
|
38
38
|
"Test Sync": "node test/sync.js",
|
|
39
39
|
"Test Async": "node test/async.js",
|
|
40
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
40
41
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
41
|
-
"Test SQLite": "node test/sqlite.js"
|
|
42
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
42
|
+
"Test SQLite": "node test/sqlite.js"
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -83,9 +83,9 @@
|
|
|
83
83
|
"commands": {
|
|
84
84
|
"Test Sync": "node test/sync.js",
|
|
85
85
|
"Test Async": "node test/async.js",
|
|
86
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
86
87
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
87
|
-
"Test SQLite": "node test/sqlite.js"
|
|
88
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
88
|
+
"Test SQLite": "node test/sqlite.js"
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -129,9 +129,9 @@
|
|
|
129
129
|
"commands": {
|
|
130
130
|
"Test Sync": "node test/sync.js",
|
|
131
131
|
"Test Async": "node test/async.js",
|
|
132
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
132
133
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
133
|
-
"Test SQLite": "node test/sqlite.js"
|
|
134
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
134
|
+
"Test SQLite": "node test/sqlite.js"
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -175,9 +175,9 @@
|
|
|
175
175
|
"commands": {
|
|
176
176
|
"Test Sync": "node test/sync.js",
|
|
177
177
|
"Test Async": "node test/async.js",
|
|
178
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
178
179
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
179
|
-
"Test SQLite": "node test/sqlite.js"
|
|
180
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
180
|
+
"Test SQLite": "node test/sqlite.js"
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
}
|
|
@@ -228,9 +228,9 @@
|
|
|
228
228
|
"commands": {
|
|
229
229
|
"Test Sync": "C:\\Node32\\node32.cmd node test/sync.js",
|
|
230
230
|
"Test Async": "C:\\Node32\\node32.cmd node test/async.js",
|
|
231
|
+
"Test Callbacks": "C:\\Node32\\node32.cmd node test/callbacks.js",
|
|
231
232
|
"Test Raylib": "seatsh C:\\Node32\\node32.cmd node test/raylib.js",
|
|
232
|
-
"Test SQLite": "C:\\Node32\\node32.cmd node test/sqlite.js"
|
|
233
|
-
"Test Callbacks": "C:\\Node32\\node32.cmd node test/callbacks.js"
|
|
233
|
+
"Test SQLite": "C:\\Node32\\node32.cmd node test/sqlite.js"
|
|
234
234
|
}
|
|
235
235
|
},
|
|
236
236
|
|
|
@@ -242,9 +242,9 @@
|
|
|
242
242
|
"commands": {
|
|
243
243
|
"Test Sync": "C:\\Node64\\node64.cmd node test/sync.js",
|
|
244
244
|
"Test Async": "C:\\Node64\\node64.cmd node test/async.js",
|
|
245
|
+
"Test Callbacks": "C:\\Node64\\node64.cmd node test/callbacks.js",
|
|
245
246
|
"Test Raylib": "seatsh C:\\Node64\\node64.cmd node test/raylib.js",
|
|
246
|
-
"Test SQLite": "C:\\Node64\\node64.cmd node test/sqlite.js"
|
|
247
|
-
"Test Callbacks": "C:\\Node64\\node64.cmd node test/callbacks.js"
|
|
247
|
+
"Test SQLite": "C:\\Node64\\node64.cmd node test/sqlite.js"
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
250
|
}
|
|
@@ -288,9 +288,9 @@
|
|
|
288
288
|
"commands": {
|
|
289
289
|
"Test Sync": "node test/sync.js",
|
|
290
290
|
"Test Async": "node test/async.js",
|
|
291
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
291
292
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
292
|
-
"Test SQLite": "node test/sqlite.js"
|
|
293
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
293
|
+
"Test SQLite": "node test/sqlite.js"
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
296
|
}
|
|
@@ -334,9 +334,9 @@
|
|
|
334
334
|
"commands": {
|
|
335
335
|
"Test Sync": "node test/sync.js",
|
|
336
336
|
"Test Async": "node test/async.js",
|
|
337
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
337
338
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
338
|
-
"Test SQLite": "node test/sqlite.js"
|
|
339
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
339
|
+
"Test SQLite": "node test/sqlite.js"
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
}
|
|
@@ -380,9 +380,9 @@
|
|
|
380
380
|
"commands": {
|
|
381
381
|
"Test Sync": "node test/sync.js",
|
|
382
382
|
"Test Async": "node test/async.js",
|
|
383
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
383
384
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
384
|
-
"Test SQLite": "node test/sqlite.js"
|
|
385
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
385
|
+
"Test SQLite": "node test/sqlite.js"
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
}
|
|
@@ -426,8 +426,8 @@
|
|
|
426
426
|
"commands": {
|
|
427
427
|
"Test Sync": "PATH=/usr/local/bin:/usr/bin:/bin node test/sync.js",
|
|
428
428
|
"Test Async": "PATH=/usr/local/bin:/usr/bin:/bin node test/async.js",
|
|
429
|
-
"Test
|
|
430
|
-
"Test
|
|
429
|
+
"Test Callbacks": "PATH=/usr/local/bin:/usr/bin:/bin node test/callbacks.js",
|
|
430
|
+
"Test SQLite": "PATH=/usr/local/bin:/usr/bin:/bin node test/sqlite.js"
|
|
431
431
|
}
|
|
432
432
|
}
|
|
433
433
|
}
|
|
@@ -471,9 +471,9 @@
|
|
|
471
471
|
"commands": {
|
|
472
472
|
"Test Sync": "node test/sync.js",
|
|
473
473
|
"Test Async": "node test/async.js",
|
|
474
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
474
475
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
475
|
-
"Test SQLite": "node test/sqlite.js"
|
|
476
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
476
|
+
"Test SQLite": "node test/sqlite.js"
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
}
|
|
@@ -517,9 +517,9 @@
|
|
|
517
517
|
"commands": {
|
|
518
518
|
"Test Sync": "node test/sync.js",
|
|
519
519
|
"Test Async": "node test/async.js",
|
|
520
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
520
521
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
521
|
-
"Test SQLite": "node test/sqlite.js"
|
|
522
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
522
|
+
"Test SQLite": "node test/sqlite.js"
|
|
523
523
|
}
|
|
524
524
|
}
|
|
525
525
|
}
|
|
@@ -563,9 +563,9 @@
|
|
|
563
563
|
"commands": {
|
|
564
564
|
"Test Sync": "node test/sync.js",
|
|
565
565
|
"Test Async": "node test/async.js",
|
|
566
|
+
"Test Callbacks": "node test/callbacks.js",
|
|
566
567
|
"Test Raylib": "xvfb-run node test/raylib.js",
|
|
567
|
-
"Test SQLite": "node test/sqlite.js"
|
|
568
|
-
"Test Callbacks": "node test/callbacks.js"
|
|
568
|
+
"Test SQLite": "node test/sqlite.js"
|
|
569
569
|
}
|
|
570
570
|
}
|
|
571
571
|
}
|
package/src/abi_arm32.cc
CHANGED
|
@@ -139,10 +139,11 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
139
139
|
} break;
|
|
140
140
|
case PrimitiveKind::Int64:
|
|
141
141
|
case PrimitiveKind::UInt64: {
|
|
142
|
-
|
|
142
|
+
bool realign = gpr_avail % 2;
|
|
143
|
+
int need = 2 + realign;
|
|
143
144
|
|
|
144
145
|
if (gpr_avail >= need) {
|
|
145
|
-
param.gpr_count =
|
|
146
|
+
param.gpr_count = 2;
|
|
146
147
|
gpr_avail -= need;
|
|
147
148
|
} else {
|
|
148
149
|
started_stack = true;
|
|
@@ -160,13 +161,14 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
160
161
|
started_stack = true;
|
|
161
162
|
}
|
|
162
163
|
} else {
|
|
163
|
-
|
|
164
|
+
bool realign = (param.type->align == 8 && (gpr_avail % 2));
|
|
165
|
+
int need = (param.type->size + 3) / 4 + realign;
|
|
164
166
|
|
|
165
|
-
if (
|
|
166
|
-
param.gpr_count =
|
|
167
|
-
gpr_avail -=
|
|
167
|
+
if (need <= gpr_avail) {
|
|
168
|
+
param.gpr_count = need - realign;
|
|
169
|
+
gpr_avail -= need;
|
|
168
170
|
} else if (!started_stack) {
|
|
169
|
-
param.gpr_count = gpr_avail;
|
|
171
|
+
param.gpr_count = gpr_avail - realign;
|
|
170
172
|
gpr_avail = 0;
|
|
171
173
|
|
|
172
174
|
started_stack = true;
|
|
@@ -195,7 +197,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
195
197
|
need += (gpr_avail % 2);
|
|
196
198
|
|
|
197
199
|
if (need <= gpr_avail) {
|
|
198
|
-
param.gpr_count =
|
|
200
|
+
param.gpr_count = 2;
|
|
199
201
|
gpr_avail -= need;
|
|
200
202
|
} else {
|
|
201
203
|
started_stack = true;
|
|
@@ -214,7 +216,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
214
216
|
|
|
215
217
|
bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
216
218
|
{
|
|
217
|
-
|
|
219
|
+
uint32_t *args_ptr = nullptr;
|
|
218
220
|
uint32_t *gpr_ptr = nullptr;
|
|
219
221
|
uint32_t *vec_ptr = nullptr;
|
|
220
222
|
|
|
@@ -251,13 +253,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
251
253
|
}
|
|
252
254
|
|
|
253
255
|
bool b = value.As<Napi::Boolean>();
|
|
254
|
-
|
|
255
|
-
if (RG_LIKELY(param.gpr_count)) {
|
|
256
|
-
*(gpr_ptr++) = (uint32_t)b;
|
|
257
|
-
} else {
|
|
258
|
-
*args_ptr = (uint8_t)b;
|
|
259
|
-
args_ptr += 4;
|
|
260
|
-
}
|
|
256
|
+
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)b;
|
|
261
257
|
} break;
|
|
262
258
|
case PrimitiveKind::Int8:
|
|
263
259
|
case PrimitiveKind::UInt8:
|
|
@@ -270,13 +266,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
270
266
|
}
|
|
271
267
|
|
|
272
268
|
int32_t v = CopyNumber<int32_t>(value);
|
|
273
|
-
|
|
274
|
-
if (RG_LIKELY(param.gpr_count)) {
|
|
275
|
-
*(int32_t *)(gpr_ptr++) = v;
|
|
276
|
-
} else {
|
|
277
|
-
*(int32_t *)args_ptr = v;
|
|
278
|
-
args_ptr += 4;
|
|
279
|
-
}
|
|
269
|
+
*(int32_t *)((param.gpr_count ? gpr_ptr : args_ptr)++) = v;
|
|
280
270
|
} break;
|
|
281
271
|
case PrimitiveKind::UInt32: {
|
|
282
272
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
@@ -285,13 +275,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
285
275
|
}
|
|
286
276
|
|
|
287
277
|
uint32_t v = CopyNumber<uint32_t>(value);
|
|
288
|
-
|
|
289
|
-
if (RG_LIKELY(param.gpr_count)) {
|
|
290
|
-
*(gpr_ptr++) = v;
|
|
291
|
-
} else {
|
|
292
|
-
*(uint32_t *)args_ptr = v;
|
|
293
|
-
args_ptr += 4;
|
|
294
|
-
}
|
|
278
|
+
*((param.gpr_count ? gpr_ptr : args_ptr)++) = v;
|
|
295
279
|
} break;
|
|
296
280
|
case PrimitiveKind::Int64: {
|
|
297
281
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
@@ -302,13 +286,13 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
302
286
|
int64_t v = CopyNumber<int64_t>(value);
|
|
303
287
|
|
|
304
288
|
if (RG_LIKELY(param.gpr_count)) {
|
|
305
|
-
gpr_ptr
|
|
289
|
+
gpr_ptr = AlignUp(gpr_ptr, 8);
|
|
306
290
|
*(int64_t *)gpr_ptr = v;
|
|
307
291
|
gpr_ptr += param.gpr_count;
|
|
308
292
|
} else {
|
|
309
293
|
args_ptr = AlignUp(args_ptr, 8);
|
|
310
294
|
*(int64_t *)args_ptr = v;
|
|
311
|
-
args_ptr +=
|
|
295
|
+
args_ptr += 2;
|
|
312
296
|
}
|
|
313
297
|
} break;
|
|
314
298
|
case PrimitiveKind::UInt64: {
|
|
@@ -320,13 +304,13 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
320
304
|
uint64_t v = CopyNumber<uint64_t>(value);
|
|
321
305
|
|
|
322
306
|
if (RG_LIKELY(param.gpr_count)) {
|
|
323
|
-
gpr_ptr
|
|
307
|
+
gpr_ptr = AlignUp(gpr_ptr, 8);
|
|
324
308
|
*(uint64_t *)gpr_ptr = v;
|
|
325
309
|
gpr_ptr += param.gpr_count;
|
|
326
310
|
} else {
|
|
327
311
|
args_ptr = AlignUp(args_ptr, 8);
|
|
328
312
|
*(uint64_t *)args_ptr = v;
|
|
329
|
-
args_ptr +=
|
|
313
|
+
args_ptr += 2;
|
|
330
314
|
}
|
|
331
315
|
} break;
|
|
332
316
|
case PrimitiveKind::String: {
|
|
@@ -342,12 +326,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
342
326
|
return false;
|
|
343
327
|
}
|
|
344
328
|
|
|
345
|
-
|
|
346
|
-
*(gpr_ptr++) = (uint64_t)str;
|
|
347
|
-
} else {
|
|
348
|
-
*(const char **)args_ptr = str;
|
|
349
|
-
args_ptr += 4;
|
|
350
|
-
}
|
|
329
|
+
*(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
|
|
351
330
|
} break;
|
|
352
331
|
case PrimitiveKind::String16: {
|
|
353
332
|
const char16_t *str16;
|
|
@@ -362,12 +341,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
362
341
|
return false;
|
|
363
342
|
}
|
|
364
343
|
|
|
365
|
-
|
|
366
|
-
*(gpr_ptr++) = (uint64_t)str16;
|
|
367
|
-
} else {
|
|
368
|
-
*(const char16_t **)args_ptr = str16;
|
|
369
|
-
args_ptr += 4;
|
|
370
|
-
}
|
|
344
|
+
*(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
|
|
371
345
|
} break;
|
|
372
346
|
case PrimitiveKind::Pointer: {
|
|
373
347
|
uint8_t *ptr;
|
|
@@ -400,12 +374,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
400
374
|
return false;
|
|
401
375
|
}
|
|
402
376
|
|
|
403
|
-
|
|
404
|
-
*(gpr_ptr++) = (uint64_t)ptr;
|
|
405
|
-
} else {
|
|
406
|
-
*(void **)args_ptr = ptr;
|
|
407
|
-
args_ptr += 4;
|
|
408
|
-
}
|
|
377
|
+
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
409
378
|
} break;
|
|
410
379
|
case PrimitiveKind::Record: {
|
|
411
380
|
if (RG_UNLIKELY(!IsObject(value))) {
|
|
@@ -422,18 +391,21 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
422
391
|
} else if (param.gpr_count) {
|
|
423
392
|
RG_ASSERT(param.type->align <= 8);
|
|
424
393
|
|
|
394
|
+
int16_t align = (param.type->align <= 4) ? 4 : 8;
|
|
395
|
+
gpr_ptr = AlignUp(gpr_ptr, align);
|
|
396
|
+
|
|
425
397
|
if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
|
|
426
398
|
return false;
|
|
427
399
|
|
|
428
400
|
gpr_ptr += param.gpr_count;
|
|
429
|
-
args_ptr +=
|
|
401
|
+
args_ptr += (param.type->size - param.gpr_count * 4 + 3) / 4;
|
|
430
402
|
} else if (param.type->size) {
|
|
431
403
|
int16_t align = (param.type->align <= 4) ? 4 : 8;
|
|
432
|
-
|
|
433
404
|
args_ptr = AlignUp(args_ptr, align);
|
|
434
|
-
|
|
405
|
+
|
|
406
|
+
if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
|
|
435
407
|
return false;
|
|
436
|
-
args_ptr +=
|
|
408
|
+
args_ptr += (param.type->size + 3) / 4;
|
|
437
409
|
}
|
|
438
410
|
} break;
|
|
439
411
|
case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
|
|
@@ -450,8 +422,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
450
422
|
} else if (param.gpr_count) {
|
|
451
423
|
*(float *)(gpr_ptr++) = f;
|
|
452
424
|
} else {
|
|
453
|
-
*(float *)args_ptr = f;
|
|
454
|
-
args_ptr += 4;
|
|
425
|
+
*(float *)(args_ptr++) = f;
|
|
455
426
|
}
|
|
456
427
|
} break;
|
|
457
428
|
case PrimitiveKind::Float64: {
|
|
@@ -466,13 +437,13 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
466
437
|
*(double *)vec_ptr = d;
|
|
467
438
|
vec_ptr += 2;
|
|
468
439
|
} else if (param.gpr_count) {
|
|
469
|
-
gpr_ptr
|
|
440
|
+
gpr_ptr = AlignUp(gpr_ptr, 8);
|
|
470
441
|
*(double *)gpr_ptr = d;
|
|
471
442
|
gpr_ptr += 2;
|
|
472
443
|
} else {
|
|
473
444
|
args_ptr = AlignUp(args_ptr, 8);
|
|
474
445
|
*(double *)args_ptr = d;
|
|
475
|
-
args_ptr +=
|
|
446
|
+
args_ptr += 2;
|
|
476
447
|
}
|
|
477
448
|
} break;
|
|
478
449
|
case PrimitiveKind::Callback: {
|
|
@@ -495,12 +466,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
495
466
|
return false;
|
|
496
467
|
}
|
|
497
468
|
|
|
498
|
-
|
|
499
|
-
*(gpr_ptr++) = (uint32_t)ptr;
|
|
500
|
-
} else {
|
|
501
|
-
*(void **)args_ptr = ptr;
|
|
502
|
-
args_ptr += 4;
|
|
503
|
-
}
|
|
469
|
+
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
504
470
|
} break;
|
|
505
471
|
}
|
|
506
472
|
}
|
|
@@ -668,7 +634,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
|
|
|
668
634
|
arguments.Append(arg);
|
|
669
635
|
} break;
|
|
670
636
|
case PrimitiveKind::Int64: {
|
|
671
|
-
gpr_ptr
|
|
637
|
+
gpr_ptr = AlignUp(gpr_ptr, 8);
|
|
638
|
+
|
|
672
639
|
int64_t v = *(int64_t *)(param.gpr_count ? gpr_ptr : args_ptr);
|
|
673
640
|
(param.gpr_count ? gpr_ptr : args_ptr) += 2;
|
|
674
641
|
|
|
@@ -676,7 +643,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
|
|
|
676
643
|
arguments.Append(arg);
|
|
677
644
|
} break;
|
|
678
645
|
case PrimitiveKind::UInt64: {
|
|
679
|
-
gpr_ptr
|
|
646
|
+
gpr_ptr = AlignUp(gpr_ptr, 8);
|
|
647
|
+
|
|
680
648
|
uint64_t v = *(uint64_t *)(param.gpr_count ? gpr_ptr : args_ptr);
|
|
681
649
|
(param.gpr_count ? gpr_ptr : args_ptr) += 2;
|
|
682
650
|
|
|
@@ -717,11 +685,32 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
|
|
|
717
685
|
} else if (param.gpr_count) {
|
|
718
686
|
RG_ASSERT(param.type->align <= 8);
|
|
719
687
|
|
|
720
|
-
|
|
721
|
-
|
|
688
|
+
int16_t gpr_size = param.gpr_count * 4;
|
|
689
|
+
int16_t align = (param.type->align <= 4) ? 4 : 8;
|
|
690
|
+
gpr_ptr = AlignUp(gpr_ptr, align);
|
|
722
691
|
|
|
723
|
-
|
|
724
|
-
|
|
692
|
+
if (param.type->size > gpr_size) {
|
|
693
|
+
uint8_t *ptr;
|
|
694
|
+
|
|
695
|
+
// XXX: Expensive, and error can't be managed by calling C code.
|
|
696
|
+
// But the object is split between the GPRs and the caller stack.
|
|
697
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->size, 16, &ptr)))
|
|
698
|
+
return;
|
|
699
|
+
|
|
700
|
+
memcpy(ptr, gpr_ptr, gpr_size);
|
|
701
|
+
memcpy(ptr + gpr_size, args_ptr, param.type->size - gpr_size);
|
|
702
|
+
|
|
703
|
+
Napi::Object obj = PopObject(ptr, param.type);
|
|
704
|
+
arguments.Append(obj);
|
|
705
|
+
|
|
706
|
+
gpr_ptr += param.gpr_count;
|
|
707
|
+
args_ptr += (param.type->size - gpr_size + 3) / 4;
|
|
708
|
+
} else {
|
|
709
|
+
Napi::Object obj = PopObject((const uint8_t *)gpr_ptr, param.type);
|
|
710
|
+
arguments.Append(obj);
|
|
711
|
+
|
|
712
|
+
gpr_ptr += param.gpr_count;
|
|
713
|
+
}
|
|
725
714
|
} else if (param.type->size) {
|
|
726
715
|
int16_t align = (param.type->align <= 4) ? 4 : 8;
|
|
727
716
|
args_ptr = AlignUp(args_ptr, align);
|
|
@@ -752,10 +741,11 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
|
|
|
752
741
|
d = *(double *)vec_ptr;
|
|
753
742
|
vec_ptr += 2;
|
|
754
743
|
} else if (param.gpr_count) {
|
|
755
|
-
gpr_ptr
|
|
744
|
+
gpr_ptr = AlignUp(gpr_ptr, 8);
|
|
756
745
|
d = *(double *)gpr_ptr;
|
|
757
746
|
gpr_ptr += 2;
|
|
758
747
|
} else {
|
|
748
|
+
args_ptr = AlignUp(args_ptr, 8);
|
|
759
749
|
d = *(double *)args_ptr;
|
|
760
750
|
args_ptr += 2;
|
|
761
751
|
}
|
package/src/abi_arm32_fwd.S
CHANGED
|
@@ -290,8 +290,8 @@ TrampolineX15:
|
|
|
290
290
|
trampoline_vec 15
|
|
291
291
|
|
|
292
292
|
# When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
|
|
293
|
-
# The
|
|
294
|
-
#
|
|
293
|
+
# The problem is that we're still running on the separate Koffi stack, and V8 will
|
|
294
|
+
# probably misdetect this as a "stack overflow". We have to restore the old
|
|
295
295
|
# stack pointer, call Node.js/V8 and go back to ours.
|
|
296
296
|
# The first three parameters (r0, r1, r2) are passed through untouched.
|
|
297
297
|
CallSwitchStack:
|