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
@@ -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 *args_ptr = nullptr;
229
- uint64_t *gpr_ptr = nullptr;
230
- uint64_t *xmm_ptr = nullptr;
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
- // Return through registers unless it's too big
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
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
256
+ const ParameterInfo &param = 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
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
269
+ const ParameterInfo &param = 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
- for (Size i = 0; i < func->parameters.len; i++) {
267
- const ParameterInfo &param = func->parameters[i];
268
- K_ASSERT(param.directions >= 1 && param.directions <= 3);
282
+ LOOP {
283
+ CASE(Void) { K_UNREACHABLE(); };
269
284
 
270
- Napi::Value value = info[param.offset];
285
+ CASE(Bool) {
286
+ const ParameterInfo &param = func->parameters[i];
287
+ Napi::Value value = info[param.offset];
271
288
 
272
- switch (param.type->primitive) {
273
- case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
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
- case PrimitiveKind::Bool: {
276
- if (!value.IsBoolean()) [[unlikely]] {
277
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argmument %2, expected boolean", GetValueType(instance, value));
278
- return false;
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 &param = func->parameters[i];
315
+ Napi::Value value = info[param.offset];
280
316
 
281
- bool b = value.As<Napi::Boolean>();
282
- *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)b;
283
- } break;
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
- *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
304
- } break;
305
- case PrimitiveKind::String16: {
306
- const char16_t *str16;
307
- if (!PushString16(value, param.directions, &str16)) [[unlikely]]
308
- return false;
321
+ *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
322
+ };
323
+ CASE(String16) {
324
+ const ParameterInfo &param = func->parameters[i];
325
+ Napi::Value value = info[param.offset];
309
326
 
310
- *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
311
- } break;
312
- case PrimitiveKind::String32: {
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
- *(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
318
- } break;
319
- case PrimitiveKind::Pointer: {
320
- void *ptr;
321
- if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
322
- return false;
331
+ *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
332
+ };
333
+ CASE(String32) {
334
+ const ParameterInfo &param = func->parameters[i];
335
+ Napi::Value value = info[param.offset];
323
336
 
324
- *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
325
- } break;
326
- case PrimitiveKind::Record:
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
- Napi::Object obj = value.As<Napi::Object>();
341
+ *(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
342
+ };
334
343
 
335
- if (param.gpr_count || param.xmm_count) {
336
- K_ASSERT(param.type->size <= 16);
344
+ CASE(Pointer) {
345
+ const ParameterInfo &param = func->parameters[i];
346
+ Napi::Value value = info[param.offset];
337
347
 
338
- uint64_t buf[2] = {};
339
- if (!PushObject(obj, param.type, (uint8_t *)buf))
340
- return false;
348
+ void *ptr;
349
+ if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
350
+ return false;
341
351
 
342
- if (param.gpr_first) {
343
- *(gpr_ptr++) = buf[0];
344
- if (param.gpr_count == 2) {
345
- *(gpr_ptr++) = buf[1];
346
- } else if (param.xmm_count == 1) {
347
- *(xmm_ptr++) = buf[1];
348
- }
349
- } else {
350
- *(xmm_ptr++) = buf[0];
351
- if (param.xmm_count == 2) {
352
- *(xmm_ptr++) = buf[1];
353
- } else if (param.gpr_count == 1) {
354
- *(gpr_ptr++) = buf[1];
355
- }
352
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
353
+ };
354
+
355
+ CASE(Record) OR(Union) {
356
+ const ParameterInfo &param = 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
- } break;
364
- case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
365
- case PrimitiveKind::Float32: {
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
- float f = GetNumber<float>(value);
372
- uint64_t *ptr = (param.xmm_count ? xmm_ptr : args_ptr)++;
397
+ CASE(Float32) {
398
+ const ParameterInfo &param = func->parameters[i];
399
+ Napi::Value value = info[param.offset];
373
400
 
374
- memset((uint8_t *)ptr + 4, 0, 4);
375
- *(float *)ptr = f;
376
- } break;
377
- case PrimitiveKind::Float64: {
378
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
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
- double d = GetNumber<double>(value);
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
- *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
392
- } break;
409
+ memset((uint8_t *)ptr + 4, 0, 4);
410
+ *(float *)ptr = f;
411
+ };
412
+ CASE(Float64) {
413
+ const ParameterInfo &param = func->parameters[i];
414
+ Napi::Value value = info[param.offset];
393
415
 
394
- case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
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 &param = 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
- if (ptr2) {
684
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
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
- arguments.Append(external);
688
- } else {
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
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
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
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
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
- if (!value.IsBoolean()) [[unlikely]] {
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
- uint8_t *ptr;
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
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
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
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
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 the GPR argument registers (rdi, rsi, rdx, rcx, r8, r9).
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