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.
Files changed (50) hide show
  1. package/build/koffi/darwin_arm64/koffi.node +0 -0
  2. package/build/koffi/darwin_x64/koffi.node +0 -0
  3. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  4. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  5. package/build/koffi/freebsd_x64/koffi.node +0 -0
  6. package/build/koffi/linux_arm64/koffi.node +0 -0
  7. package/build/koffi/linux_armhf/koffi.node +0 -0
  8. package/build/koffi/linux_ia32/koffi.node +0 -0
  9. package/build/koffi/linux_loong64/koffi.node +0 -0
  10. package/build/koffi/linux_riscv64d/koffi.node +0 -0
  11. package/build/koffi/linux_x64/koffi.node +0 -0
  12. package/build/koffi/musl_arm64/koffi.node +0 -0
  13. package/build/koffi/musl_x64/koffi.node +0 -0
  14. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  15. package/build/koffi/openbsd_x64/koffi.node +0 -0
  16. package/build/koffi/win32_arm64/koffi.node +0 -0
  17. package/build/koffi/win32_ia32/koffi.node +0 -0
  18. package/build/koffi/win32_x64/koffi.node +0 -0
  19. package/index.d.ts +11 -9
  20. package/index.js +8 -8
  21. package/indirect.js +8 -8
  22. package/package.json +1 -1
  23. package/src/koffi/src/abi_arm32.cc +222 -219
  24. package/src/koffi/src/abi_arm32_asm.S +1 -29
  25. package/src/koffi/src/abi_arm64.cc +257 -235
  26. package/src/koffi/src/abi_arm64_asm.S +1 -32
  27. package/src/koffi/src/abi_arm64_asm.asm +1 -23
  28. package/src/koffi/src/abi_loong64_asm.S +1 -25
  29. package/src/koffi/src/abi_riscv64.cc +220 -217
  30. package/src/koffi/src/abi_riscv64_asm.S +1 -25
  31. package/src/koffi/src/abi_x64_sysv.cc +196 -192
  32. package/src/koffi/src/abi_x64_sysv_asm.S +1 -31
  33. package/src/koffi/src/abi_x64_win.cc +188 -172
  34. package/src/koffi/src/abi_x64_win_asm.S +1 -19
  35. package/src/koffi/src/abi_x64_win_asm.asm +1 -21
  36. package/src/koffi/src/abi_x86.cc +224 -189
  37. package/src/koffi/src/abi_x86_asm.S +6 -25
  38. package/src/koffi/src/abi_x86_asm.asm +9 -22
  39. package/src/koffi/src/call.cc +246 -428
  40. package/src/koffi/src/call.hh +9 -8
  41. package/src/koffi/src/ffi.cc +140 -87
  42. package/src/koffi/src/ffi.hh +12 -58
  43. package/src/koffi/src/primitives.inc +39 -0
  44. package/src/koffi/src/trampolines/armasm.inc +0 -32770
  45. package/src/koffi/src/trampolines/gnu.inc +0 -24578
  46. package/src/koffi/src/trampolines/masm32.inc +0 -32770
  47. package/src/koffi/src/trampolines/masm64.inc +0 -32770
  48. package/src/koffi/src/trampolines/prototypes.inc +16385 -16385
  49. package/src/koffi/src/util.cc +149 -107
  50. package/src/koffi/src/util.hh +76 -40
@@ -52,8 +52,6 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
52
52
  uint8_t *old_sp, Span<uint8_t> *new_stack,
53
53
  napi_value (*call)(Napi::Function *func, size_t argc, napi_value *argv));
54
54
 
55
- #include "trampolines/prototypes.inc"
56
-
57
55
  static HfaInfo IsHFA(const TypeInfo *type)
