koffi 2.15.1 → 2.16.0-beta.1
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/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_armhf/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_loong64/koffi.node +0 -0
- package/build/koffi/linux_riscv64d/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/musl_arm64/koffi.node +0 -0
- package/build/koffi/musl_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/index.d.ts +11 -9
- package/index.js +8 -8
- package/indirect.js +8 -8
- package/package.json +1 -1
- package/src/koffi/src/abi_arm32.cc +222 -219
- package/src/koffi/src/abi_arm32_asm.S +1 -29
- package/src/koffi/src/abi_arm64.cc +257 -235
- package/src/koffi/src/abi_arm64_asm.S +1 -32
- package/src/koffi/src/abi_arm64_asm.asm +1 -23
- package/src/koffi/src/abi_loong64_asm.S +1 -25
- package/src/koffi/src/abi_riscv64.cc +220 -217
- package/src/koffi/src/abi_riscv64_asm.S +1 -25
- package/src/koffi/src/abi_x64_sysv.cc +196 -192
- package/src/koffi/src/abi_x64_sysv_asm.S +1 -31
- package/src/koffi/src/abi_x64_win.cc +188 -172
- package/src/koffi/src/abi_x64_win_asm.S +1 -19
- package/src/koffi/src/abi_x64_win_asm.asm +1 -21
- package/src/koffi/src/abi_x86.cc +224 -189
- package/src/koffi/src/abi_x86_asm.S +6 -25
- package/src/koffi/src/abi_x86_asm.asm +9 -22
- package/src/koffi/src/call.cc +246 -428
- package/src/koffi/src/call.hh +9 -8
- package/src/koffi/src/ffi.cc +140 -87
- package/src/koffi/src/ffi.hh +12 -58
- package/src/koffi/src/primitives.inc +39 -0
- package/src/koffi/src/trampolines/armasm.inc +0 -32770
- package/src/koffi/src/trampolines/gnu.inc +0 -24578
- package/src/koffi/src/trampolines/masm32.inc +0 -32770
- package/src/koffi/src/trampolines/masm64.inc +0 -32770
- package/src/koffi/src/trampolines/prototypes.inc +16385 -16385
- package/src/koffi/src/util.cc +149 -107
- package/src/koffi/src/util.hh +76 -40
|
@@ -59,8 +59,6 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
|
|
|
59
59
|
uint8_t *old_sp, Span<uint8_t> *new_stack,
|
|
60
60
|
napi_value (*call)(Napi::Function *func, size_t argc, napi_value *argv));
|
|
61
61
|
|
|
62
|
-
#include "trampolines/prototypes.inc"
|
|
63
|
-
|
|
64
62
|
static inline RegisterClass MergeClasses(RegisterClass cls1, RegisterClass cls2)
|
|
65
63
|
{
|
|
66
64
|
if (cls1 == cls2)
|
|
@@ -225,179 +223,226 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
225
223
|
|
|
226
224
|
bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
227
225
|
{
|
|
228
|
-
uint64_t *
|
|
229
|
-
uint64_t *
|
|
230
|
-
uint64_t *
|
|
226
|
+
uint64_t *gpr_ptr = AllocStack<uint64_t>(14 * 8 + func->args_size);
|
|
227
|
+
uint64_t *xmm_ptr = gpr_ptr + 6;
|
|
228
|
+
uint64_t *args_ptr = gpr_ptr + 14;
|
|
231
229
|
|
|
232
|
-
|
|
233
|
-
if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]]
|
|
234
|
-
return false;
|
|
235
|
-
if (!AllocStack(8 * 8, 8, &xmm_ptr)) [[unlikely]]
|
|
236
|
-
return false;
|
|
237
|
-
if (!AllocStack(6 * 8, 8, &gpr_ptr)) [[unlikely]]
|
|
230
|
+
if (!gpr_ptr) [[unlikely]]
|
|
238
231
|
return false;
|
|
239
232
|
if (func->ret.use_memory) {
|
|
240
233
|
return_ptr = AllocHeap(func->ret.type->size, 16);
|
|
241
234
|
*(uint8_t **)(gpr_ptr++) = return_ptr;
|
|
242
235
|
}
|
|
243
236
|
|
|
237
|
+
Size i = -1;
|
|
238
|
+
|
|
239
|
+
static const void *const DispatchTable[] = {
|
|
240
|
+
#define PRIMITIVE(Name) && Name,
|
|
241
|
+
#include "primitives.inc"
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
#define LOOP
|
|
245
|
+
#define CASE(Primitive) \
|
|
246
|
+
do { \
|
|
247
|
+
PrimitiveKind next = func->primitives[++i]; \
|
|
248
|
+
goto *DispatchTable[(int)next]; \
|
|
249
|
+
} while (false); \
|
|
250
|
+
Primitive:
|
|
251
|
+
#define OR(Primitive) \
|
|
252
|
+
Primitive:
|
|
253
|
+
|
|
244
254
|
#define PUSH_INTEGER(CType) \
|
|
245
255
|
do { \
|
|
246
|
-
|
|
256
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
257
|
+
Napi::Value value = info[param.offset]; \
|
|
258
|
+
\
|
|
259
|
+
CType v; \
|
|
260
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
247
261
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
248
262
|
return false; \
|
|
249
263
|
} \
|
|
250
264
|
\
|
|
251
|
-
CType v = GetNumber<CType>(value); \
|
|
252
265
|
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)v; \
|
|
253
266
|
} while (false)
|
|
254
267
|
#define PUSH_INTEGER_SWAP(CType) \
|
|
255
268
|
do { \
|
|
256
|
-
|
|
269
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
270
|
+
Napi::Value value = info[param.offset]; \
|
|
271
|
+
\
|
|
272
|
+
CType v; \
|
|
273
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
257
274
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
258
275
|
return false; \
|
|
259
276
|
} \
|
|
260
277
|
\
|
|
261
|
-
CType v = GetNumber<CType>(value); \
|
|
262
278
|
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)ReverseBytes(v); \
|
|
263
279
|
} while (false)
|
|
264
280
|
|
|
265
281
|
// Push arguments
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
282
|
+
LOOP {
|
|
283
|
+
CASE(Void) { K_UNREACHABLE(); };
|
|
269
284
|
|
|
270
|
-
|
|
285
|
+
CASE(Bool) {
|
|
286
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
287
|
+
Napi::Value value = info[param.offset];
|
|
271
288
|
|
|
272
|
-
|
|
273
|
-
|
|
289
|
+
bool b;
|
|
290
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
291
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
274
294
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
295
|
+
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)b;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
CASE(Int8) { PUSH_INTEGER(int8_t); };
|
|
299
|
+
CASE(UInt8) { PUSH_INTEGER(uint8_t); };
|
|
300
|
+
CASE(Int16) { PUSH_INTEGER(int16_t); };
|
|
301
|
+
CASE(Int16S) { PUSH_INTEGER_SWAP(int16_t); };
|
|
302
|
+
CASE(UInt16) { PUSH_INTEGER(uint16_t); };
|
|
303
|
+
CASE(UInt16S) { PUSH_INTEGER_SWAP(uint16_t); };
|
|
304
|
+
CASE(Int32) { PUSH_INTEGER(int32_t); };
|
|
305
|
+
CASE(Int32S) { PUSH_INTEGER_SWAP(int32_t); };
|
|
306
|
+
CASE(UInt32) { PUSH_INTEGER(uint32_t); };
|
|
307
|
+
CASE(UInt32S) { PUSH_INTEGER_SWAP(uint32_t); };
|
|
308
|
+
CASE(Int64) { PUSH_INTEGER(int64_t); };
|
|
309
|
+
CASE(Int64S) { PUSH_INTEGER_SWAP(int64_t); };
|
|
310
|
+
CASE(UInt64) { PUSH_INTEGER(int64_t); };
|
|
311
|
+
CASE(UInt64S) { PUSH_INTEGER_SWAP(int64_t); };
|
|
312
|
+
|
|
313
|
+
CASE(String) {
|
|
314
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
315
|
+
Napi::Value value = info[param.offset];
|
|
280
316
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
|
|
285
|
-
case PrimitiveKind::UInt8: { PUSH_INTEGER(uint8_t); } break;
|
|
286
|
-
case PrimitiveKind::Int16: { PUSH_INTEGER(int16_t); } break;
|
|
287
|
-
case PrimitiveKind::Int16S: { PUSH_INTEGER_SWAP(int16_t); } break;
|
|
288
|
-
case PrimitiveKind::UInt16: { PUSH_INTEGER(uint16_t); } break;
|
|
289
|
-
case PrimitiveKind::UInt16S: { PUSH_INTEGER_SWAP(uint16_t); } break;
|
|
290
|
-
case PrimitiveKind::Int32: { PUSH_INTEGER(int32_t); } break;
|
|
291
|
-
case PrimitiveKind::Int32S: { PUSH_INTEGER_SWAP(int32_t); } break;
|
|
292
|
-
case PrimitiveKind::UInt32: { PUSH_INTEGER(uint32_t); } break;
|
|
293
|
-
case PrimitiveKind::UInt32S: { PUSH_INTEGER_SWAP(uint32_t); } break;
|
|
294
|
-
case PrimitiveKind::Int64: { PUSH_INTEGER(int64_t); } break;
|
|
295
|
-
case PrimitiveKind::Int64S: { PUSH_INTEGER_SWAP(int64_t); } break;
|
|
296
|
-
case PrimitiveKind::UInt64: { PUSH_INTEGER(uint64_t); } break;
|
|
297
|
-
case PrimitiveKind::UInt64S: { PUSH_INTEGER_SWAP(uint64_t); } break;
|
|
298
|
-
case PrimitiveKind::String: {
|
|
299
|
-
const char *str;
|
|
300
|
-
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
301
|
-
return false;
|
|
317
|
+
const char *str;
|
|
318
|
+
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
319
|
+
return false;
|
|
302
320
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
return false;
|
|
321
|
+
*(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
|
|
322
|
+
};
|
|
323
|
+
CASE(String16) {
|
|
324
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
325
|
+
Napi::Value value = info[param.offset];
|
|
309
326
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const char32_t *str32;
|
|
314
|
-
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
315
|
-
return false;
|
|
327
|
+
const char16_t *str16;
|
|
328
|
+
if (!PushString16(value, param.directions, &str16)) [[unlikely]]
|
|
329
|
+
return false;
|
|
316
330
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
return false;
|
|
331
|
+
*(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
|
|
332
|
+
};
|
|
333
|
+
CASE(String32) {
|
|
334
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
335
|
+
Napi::Value value = info[param.offset];
|
|
323
336
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
case PrimitiveKind::Union: {
|
|
328
|
-
if (!IsObject(value)) [[unlikely]] {
|
|
329
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
330
|
-
return false;
|
|
331
|
-
}
|
|
337
|
+
const char32_t *str32;
|
|
338
|
+
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
339
|
+
return false;
|
|
332
340
|
|
|
333
|
-
|
|
341
|
+
*(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
|
|
342
|
+
};
|
|
334
343
|
|
|
335
|
-
|
|
336
|
-
|
|
344
|
+
CASE(Pointer) {
|
|
345
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
346
|
+
Napi::Value value = info[param.offset];
|
|
337
347
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
348
|
+
void *ptr;
|
|
349
|
+
if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
|
|
350
|
+
return false;
|
|
341
351
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
352
|
+
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
CASE(Record) OR(Union) {
|
|
356
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
357
|
+
Napi::Value value = info[param.offset];
|
|
358
|
+
|
|
359
|
+
if (!IsObject(value)) [[unlikely]] {
|
|
360
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
Napi::Object obj = value.As<Napi::Object>();
|
|
365
|
+
|
|
366
|
+
if (param.gpr_count || param.xmm_count) {
|
|
367
|
+
K_ASSERT(param.type->size <= 16);
|
|
368
|
+
|
|
369
|
+
uint64_t buf[2] = {};
|
|
370
|
+
if (!PushObject(obj, param.type, (uint8_t *)buf))
|
|
371
|
+
return false;
|
|
372
|
+
|
|
373
|
+
if (param.gpr_first) {
|
|
374
|
+
*(gpr_ptr++) = buf[0];
|
|
375
|
+
if (param.gpr_count == 2) {
|
|
376
|
+
*(gpr_ptr++) = buf[1];
|
|
377
|
+
} else if (param.xmm_count == 1) {
|
|
378
|
+
*(xmm_ptr++) = buf[1];
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
*(xmm_ptr++) = buf[0];
|
|
382
|
+
if (param.xmm_count == 2) {
|
|
383
|
+
*(xmm_ptr++) = buf[1];
|
|
384
|
+
} else if (param.gpr_count == 1) {
|
|
385
|
+
*(gpr_ptr++) = buf[1];
|
|
356
386
|
}
|
|
357
|
-
} else if (param.use_memory) {
|
|
358
|
-
args_ptr = AlignUp(args_ptr, param.type->align);
|
|
359
|
-
if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
|
|
360
|
-
return false;
|
|
361
|
-
args_ptr += (param.type->size + 7) / 8;
|
|
362
387
|
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
367
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
388
|
+
} else if (param.use_memory) {
|
|
389
|
+
args_ptr = AlignUp(args_ptr, param.type->align);
|
|
390
|
+
if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
|
|
368
391
|
return false;
|
|
369
|
-
|
|
392
|
+
args_ptr += (param.type->size + 7) / 8;
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
CASE(Array) { K_UNREACHABLE(); };
|
|
370
396
|
|
|
371
|
-
|
|
372
|
-
|
|
397
|
+
CASE(Float32) {
|
|
398
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
399
|
+
Napi::Value value = info[param.offset];
|
|
373
400
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
380
|
-
return false;
|
|
381
|
-
}
|
|
401
|
+
float f;
|
|
402
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
403
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
382
406
|
|
|
383
|
-
|
|
384
|
-
*(double *)((param.xmm_count ? xmm_ptr : args_ptr)++) = d;
|
|
385
|
-
} break;
|
|
386
|
-
case PrimitiveKind::Callback: {
|
|
387
|
-
void *ptr;
|
|
388
|
-
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
389
|
-
return false;
|
|
407
|
+
uint64_t *ptr = (param.xmm_count ? xmm_ptr : args_ptr)++;
|
|
390
408
|
|
|
391
|
-
|
|
392
|
-
|
|
409
|
+
memset((uint8_t *)ptr + 4, 0, 4);
|
|
410
|
+
*(float *)ptr = f;
|
|
411
|
+
};
|
|
412
|
+
CASE(Float64) {
|
|
413
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
414
|
+
Napi::Value value = info[param.offset];
|
|
393
415
|
|
|
394
|
-
|
|
395
|
-
|
|
416
|
+
double d;
|
|
417
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
418
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
*(double *)((param.xmm_count ? xmm_ptr : args_ptr)++) = d;
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
CASE(Callback) {
|
|
426
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
427
|
+
Napi::Value value = info[param.offset];
|
|
428
|
+
|
|
429
|
+
void *ptr;
|
|
430
|
+
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
431
|
+
return false;
|
|
432
|
+
|
|
433
|
+
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
CASE(Prototype) { /* End loop */ };
|
|
396
437
|
}
|
|
397
438
|
|
|
398
439
|
#undef PUSH_INTEGER_SWAP
|
|
399
440
|
#undef PUSH_INTEGER
|
|
400
441
|
|
|
442
|
+
#undef OR
|
|
443
|
+
#undef CASE
|
|
444
|
+
#undef LOOP
|
|
445
|
+
|
|
401
446
|
new_sp = mem->stack.end();
|
|
402
447
|
|
|
403
448
|
return true;
|
|
@@ -491,17 +536,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
491
536
|
case PrimitiveKind::String: return result.ptr ? Napi::String::New(env, (const char *)result.ptr) : env.Null();
|
|
492
537
|
case PrimitiveKind::String16: return result.ptr ? Napi::String::New(env, (const char16_t *)result.ptr) : env.Null();
|
|
493
538
|
case PrimitiveKind::String32: return result.ptr ? MakeStringFromUTF32(env, (const char32_t *)result.ptr) : env.Null();
|
|
494
|
-
case PrimitiveKind::Pointer:
|
|
495
|
-
case PrimitiveKind::Callback:
|
|
496
|
-
if (result.ptr) {
|
|
497
|
-
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
498
|
-
SetValueTag(external, func->ret.type->ref.marker);
|
|
499
|
-
|
|
500
|
-
return external;
|
|
501
|
-
} else {
|
|
502
|
-
return env.Null();
|
|
503
|
-
}
|
|
504
|
-
} break;
|
|
539
|
+
case PrimitiveKind::Pointer: return result.ptr ? WrapPointer(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
540
|
+
case PrimitiveKind::Callback: return result.ptr ? WrapCallback(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
505
541
|
case PrimitiveKind::Record:
|
|
506
542
|
case PrimitiveKind::Union: {
|
|
507
543
|
const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
|
|
@@ -676,18 +712,21 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
676
712
|
Napi::Value arg = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
|
|
677
713
|
arguments.Append(arg);
|
|
678
714
|
} break;
|
|
679
|
-
case PrimitiveKind::Pointer:
|
|
680
|
-
case PrimitiveKind::Callback: {
|
|
715
|
+
case PrimitiveKind::Pointer: {
|
|
681
716
|
void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
|
|
682
717
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
SetValueTag(external, param.type->ref.marker);
|
|
718
|
+
Napi::Value p = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
|
|
719
|
+
arguments.Append(p);
|
|
686
720
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
arguments.Append(env.Null());
|
|
721
|
+
if (param.type->dispose) {
|
|
722
|
+
param.type->dispose(env, param.type, ptr2);
|
|
690
723
|
}
|
|
724
|
+
} break;
|
|
725
|
+
case PrimitiveKind::Callback: {
|
|
726
|
+
void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
|
|
727
|
+
|
|
728
|
+
Napi::Value p = ptr2 ? WrapCallback(env, param.type->ref.type, ptr2) : env.Null();
|
|
729
|
+
arguments.Append(p);
|
|
691
730
|
|
|
692
731
|
if (param.type->dispose) {
|
|
693
732
|
param.type->dispose(env, param.type, ptr2);
|
|
@@ -762,22 +801,22 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
762
801
|
|
|
763
802
|
#define RETURN_INTEGER(CType) \
|
|
764
803
|
do { \
|
|
765
|
-
|
|
804
|
+
CType v; \
|
|
805
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
766
806
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
767
807
|
return; \
|
|
768
808
|
} \
|
|
769
809
|
\
|
|
770
|
-
CType v = GetNumber<CType>(value); \
|
|
771
810
|
out_reg->rax = (uint64_t)v; \
|
|
772
811
|
} while (false)
|
|
773
812
|
#define RETURN_INTEGER_SWAP(CType) \
|
|
774
813
|
do { \
|
|
775
|
-
|
|
814
|
+
CType v; \
|
|
815
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
776
816
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
777
817
|
return; \
|
|
778
818
|
} \
|
|
779
819
|
\
|
|
780
|
-
CType v = GetNumber<CType>(value); \
|
|
781
820
|
out_reg->rax = (uint64_t)ReverseBytes(v); \
|
|
782
821
|
} while (false)
|
|
783
822
|
|
|
@@ -785,12 +824,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
785
824
|
switch (type->primitive) {
|
|
786
825
|
case PrimitiveKind::Void: {} break;
|
|
787
826
|
case PrimitiveKind::Bool: {
|
|
788
|
-
|
|
827
|
+
bool b;
|
|
828
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
789
829
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
790
830
|
return;
|
|
791
831
|
}
|
|
792
832
|
|
|
793
|
-
bool b = value.As<Napi::Boolean>();
|
|
794
833
|
out_reg->rax = (uint64_t)b;
|
|
795
834
|
} break;
|
|
796
835
|
case PrimitiveKind::Int8: { RETURN_INTEGER(int8_t); } break;
|
|
@@ -829,24 +868,9 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
829
868
|
out_reg->rax = (uint64_t)str32;
|
|
830
869
|
} break;
|
|
831
870
|
case PrimitiveKind::Pointer: {
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
if (CheckValueTag(value, type->ref.marker)) {
|
|
835
|
-
ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
836
|
-
} else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
|
|
837
|
-
type->ref.type->primitive == PrimitiveKind::Union)) {
|
|
838
|
-
Napi::Object obj = value.As<Napi::Object>();
|
|
839
|
-
|
|
840
|
-
ptr = AllocHeap(type->ref.type->size, 16);
|
|
841
|
-
|
|
842
|
-
if (!PushObject(obj, type->ref.type, ptr))
|
|
843
|
-
return;
|
|
844
|
-
} else if (IsNullOrUndefined(value)) {
|
|
845
|
-
ptr = nullptr;
|
|
846
|
-
} else {
|
|
847
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
871
|
+
void *ptr;
|
|
872
|
+
if (!PushPointer(value, type, 1, &ptr)) [[unlikely]]
|
|
848
873
|
return;
|
|
849
|
-
}
|
|
850
874
|
|
|
851
875
|
out_reg->rax = (uint64_t)ptr;
|
|
852
876
|
} break;
|
|
@@ -887,42 +911,28 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
887
911
|
} break;
|
|
888
912
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
889
913
|
case PrimitiveKind::Float32: {
|
|
890
|
-
|
|
914
|
+
float f;
|
|
915
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
891
916
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
892
917
|
return;
|
|
893
918
|
}
|
|
894
919
|
|
|
895
|
-
float f = GetNumber<float>(value);
|
|
896
|
-
|
|
897
920
|
memset((uint8_t *)&out_reg->xmm0 + 4, 0, 4);
|
|
898
921
|
memcpy(&out_reg->xmm0, &f, 4);
|
|
899
922
|
} break;
|
|
900
923
|
case PrimitiveKind::Float64: {
|
|
901
|
-
|
|
924
|
+
double d;
|
|
925
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
902
926
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
903
927
|
return;
|
|
904
928
|
}
|
|
905
929
|
|
|
906
|
-
double d = GetNumber<double>(value);
|
|
907
930
|
out_reg->xmm0 = d;
|
|
908
931
|
} break;
|
|
909
932
|
case PrimitiveKind::Callback: {
|
|
910
933
|
void *ptr;
|
|
911
|
-
|
|
912
|
-
if (value.IsFunction()) {
|
|
913
|
-
Napi::Function func2 = value.As<Napi::Function>();
|
|
914
|
-
|
|
915
|
-
ptr = ReserveTrampoline(type->ref.proto, func2);
|
|
916
|
-
if (!ptr) [[unlikely]]
|
|
917
|
-
return;
|
|
918
|
-
} else if (CheckValueTag(value, type->ref.marker)) {
|
|
919
|
-
ptr = value.As<Napi::External<void>>().Data();
|
|
920
|
-
} else if (IsNullOrUndefined(value)) {
|
|
921
|
-
ptr = nullptr;
|
|
922
|
-
} else {
|
|
923
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
934
|
+
if (!PushCallback(value, type, &ptr)) [[unlikely]]
|
|
924
935
|
return;
|
|
925
|
-
}
|
|
926
936
|
|
|
927
937
|
out_reg->rax = (uint64_t)ptr;
|
|
928
938
|
} break;
|
|
@@ -936,12 +946,6 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
936
946
|
err_guard.Disable();
|
|
937
947
|
}
|
|
938
948
|
|
|
939
|
-
void *GetTrampoline(int16_t idx, const FunctionInfo *proto)
|
|
940
|
-
{
|
|
941
|
-
bool xmm = proto->forward_fp || IsFloat(proto->ret.type);
|
|
942
|
-
return Trampolines[idx][xmm];
|
|
943
|
-
}
|
|
944
|
-
|
|
945
949
|
}
|
|
946
950
|
|
|
947
951
|
#endif
|
|
@@ -148,42 +148,12 @@ SYMBOL(ForwardCallXDD):
|
|
|
148
148
|
.global SYMBOL(RelayCallback)
|
|
149
149
|
.global SYMBOL(CallSwitchStack)
|
|
150
150
|
|
|
151
|
-
# First, make a copy of
|
|
151
|
+
# First, make a copy of argument registers.
|
|
152
152
|
# Then call the C function RelayCallback with the following arguments:
|
|
153
153
|
# static trampoline ID, a pointer to the saved GPR array, a pointer to the stack
|
|
154
154
|
# arguments of this call, and a pointer to a struct that will contain the result registers.
|
|
155
155
|
# After the call, simply load these registers from the output struct.
|
|
156
156
|
.macro trampoline id
|
|
157
|
-
.cfi_startproc
|
|
158
|
-
.cfi_def_cfa rsp, 8
|
|
159
|
-
ENDBR64
|
|
160
|
-
subq $152, %rsp
|
|
161
|
-
.cfi_def_cfa rsp, 160
|
|
162
|
-
movq %rdi, 0(%rsp)
|
|
163
|
-
movq %rsi, 8(%rsp)
|
|
164
|
-
movq %rdx, 16(%rsp)
|
|
165
|
-
movq %rcx, 24(%rsp)
|
|
166
|
-
movq %r8, 32(%rsp)
|
|
167
|
-
movq %r9, 40(%rsp)
|
|
168
|
-
movq $\id, %rdi
|
|
169
|
-
movq %rsp, %rsi
|
|
170
|
-
leaq 160(%rsp), %rdx
|
|
171
|
-
leaq 112(%rsp), %rcx
|
|
172
|
-
#if defined(__linux__)
|
|
173
|
-
call *RelayCallback@GOTPCREL(%rip)
|
|
174
|
-
#else
|
|
175
|
-
call SYMBOL(RelayCallback)
|
|
176
|
-
#endif
|
|
177
|
-
movq 112(%rsp), %rax
|
|
178
|
-
movq 120(%rsp), %rdx
|
|
179
|
-
addq $152, %rsp
|
|
180
|
-
.cfi_def_cfa rsp, 8
|
|
181
|
-
ret
|
|
182
|
-
.cfi_endproc
|
|
183
|
-
.endm
|
|
184
|
-
|
|
185
|
-
# Same thing, but also forward the XMM argument registers and load the XMM result registers.
|
|
186
|
-
.macro trampoline_vec id
|
|
187
157
|
.cfi_startproc
|
|
188
158
|
.cfi_def_cfa rsp, 8
|
|
189
159
|
ENDBR64
|