58
56
  {
59
57
  bool float32 = false;
@@ -249,22 +247,45 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
249
247
 
250
248
  bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
251
249
  {
252
- uint64_t *args_ptr = nullptr;
253
- uint64_t *gpr_ptr = nullptr;
254
- uint64_t *vec_ptr = nullptr;
250
+ uint64_t *gpr_ptr = AllocStack<uint64_t>(17 * 8 + func->args_size);
251
+ uint64_t *vec_ptr = gpr_ptr + 9;
252
+ uint64_t *args_ptr = gpr_ptr + 17;
255
253
 
256
- // Return through registers unless it's too big
257
- if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]]
258
- return false;
259
- if (!AllocStack(8 * 8, 8, &vec_ptr)) [[unlikely]]
260
- return false;
261
- if (!AllocStack(9 * 8, 8, &gpr_ptr)) [[unlikely]]
254
+ if (!gpr_ptr) [[unlikely]]
262
255
  return false;
263
256
  if (func->ret.use_memory) {
264
257
  return_ptr = AllocHeap(func->ret.type->size, 16);
265
258
  gpr_ptr[8] = (uint64_t)return_ptr;
266
259
  }
267
260
 
261
+ Size i = -1;
262
+
263
+ #if defined(__GNUC__) || defined(__clang__)
264
+ static const void *const DispatchTable[] = {
265
+ #define PRIMITIVE(Name) && Name,
266
+ #include "primitives.inc"
267
+ };
268
+
269
+ #define LOOP
270
+ #define CASE(Primitive) \
271
+ do { \
272
+ PrimitiveKind next = func->primitives[++i]; \
273
+ goto *DispatchTable[(int)next]; \
274
+ } while (false); \
275
+ Primitive:
276
+ #define OR(Primitive) \
277
+ Primitive:
278
+ #else
279
+ #define LOOP \
280
+ while (++i < func->parameters.len) \
281
+ switch (func->primitives[i])
282
+ #define CASE(Primitive) \
283
+ break; \
284
+ case PrimitiveKind::Primitive:
285
+ #define OR(Primitive) \
286
+ case PrimitiveKind::Primitive:
287
+ #endif
288
+
268
289
  #if defined(_M_ARM64EC)
269
290
  if (func->variadic) {
270
291
  gpr_ptr[4] = (uint64_t)args_ptr;
@@ -280,13 +301,15 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
280
301
  #if defined(__APPLE__)
281
302
  #define PUSH_INTEGER(CType) \
282
303
  do { \
283
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
304
+ const ParameterInfo &param = func->parameters[i]; \
305
+ Napi::Value value = info[param.offset]; \
306
+ \
307
+ CType v; \
308
+ if (!TryNumber(value, &v)) [[unlikely]] { \
284
309
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
285
310
  return false; \
286
311
  } \
287
312
  \
288
- CType v = GetNumber<CType>(value); \
289
- \
290
313
  if (param.gpr_count) [[likely]] { \
291
314
  *(gpr_ptr++) = (uint64_t)v; \
292
315
  } else { \
@@ -297,13 +320,15 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
297
320
  } while (false)
298
321
  #define PUSH_INTEGER_SWAP(CType) \
299
322
  do { \
300
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
323
+ const ParameterInfo &param = func->parameters[i]; \
324
+ Napi::Value value = info[param.offset]; \
325
+ \
326
+ CType v; \
327
+ if (!TryNumber(value, &v)) [[unlikely]] { \
301
328
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
302
329
  return false; \
303
330
  } \
304
331
  \
305
- CType v = GetNumber<CType>(value); \
306
- \
307
332
  if (param.gpr_count) [[likely]] { \
308
333
  *(gpr_ptr++) = (uint64_t)ReverseBytes(v); \
309
334
  } else { \
@@ -315,227 +340,259 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
315
340
  #else
316
341
  #define PUSH_INTEGER(CType) \
317
342
  do { \
318
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
343
+ const ParameterInfo &param = func->parameters[i]; \
344
+ Napi::Value value = info[param.offset]; \
345
+ \
346
+ CType v; \
347
+ if (!TryNumber(value, &v)) [[unlikely]] { \
319
348
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
320
349
  return false; \
321
350
  } \
322
351
  \
323
- CType v = GetNumber<CType>(value); \
324
352
  *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)v; \
325
353
  } while (false)
326
354
  #define PUSH_INTEGER_SWAP(CType) \
327
355
  do { \
328
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
356
+ const ParameterInfo &param = func->parameters[i]; \
357
+ Napi::Value value = info[param.offset]; \
358
+ \
359
+ CType v; \
360
+ if (!TryNumber(value, &v)) [[unlikely]] { \
329
361
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
330
362
  return false; \
331
363
  } \
332
364
  \
333
- CType v = GetNumber<CType>(value); \
334
365
  *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)ReverseBytes(v); \
335
366
  } while (false)
336
367
  #endif
337
368
 
338
369
  // Push arguments
339
- for (Size i = 0; i < func->parameters.len; i++) {
340
- const ParameterInfo &param = func->parameters[i];
341
- K_ASSERT(param.directions >= 1 && param.directions <= 3);
370
+ LOOP {
371
+ CASE(Void) { K_UNREACHABLE(); };
342
372
 
343
- Napi::Value value = info[param.offset];
344
-
345
- switch (param.type->primitive) {
346
- case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
347
-
348
- case PrimitiveKind::Bool: {
349
- if (!value.IsBoolean()) [[unlikely]] {
350
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
351
- return false;
352
- }
373
+ CASE(Bool) {
374
+ const ParameterInfo &param = func->parameters[i];
375
+ Napi::Value value = info[param.offset];
353
376
 
354
- bool b = value.As<Napi::Boolean>();
377
+ bool b;
378
+ if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
379
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
380
+ return false;
381
+ }
355
382
 
356
383
  #if defined(__APPLE__)
357
- if (param.gpr_count) [[likely]] {
358
- *(gpr_ptr++) = (uint64_t)b;
359
- } else {
360
- *(uint8_t *)args_ptr = b;
361
- args_ptr = (uint64_t *)((uint8_t *)args_ptr + 1);
362
- }
384
+ if (param.gpr_count) [[likely]] {
385
+ *(gpr_ptr++) = (uint64_t)b;
386
+ } else {
387
+ *(uint8_t *)args_ptr = b;
388
+ args_ptr = (uint64_t *)((uint8_t *)args_ptr + 1);
389
+ }
363
390
  #else
364
- *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)b;
391
+ *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)b;
365
392
  #endif
366
- } break;
367
- case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
368
- case PrimitiveKind::UInt8: { PUSH_INTEGER(uint8_t); } break;
369
- case PrimitiveKind::Int16: { PUSH_INTEGER(int16_t); } break;
370
- case PrimitiveKind::Int16S: { PUSH_INTEGER_SWAP(int16_t); } break;
371
- case PrimitiveKind::UInt16: { PUSH_INTEGER(uint16_t); } break;
372
- case PrimitiveKind::UInt16S: { PUSH_INTEGER_SWAP(uint16_t); } break;
373
- case PrimitiveKind::Int32: { PUSH_INTEGER(int32_t); } break;
374
- case PrimitiveKind::Int32S: { PUSH_INTEGER_SWAP(int32_t); } break;
375
- case PrimitiveKind::UInt32: { PUSH_INTEGER(uint32_t); } break;
376
- case PrimitiveKind::UInt32S: { PUSH_INTEGER_SWAP(uint32_t); } break;
377
- case PrimitiveKind::Int64: { PUSH_INTEGER(int64_t); } break;
378
- case PrimitiveKind::Int64S: { PUSH_INTEGER_SWAP(int64_t); } break;
379
- case PrimitiveKind::UInt64: { PUSH_INTEGER(uint64_t); } break;
380
- case PrimitiveKind::UInt64S: { PUSH_INTEGER_SWAP(uint64_t); } break;
381
- case PrimitiveKind::String: {
382
- const char *str;
383
- if (!PushString(value, param.directions, &str)) [[unlikely]]
384
- return false;
393
+ };
394
+
395
+ CASE(Int8) { PUSH_INTEGER(int8_t); };
396
+ CASE(UInt8) { PUSH_INTEGER(uint8_t); };
397
+ CASE(Int16) { PUSH_INTEGER(int16_t); };
398
+ CASE(Int16S) { PUSH_INTEGER_SWAP(int16_t); };
399
+ CASE(UInt16) { PUSH_INTEGER(uint16_t); };
400
+ CASE(UInt16S) { PUSH_INTEGER_SWAP(uint16_t); };
401
+ CASE(Int32) { PUSH_INTEGER(int32_t); };
402
+ CASE(Int32S) { PUSH_INTEGER_SWAP(int32_t); };
403
+ CASE(UInt32) { PUSH_INTEGER(uint32_t); };
404
+ CASE(UInt32S) { PUSH_INTEGER_SWAP(uint32_t); };
405
+ CASE(Int64) { PUSH_INTEGER(int64_t); };
406
+ CASE(Int64S) { PUSH_INTEGER_SWAP(int64_t); };
407
+ CASE(UInt64) { PUSH_INTEGER(uint64_t); };
408
+ CASE(UInt64S) { PUSH_INTEGER_SWAP(uint64_t); };
409
+
410
+ CASE(String) {
411
+ const ParameterInfo &param = func->parameters[i];
412
+ Napi::Value value = info[param.offset];
413
+
414
+ const char *str;
415
+ if (!PushString(value, param.directions, &str)) [[unlikely]]
416
+ return false;
385
417
 
386
418
  #if defined(__APPLE__)
387
- args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
419
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
388
420
  #endif
389
- *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
390
- } break;
391
- case PrimitiveKind::String16: {
392
- const char16_t *str16;
393
- if (!PushString16(value, param.directions, &str16)) [[unlikely]]
394
- return false;
421
+ *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
422
+ };
423
+ CASE(String16) {
424
+ const ParameterInfo &param = func->parameters[i];
425
+ Napi::Value value = info[param.offset];
426
+
427
+ const char16_t *str16;
428
+ if (!PushString16(value, param.directions, &str16)) [[unlikely]]
429
+ return false;
395
430
 
396
431
  #if defined(__APPLE__)
397
- args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
432
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
398
433
  #endif
399
- *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
400
- } break;
401
- case PrimitiveKind::String32: {
402
- const char32_t *str32;
403
- if (!PushString32(value, param.directions, &str32)) [[unlikely]]
404
- return false;
434
+ *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
435
+ };
436
+ CASE(String32) {
437
+ const ParameterInfo &param = func->parameters[i];
438
+ Napi::Value value = info[param.offset];
439
+
440
+ const char32_t *str32;
441
+ if (!PushString32(value, param.directions, &str32)) [[unlikely]]
442
+ return false;
405
443
 
406
444
  #if defined(__APPLE__)
407
- args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
445
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
408
446
  #endif
409
- *(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
410
- } break;
411
- case PrimitiveKind::Pointer: {
412
- void *ptr;
413
- if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
414
- return false;
447
+ *(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
448
+ };
449
+
450
+ CASE(Pointer) {
451
+ const ParameterInfo &param = func->parameters[i];
452
+ Napi::Value value = info[param.offset];
453
+
454
+ void *ptr;
455
+ if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
456
+ return false;
415
457
 
416
458
  #if defined(__APPLE__)
417
- args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
459
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
418
460
  #endif
419
- *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
420
- } break;
421
- case PrimitiveKind::Record:
422
- case PrimitiveKind::Union: {
423
- if (!IsObject(value)) [[unlikely]] {
424
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
425
- return false;
426
- }
461
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
462
+ };
427
463
 
428
- Napi::Object obj = value.As<Napi::Object>();
464
+ CASE(Record) OR(Union) {
465
+ const ParameterInfo &param = func->parameters[i];
466
+ Napi::Value value = info[param.offset];
429
467
 
430
- if (param.vec_count) { // HFA
431
- uint8_t *ptr = (uint8_t *)vec_ptr;
468
+ if (!IsObject(value)) [[unlikely]] {
469
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
470
+ return false;
471
+ }
432
472
 
433
- if (!PushObject(obj, param.type, ptr))
434
- return false;
435
- ExpandFloats(ptr, param.vec_count, param.vec_bytes);
473
+ Napi::Object obj = value.As<Napi::Object>();
436
474
 
437
- vec_ptr += param.vec_count;
438
- } else if (!param.use_memory) {
439
- if (param.gpr_count) {
440
- K_ASSERT(param.type->align <= 8);
475
+ if (param.vec_count) { // HFA
476
+ uint8_t *ptr = (uint8_t *)vec_ptr;
441
477
 
442
- if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
443
- return false;
444
- gpr_ptr += param.gpr_count;
445
- } else if (param.type->size) {
478
+ if (!PushObject(obj, param.type, ptr))
479
+ return false;
480
+ ExpandFloats(ptr, param.vec_count, param.vec_bytes);
481
+
482
+ vec_ptr += param.vec_count;
483
+ } else if (!param.use_memory) {
484
+ if (param.gpr_count) {
485
+ K_ASSERT(param.type->align <= 8);
486
+
487
+ if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
488
+ return false;
489
+ gpr_ptr += param.gpr_count;
490
+ } else if (param.type->size) {
446
491
  #if defined(__APPLE__)
447
- args_ptr = AlignUp(args_ptr, 8);
492
+ args_ptr = AlignUp(args_ptr, 8);
448
493
  #endif
449
- if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
450
- return false;
451
- args_ptr += (param.type->size + 7) / 8;
452
- }
453
- } else {
454
- uint8_t *ptr = AllocHeap(param.type->size, 16);
494
+ if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
495
+ return false;
496
+ args_ptr += (param.type->size + 7) / 8;
497
+ }
498
+ } else {
499
+ uint8_t *ptr = AllocHeap(param.type->size, 16);
455
500
 
456
- if (param.gpr_count) {
457
- K_ASSERT(param.gpr_count == 1);
458
- K_ASSERT(param.vec_count == 0);
501
+ if (param.gpr_count) {
502
+ K_ASSERT(param.gpr_count == 1);
503
+ K_ASSERT(param.vec_count == 0);
459
504
 
460
- *(uint8_t **)(gpr_ptr++) = ptr;
461
- } else {
505
+ *(uint8_t **)(gpr_ptr++) = ptr;
506
+ } else {
462
507
  #if defined(__APPLE__)
463
- args_ptr = AlignUp(args_ptr, 8);
508
+ args_ptr = AlignUp(args_ptr, 8);
464
509
  #endif
465
- *(uint8_t **)(args_ptr++) = ptr;
466
- }
467
-
468
- if (!PushObject(obj, param.type, ptr))
469
- return false;
510
+ *(uint8_t **)(args_ptr++) = ptr;
470
511
  }
471
- } break;
472
- case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
473
- case PrimitiveKind::Float32: {
474
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
475
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
512
+
513
+ if (!PushObject(obj, param.type, ptr))
476
514
  return false;
477
- }
515
+ }
516
+ };
517
+ CASE(Array) { K_UNREACHABLE(); };
478
518
 
479
- float f = GetNumber<float>(value);
519
+ CASE(Float32) {
520
+ const ParameterInfo &param = func->parameters[i];
521
+ Napi::Value value = info[param.offset];
480
522
 
481
- if (param.vec_count) [[likely]] {
482
- memset((uint8_t *)vec_ptr + 4, 0, 4);
483
- *(float *)(vec_ptr++) = f;
523
+ float f;
524
+ if (!TryNumber(value, &f)) [[unlikely]] {
525
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
526
+ return false;
527
+ }
528
+
529
+ if (param.vec_count) [[likely]] {
530
+ memset((uint8_t *)vec_ptr + 4, 0, 4);
531
+ *(float *)(vec_ptr++) = f;
484
532
  #if defined(_WIN32)
485
- } else if (param.gpr_count) {
486
- memset((uint8_t *)gpr_ptr + 4, 0, 4);
487
- *(float *)(gpr_ptr++) = f;
533
+ } else if (param.gpr_count) {
534
+ memset((uint8_t *)gpr_ptr + 4, 0, 4);
535
+ *(float *)(gpr_ptr++) = f;
488
536
  #endif
489
- } else {
537
+ } else {
490
538
  #if defined(__APPLE__)
491
- args_ptr = AlignUp(args_ptr, 4);
492
- *(float *)args_ptr = f;
493
- args_ptr = (uint64_t *)((uint8_t *)args_ptr + 4);
539
+ args_ptr = AlignUp(args_ptr, 4);
540
+ *(float *)args_ptr = f;
541
+ args_ptr = (uint64_t *)((uint8_t *)args_ptr + 4);
494
542
  #else
495
- memset((uint8_t *)args_ptr + 4, 0, 4);
496
- *(float *)(args_ptr++) = f;
543
+ memset((uint8_t *)args_ptr + 4, 0, 4);
544
+ *(float *)(args_ptr++) = f;
497
545
  #endif
498
- }
499
- } break;
500
- case PrimitiveKind::Float64: {
501
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
502
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
503
- return false;
504
- }
546
+ }
547
+ };
548
+ CASE(Float64) {
549
+ const ParameterInfo &param = func->parameters[i];
550
+ Napi::Value value = info[param.offset];
505
551
 
506
- double d = GetNumber<double>(value);
552
+ double d;
553
+ if (!TryNumber(value, &d)) [[unlikely]] {
554
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
555
+ return false;
556
+ }
507
557
 
508
- if (param.vec_count) [[likely]] {
509
- *(double *)(vec_ptr++) = d;
558
+ if (param.vec_count) [[likely]] {
559
+ *(double *)(vec_ptr++) = d;
510
560
  #if defined(_WIN32)
511
- } else if (param.gpr_count) {
512
- *(double *)(gpr_ptr++) = d;
561
+ } else if (param.gpr_count) {
562
+ *(double *)(gpr_ptr++) = d;
513
563
  #endif
514
- } else {
564
+ } else {
515
565
  #if defined(__APPLE__)
516
- args_ptr = AlignUp(args_ptr, 8);
566
+ args_ptr = AlignUp(args_ptr, 8);
517
567
  #endif
518
- *(double *)(args_ptr++) = d;
519
- }
520
- } break;
521
- case PrimitiveKind::Callback: {
522
- void *ptr;
523
- if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
524
- return false;
568
+ *(double *)(args_ptr++) = d;
569
+ }
570
+ };
571
+
572
+ CASE(Callback) {
573
+ const ParameterInfo &param = func->parameters[i];
574
+ Napi::Value value = info[param.offset];
575
+
576
+ void *ptr;
577
+ if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
578
+ return false;
525
579
 
526
580
  #if defined(__APPLE__)
527
- args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
581
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
528
582
  #endif
529
- *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
530
- } break;
583
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
584
+ };
531
585
 
532
- case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
533
- }
586
+ CASE(Prototype) { /* End loop */ };
534
587
  }
535
588
 
536
589
  #undef PUSH_INTEGER_SWAP
537
590
  #undef PUSH_INTEGER
538
591
 
592
+ #undef OR
593
+ #undef CASE
594
+ #undef LOOP
595
+
539
596
  new_sp = mem->stack.end();
540
597
 
541
598
  return true;
@@ -653,17 +710,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
653
710
  case PrimitiveKind::String: return result.ptr ? Napi::String::New(env, (const char *)result.ptr) : env.Null();
654
711
  case PrimitiveKind::String16: return result.ptr ? Napi::String::New(env, (const char16_t *)result.ptr) : env.Null();
655
712
  case PrimitiveKind::String32: return result.ptr ? MakeStringFromUTF32(env, (const char32_t *)result.ptr) : env.Null();
656
- case PrimitiveKind::Pointer:
657
- case PrimitiveKind::Callback: {
658
- if (result.ptr) {
659
- Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
660
- SetValueTag(external, func->ret.type->ref.marker);
661
-
662
- return external;
663
- } else {
664
- return env.Null();
665
- }
666
- } break;
713
+ case PrimitiveKind::Pointer: return result.ptr ? WrapPointer(env, func->ret.type->ref.type, result.ptr) : env.Null();
714
+ case PrimitiveKind::Callback: return result.ptr ? WrapCallback(env, func->ret.type->ref.type, result.ptr) : env.Null();
667
715
  case PrimitiveKind::Record:
668
716
  case PrimitiveKind::Union: {
669
717
  if (func->ret.vec_count) { // HFA
@@ -1026,22 +1074,29 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
1026
1074
  Napi::Value arg = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
1027
1075
  arguments.Append(arg);
1028
1076
  } break;
1029
- case PrimitiveKind::Pointer:
1030
- case PrimitiveKind::Callback: {
1077
+ case PrimitiveKind::Pointer: {
1031
1078
  #if defined(__APPLE__)
1032
1079
  args_ptr = AlignUp(args_ptr, 8);
1033
1080
  #endif
1034
1081
 
1035
1082
  void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
1036
1083
 
1037
- if (ptr2) {
1038
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
1039
- SetValueTag(external, param.type->ref.marker);
1084
+ Napi::Value p = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1085
+ arguments.Append(p);
1040
1086
 
1041
- arguments.Append(external);
1042
- } else {
1043
- arguments.Append(env.Null());
1087
+ if (param.type->dispose) {
1088
+ param.type->dispose(env, param.type, ptr2);
1044
1089
  }
1090
+ } break;
1091
+ case PrimitiveKind::Callback: {
1092
+ #if defined(__APPLE__)
1093
+ args_ptr = AlignUp(args_ptr, 8);
1094
+ #endif
1095
+
1096
+ void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
1097
+
1098
+ Napi::Value p = ptr2 ? WrapCallback(env, param.type->ref.type, ptr2) : env.Null();
1099
+ arguments.Append(p);
1045
1100
 
1046
1101
  if (param.type->dispose) {
1047
1102
  param.type->dispose(env, param.type, ptr2);
@@ -1148,22 +1203,22 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
1148
1203
 
1149
1204
  #define RETURN_INTEGER(CType) \
1150
1205
  do { \
1151
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
1206
+ CType v; \
1207
+ if (!TryNumber(value, &v)) [[unlikely]] { \
1152
1208
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
1153
1209
  return; \
1154
1210
  } \
1155
1211
  \
1156
- CType v = GetNumber<CType>(value); \
1157
1212
  out_reg->x0 = (uint64_t)v; \
1158
1213
  } while (false)
1159
1214
  #define RETURN_INTEGER_SWAP(CType) \
1160
1215
  do { \
1161
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
1216
+ CType v; \
1217
+ if (!TryNumber(value, &v)) [[unlikely]] { \
1162
1218
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
1163
1219
  return; \
1164
1220
  } \
1165
1221
  \
1166
- CType v = GetNumber<CType>(value); \
1167
1222
  out_reg->x0 = (uint64_t)ReverseBytes(v); \
1168
1223
  } while (false)
1169
1224
 
@@ -1171,12 +1226,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
1171
1226
  switch (type->primitive) {
1172
1227
  case PrimitiveKind::Void: {} break;
1173
1228
  case PrimitiveKind::Bool: {
1174
- if (!value.IsBoolean()) [[unlikely]] {
1229
+ bool b;
1230
+ if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
1175
1231
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
1176
1232
  return;
1177
1233
  }
1178
1234
 
1179
- bool b = value.As<Napi::Boolean>();
1180
1235
  out_reg->x0 = (uint64_t)b;
1181
1236
  } break;
1182
1237
  case PrimitiveKind::Int8: { RETURN_INTEGER(int8_t); } break;
@@ -1215,24 +1270,9 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
1215
1270
  out_reg->x0 = (uint64_t)str32;
1216
1271
  } break;
1217
1272
  case PrimitiveKind::Pointer: {
1218
- uint8_t *ptr;
1219
-
1220
- if (CheckValueTag(value, type->ref.marker)) {
1221
- ptr = value.As<Napi::External<uint8_t>>().Data();
1222
- } else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
1223
- type->ref.type->primitive == PrimitiveKind::Union)) {
1224
- Napi::Object obj = value.As<Napi::Object>();
1225
-
1226
- ptr = AllocHeap(type->ref.type->size, 16);
1227
-
1228
- if (!PushObject(obj, type->ref.type, ptr))
1229
- return;
1230
- } else if (IsNullOrUndefined(value)) {
1231
- ptr = nullptr;
1232
- } else {
1233
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
1273
+ void *ptr;
1274
+ if (!PushPointer(value, type, 1, &ptr)) [[unlikely]]
1234
1275
  return;
1235
- }
1236
1276
 
1237
1277
  out_reg->x0 = (uint64_t)ptr;
1238
1278
  } break;
@@ -1260,42 +1300,30 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
1260
1300
  } break;
1261
1301
  case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
1262
1302
  case PrimitiveKind::Float32: {
1263
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
1303
+ float f;
1304
+
1305
+ if (!TryNumber(value, &f)) [[unlikely]] {
1264
1306
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
1265
1307
  return;
1266
1308
  }
1267
1309
 
1268
- float f = GetNumber<float>(value);
1269
-
1270
1310
  memset((uint8_t *)&out_reg->d0 + 4, 0, 4);
1271
1311
  memcpy(&out_reg->d0, &f, 4);
1272
1312
  } break;
1273
1313
  case PrimitiveKind::Float64: {
1274
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
1314
+ double d;
1315
+
1316
+ if (!TryNumber(value, &d)) [[unlikely]] {
1275
1317
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
1276
1318
  return;
1277
1319
  }
1278
1320
 
1279
- double d = GetNumber<double>(value);
1280
1321
  out_reg->d0 = d;
1281
1322
  } break;
1282
1323
  case PrimitiveKind::Callback: {
1283
1324
  void *ptr;
1284
-
1285
- if (value.IsFunction()) {
1286
- Napi::Function func2 = value.As<Napi::Function>();
1287
-
1288
- ptr = ReserveTrampoline(type->ref.proto, func2);
1289
- if (!ptr) [[unlikely]]
1290
- return;
1291
- } else if (CheckValueTag(value, type->ref.marker)) {
1292
- ptr = value.As<Napi::External<void>>().Data();
1293
- } else if (IsNullOrUndefined(value)) {
1294
- ptr = nullptr;
1295
- } else {
1296
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
1325
+ if (!PushCallback(value, type, &ptr)) [[unlikely]]
1297
1326
  return;
1298
- }
1299
1327
 
1300
1328
  out_reg->x0 = (uint64_t)ptr;
1301
1329
  } break;
@@ -1309,12 +1337,6 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
1309
1337
  err_guard.Disable();
1310
1338
  }
1311
1339
 
1312
- void *GetTrampoline(int16_t idx, const FunctionInfo *proto)
1313
- {
1314
- bool vec = proto->forward_fp || IsFloat(proto->ret.type);
1315
- return Trampolines[idx][vec];
1316
- }
1317
-
1318
1340
  }
1319
1341
 
1320
1342
  #endif