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
@@ -42,8 +42,6 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
42
42
  uint8_t *old_sp, Span<uint8_t> *new_stack,
43
43
  napi_value (*call)(Napi::Function *func, size_t argc, napi_value *argv));
44
44
 
45
- #include "trampolines/prototypes.inc"
46
-
47
45
  static int IsHFA(const TypeInfo *type)
48
46
  {
49
47
  #if defined(__ARM_PCS_VFP)
@@ -201,54 +199,73 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
201
199
 
202
200
  bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
203
201
  {
204
- uint32_t *args_ptr = nullptr;
205
- uint32_t *gpr_ptr = nullptr;
206
- uint32_t *vec_ptr = nullptr;
207
-
208
- // Unlike other call conventions, here we put the general-purpose
209
- // registers just before the stack (so behind the vector ones).
210
- // In the armv7hf calling convention, some arguments can end up
211
- // partially in GPR, partially in the stack.
212
- if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]]
213
- return false;
214
- if (!AllocStack(4 * 4, 8, &gpr_ptr)) [[unlikely]]
215
- return false;
216
- if (!AllocStack(8 * 8, 8, &vec_ptr)) [[unlikely]]
202
+ // Unlike other call conventions, here we put the general-purpose registers before the stack, behind the vector ones).
203
+ // In the armv7hf calling convention, some arguments can end up partially in GPR, partially in the stack.
204
+ uint32_t *vec_ptr = AllocStack<uint32_t>(20 * 4 + func->args_size);
205
+ uint32_t *gpr_ptr = vec_ptr + 16;
206
+ uint32_t *args_ptr = vec_ptr + 20;
207
+
208
+ if (!vec_ptr) [[unlikely]]
217
209
  return false;
218
210
  if (func->ret.use_memory) {
219
211
  return_ptr = AllocHeap(func->ret.type->size, 16);
220
212
  *(uint8_t **)(gpr_ptr++) = return_ptr;
221
213
  }
222
214
 
215
+ Size i = -1;
216
+
217
+ static const void *const DispatchTable[] = {
218
+ #define PRIMITIVE(Name) && Name,
219
+ #include "primitives.inc"
220
+ };
221
+
222
+ #define LOOP
223
+ #define CASE(Primitive) \
224
+ do { \
225
+ PrimitiveKind next = func->primitives[++i]; \
226
+ goto *DispatchTable[(int)next]; \
227
+ } while (false); \
228
+ Primitive:
229
+ #define OR(Primitive) \
230
+ Primitive:
231
+
223
232
  #define PUSH_INTEGER_32(CType) \
224
233
  do { \
225
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
234
+ const ParameterInfo &param = func->parameters[i]; \
235
+ Napi::Value value = info[param.offset]; \
236
+ \
237
+ CType v; \
238
+ if (!TryNumber(value, &v)) [[unlikely]] { \
226
239
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
227
240
  return false; \
228
241
  } \
229
242
  \
230
- CType v = GetNumber<CType>(value); \
231
243
  *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)v; \
232
244
  } while (false)
233
245
  #define PUSH_INTEGER_32_SWAP(CType) \
234
246
  do { \
235
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
247
+ const ParameterInfo &param = func->parameters[i]; \
248
+ Napi::Value value = info[param.offset]; \
249
+ \
250
+ CType v; \
251
+ if (!TryNumber(value, &v)) [[unlikely]] { \
236
252
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
237
253
  return false; \
238
254
  } \
239
255
  \
240
- CType v = GetNumber<CType>(value); \
241
256
  *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)ReverseBytes(v); \
242
257
  } while (false)
243
258
  #define PUSH_INTEGER_64(CType) \
244
259
  do { \
245
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
260
+ const ParameterInfo &param = func->parameters[i]; \
261
+ Napi::Value value = info[param.offset]; \
262
+ \
263
+ CType v; \
264
+ if (!TryNumber(value, &v)) [[unlikely]] { \
246
265
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
247
266
  return false; \
248
267
  } \
249
268
  \
250
- CType v = GetNumber<CType>(value); \
251
- \
252
269
  if (param.gpr_count) [[likely]] { \
253
270
  gpr_ptr = AlignUp(gpr_ptr, 8); \
254
271
  *(uint64_t *)gpr_ptr = (uint64_t)v; \
@@ -261,13 +278,15 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
261
278
  } while (false)
262
279
  #define PUSH_INTEGER_64_SWAP(CType) \
263
280
  do { \
264
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
281
+ const ParameterInfo &param = func->parameters[i]; \
282
+ Napi::Value value = info[param.offset]; \
283
+ \
284
+ CType v; \
285
+ if (!TryNumber(value, &v)) [[unlikely]] { \
265
286
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
266
287
  return false; \
267
288
  } \
268
289
  \
269
- CType v = GetNumber<CType>(value); \
270
- \
271
290
  if (param.gpr_count) [[likely]] { \
272
291
  gpr_ptr = AlignUp(gpr_ptr, 8); \
273
292
  *(uint64_t *)gpr_ptr = (uint64_t)ReverseBytes(v); \
@@ -279,148 +298,170 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
279
298
  } \
280
299
  } while (false)
281
300
 
282
- // Push arguments
283
- for (Size i = 0; i < func->parameters.len; i++) {
284
- const ParameterInfo &param = func->parameters[i];
285
- K_ASSERT(param.directions >= 1 && param.directions <= 3);
301
+ LOOP {
302
+ CASE(Void) { K_UNREACHABLE(); };
286
303
 
287
- Napi::Value value = info[param.offset];
304
+ CASE(Bool) {
305
+ const ParameterInfo &param = func->parameters[i];
306
+ Napi::Value value = info[param.offset];
288
307
 
289
- switch (param.type->primitive) {
290
- case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
308
+ bool b;
309
+ if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
310
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
311
+ return false;
312
+ }
291
313
 
292
- case PrimitiveKind::Bool: {
293
- if (!value.IsBoolean()) [[unlikely]] {
294
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
295
- return false;
296
- }
314
+ *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)b;
315
+ };
316
+
317
+ CASE(Int8) { PUSH_INTEGER_32(int8_t); };
318
+ CASE(UInt8) { PUSH_INTEGER_32(uint8_t); };
319
+ CASE(Int16) { PUSH_INTEGER_32(int16_t); };
320
+ CASE(Int16S) { PUSH_INTEGER_32_SWAP(int16_t); };
321
+ CASE(UInt16) { PUSH_INTEGER_32(uint16_t); };
322
+ CASE(UInt16S) { PUSH_INTEGER_32_SWAP(uint16_t); };
323
+ CASE(Int32) { PUSH_INTEGER_32(int32_t); };
324
+ CASE(Int32S) { PUSH_INTEGER_32_SWAP(int32_t); };
325
+ CASE(UInt32) { PUSH_INTEGER_32(uint32_t); };
326
+ CASE(UInt32S) { PUSH_INTEGER_32_SWAP(uint32_t); };
327
+ CASE(Int64) { PUSH_INTEGER_64(int64_t); };
328
+ CASE(Int64S) { PUSH_INTEGER_64_SWAP(int64_t); };
329
+ CASE(UInt64) { PUSH_INTEGER_64(uint64_t); };
330
+ CASE(UInt64S) { PUSH_INTEGER_64_SWAP(uint64_t); };
331
+
332
+ CASE(String) {
333
+ const ParameterInfo &param = func->parameters[i];
334
+ Napi::Value value = info[param.offset];
297
335
 
298
- bool b = value.As<Napi::Boolean>();
299
- *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)b;
300
- } break;
301
- case PrimitiveKind::Int8: { PUSH_INTEGER_32(int8_t); } break;
302
- case PrimitiveKind::UInt8: { PUSH_INTEGER_32(uint8_t); } break;
303
- case PrimitiveKind::Int16: { PUSH_INTEGER_32(int16_t); } break;
304
- case PrimitiveKind::Int16S: { PUSH_INTEGER_32_SWAP(int16_t); } break;
305
- case PrimitiveKind::UInt16: { PUSH_INTEGER_32(uint16_t); } break;
306
- case PrimitiveKind::UInt16S: { PUSH_INTEGER_32_SWAP(uint16_t); } break;
307
- case PrimitiveKind::Int32: { PUSH_INTEGER_32(int32_t); } break;
308
- case PrimitiveKind::Int32S: { PUSH_INTEGER_32_SWAP(int32_t); } break;
309
- case PrimitiveKind::UInt32: { PUSH_INTEGER_32(uint32_t); } break;
310
- case PrimitiveKind::UInt32S: { PUSH_INTEGER_32_SWAP(uint32_t); } break;
311
- case PrimitiveKind::Int64: { PUSH_INTEGER_64(int64_t); } break;
312
- case PrimitiveKind::Int64S: { PUSH_INTEGER_64_SWAP(int64_t); } break;
313
- case PrimitiveKind::UInt64: { PUSH_INTEGER_64(uint64_t); } break;
314
- case PrimitiveKind::UInt64S: { PUSH_INTEGER_64_SWAP(uint64_t); } break;
315
- case PrimitiveKind::String: {
316
- const char *str;
317
- if (!PushString(value, param.directions, &str)) [[unlikely]]
318
- return false;
336
+ const char *str;
337
+ if (!PushString(value, param.directions, &str)) [[unlikely]]
338
+ return false;
319
339
 
320
- *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
321
- } break;
322
- case PrimitiveKind::String16: {
323
- const char16_t *str16;
324
- if (!PushString16(value, param.directions, &str16)) [[unlikely]]
325
- return false;
340
+ *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
341
+ };
342
+ CASE(String16) {
343
+ const ParameterInfo &param = func->parameters[i];
344
+ Napi::Value value = info[param.offset];
326
345
 
327
- *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
328
- } break;
329
- case PrimitiveKind::String32: {
330
- const char32_t *str32;
331
- if (!PushString32(value, param.directions, &str32)) [[unlikely]]
332
- return false;
346
+ const char16_t *str16;
347
+ if (!PushString16(value, param.directions, &str16)) [[unlikely]]
348
+ return false;
333
349
 
334
- *(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
335
- } break;
336
- case PrimitiveKind::Pointer: {
337
- void *ptr;
338
- if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
339
- return false;
350
+ *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
351
+ };
352
+ CASE(String32) {
353
+ const ParameterInfo &param = func->parameters[i];
354
+ Napi::Value value = info[param.offset];
340
355
 
341
- *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
342
- } break;
343
- case PrimitiveKind::Record:
344
- case PrimitiveKind::Union: {
345
- if (!IsObject(value)) [[unlikely]] {
346
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
347
- return false;
348
- }
356
+ const char32_t *str32;
357
+ if (!PushString32(value, param.directions, &str32)) [[unlikely]]
358
+ return false;
349
359
 
350
- Napi::Object obj = value.As<Napi::Object>();
360
+ *(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
361
+ };
351
362
 
352
- if (param.vec_count) {
353
- if (!PushObject(obj, param.type, (uint8_t *)vec_ptr))
354
- return false;
355
- vec_ptr += param.vec_count;
356
- } else if (param.gpr_count) {
357
- K_ASSERT(param.type->align <= 8);
363
+ CASE(Pointer) {
364
+ const ParameterInfo &param = func->parameters[i];
365
+ Napi::Value value = info[param.offset];
358
366
 
359
- int16_t align = (param.type->align <= 4) ? 4 : 8;
360
- gpr_ptr = AlignUp(gpr_ptr, align);
367
+ void *ptr;
368
+ if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
369
+ return false;
361
370
 
362
- if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
363
- return false;
371
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
372
+ };
364
373
 
365
- gpr_ptr += param.gpr_count;
366
- args_ptr += (param.type->size - param.gpr_count * 4 + 3) / 4;
367
- } else if (param.type->size) {
368
- int16_t align = (param.type->align <= 4) ? 4 : 8;
369
- args_ptr = AlignUp(args_ptr, align);
374
+ CASE(Record) OR(Union) {
375
+ const ParameterInfo &param = func->parameters[i];
376
+ Napi::Value value = info[param.offset];
370
377
 
371
- if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
372
- return false;
373
- args_ptr += (param.type->size + 3) / 4;
374
- }
375
- } break;
376
- case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
377
- case PrimitiveKind::Float32: {
378
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
379
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
378
+ if (!IsObject(value)) [[unlikely]] {
379
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
380
+ return false;
381
+ }
382
+
383
+ Napi::Object obj = value.As<Napi::Object>();
384
+
385
+ if (param.vec_count) {
386
+ if (!PushObject(obj, param.type, (uint8_t *)vec_ptr))
380
387
  return false;
381
- }
388
+ vec_ptr += param.vec_count;
389
+ } else if (param.gpr_count) {
390
+ K_ASSERT(param.type->align <= 8);
382
391
 
383
- float f = GetNumber<float>(value);
392
+ int16_t align = (param.type->align <= 4) ? 4 : 8;
393
+ gpr_ptr = AlignUp(gpr_ptr, align);
384
394
 
385
- if (param.vec_count) [[likely]] {
386
- *(float *)(vec_ptr++) = f;
387
- } else if (param.gpr_count) {
388
- *(float *)(gpr_ptr++) = f;
389
- } else {
390
- *(float *)(args_ptr++) = f;
391
- }
392
- } break;
393
- case PrimitiveKind::Float64: {
394
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
395
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
395
+ if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
396
396
  return false;
397
- }
398
397
 
399
- double d = GetNumber<double>(value);
398
+ gpr_ptr += param.gpr_count;
399
+ args_ptr += (param.type->size - param.gpr_count * 4 + 3) / 4;
400
+ } else if (param.type->size) {
401
+ int16_t align = (param.type->align <= 4) ? 4 : 8;
402
+ args_ptr = AlignUp(args_ptr, align);
400
403
 
401
- if (param.vec_count) [[likely]] {
402
- *(double *)vec_ptr = d;
403
- vec_ptr += 2;
404
- } else if (param.gpr_count) {
405
- gpr_ptr = AlignUp(gpr_ptr, 8);
406
- *(double *)gpr_ptr = d;
407
- gpr_ptr += 2;
408
- } else {
409
- args_ptr = AlignUp(args_ptr, 8);
410
- *(double *)args_ptr = d;
411
- args_ptr += 2;
412
- }
413
- } break;
414
- case PrimitiveKind::Callback: {
415
- void *ptr;
416
- if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
404
+ if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
417
405
  return false;
406
+ args_ptr += (param.type->size + 3) / 4;
407
+ }
408
+ };
409
+ CASE(Array) { K_UNREACHABLE(); };
418
410
 
419
- *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
420
- } break;
411
+ CASE(Float32) {
412
+ const ParameterInfo &param = func->parameters[i];
413
+ Napi::Value value = info[param.offset];
421
414
 
422
- case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
423
- }
415
+ float f;
416
+ if (!TryNumber(value, &f)) [[unlikely]] {
417
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
418
+ return false;
419
+ }
420
+
421
+ if (param.vec_count) [[likely]] {
422
+ *(float *)(vec_ptr++) = f;
423
+ } else if (param.gpr_count) {
424
+ *(float *)(gpr_ptr++) = f;
425
+ } else {
426
+ *(float *)(args_ptr++) = f;
427
+ }
428
+ };
429
+ CASE(Float64) {
430
+ const ParameterInfo &param = func->parameters[i];
431
+ Napi::Value value = info[param.offset];
432
+
433
+ double d;
434
+ if (!TryNumber(value, &d)) [[unlikely]] {
435
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
436
+ return false;
437
+ }
438
+
439
+ if (param.vec_count) [[likely]] {
440
+ *(double *)vec_ptr = d;
441
+ vec_ptr += 2;
442
+ } else if (param.gpr_count) {
443
+ gpr_ptr = AlignUp(gpr_ptr, 8);
444
+ *(double *)gpr_ptr = d;
445
+ gpr_ptr += 2;
446
+ } else {
447
+ args_ptr = AlignUp(args_ptr, 8);
448
+ *(double *)args_ptr = d;
449
+ args_ptr += 2;
450
+ }
451
+ };
452
+
453
+ CASE(Callback) {
454
+ const ParameterInfo &param = func->parameters[i];
455
+ Napi::Value value = info[param.offset];
456
+
457
+ void *ptr;
458
+ if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
459
+ return false;
460
+
461
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
462
+ };
463
+
464
+ CASE(Prototype) { /* End loop */ };
424
465
  }
425
466
 
426
467
  #undef PUSH_INTEGER_64_SWAP
@@ -428,6 +469,10 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
428
469
  #undef PUSH_INTEGER_32_SWAP
429
470
  #undef PUSH_INTEGER_32
430
471
 
472
+ #undef OR
473
+ #undef CASE
474
+ #undef LOOP
475
+
431
476
  new_sp = mem->stack.end();
432
477
 
433
478
  return true;
@@ -514,17 +559,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
514
559
  case PrimitiveKind::String: return result.ptr ? Napi::String::New(env, (const char *)result.ptr) : env.Null();
515
560
  case PrimitiveKind::String16: return result.ptr ? Napi::String::New(env, (const char16_t *)result.ptr) : env.Null();
516
561
  case PrimitiveKind::String32: return result.ptr ? MakeStringFromUTF32(env, (const char32_t *)result.ptr) : env.Null();
517
- case PrimitiveKind::Pointer:
518
- case PrimitiveKind::Callback: {
519
- if (result.ptr) {
520
- Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
521
- SetValueTag(external, func->ret.type->ref.marker);
522
-
523
- return external;
524
- } else {
525
- return env.Null();
526
- }
527
- } break;
562
+ case PrimitiveKind::Pointer: return result.ptr ? WrapPointer(env, func->ret.type->ref.type, result.ptr) : env.Null();
563
+ case PrimitiveKind::Callback: return result.ptr ? WrapCallback(env, func->ret.type->ref.type, result.ptr) : env.Null();
528
564
  case PrimitiveKind::Record:
529
565
  case PrimitiveKind::Union: {
530
566
  const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
@@ -711,18 +747,21 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
711
747
  Napi::Value arg = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
712
748
  arguments.Append(arg);
713
749
  } break;
714
- case PrimitiveKind::Pointer:
715
- case PrimitiveKind::Callback: {
750
+ case PrimitiveKind::Pointer: {
716
751
  void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
717
752
 
718
- if (ptr2) {
719
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
720
- SetValueTag(external, param.type->ref.marker);
753
+ Napi::Value p = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
754
+ arguments.Append(p);
721
755
 
722
- arguments.Append(external);
723
- } else {
724
- arguments.Append(env.Null());
756
+ if (param.type->dispose) {
757
+ param.type->dispose(env, param.type, ptr2);
725
758
  }
759
+ } break;
760
+ case PrimitiveKind::Callback: {
761
+ void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
762
+
763
+ Napi::Value p = ptr2 ? WrapCallback(env, param.type->ref.type, ptr2) : env.Null();
764
+ arguments.Append(p);
726
765
 
727
766
  if (param.type->dispose) {
728
767
  param.type->dispose(env, param.type, ptr2);
@@ -825,45 +864,43 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
825
864
 
826
865
  #define RETURN_INTEGER_32(CType) \
827
866
  do { \
828
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
867
+ CType v; \
868
+ if (!TryNumber(value, &v)) [[unlikely]] { \
829
869
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for return value, expected number", GetValueType(instance, value)); \
830
870
  return; \
831
871
  } \
832
872
  \
833
- CType v = GetNumber<CType>(value); \
834
873
  out_reg->r0 = (uint32_t)v; \
835
874
  } while (false)
836
875
  #define RETURN_INTEGER_32_SWAP(CType) \
837
876
  do { \
838
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
839
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
877
+ CType v; \
878
+ if (!TryNumber(value, &v)) [[unlikely]] { \
879
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for return value, expected number", GetValueType(instance, value)); \
840
880
  return; \
841
881
  } \
842
882
  \
843
- CType v = GetNumber<CType>(value); \
844
883
  out_reg->r0 = (uint32_t)ReverseBytes(v); \
845
884
  } while (false)
846
885
  #define RETURN_INTEGER_64(CType) \
847
886
  do { \
848
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
849
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
887
+ CType v; \
888
+ if (!TryNumber(value, &v)) [[unlikely]] { \
889
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for return value, expected number", GetValueType(instance, value)); \
850
890
  return; \
851
891
  } \
852
892
  \
853
- CType v = GetNumber<CType>(value); \
854
- \
855
893
  out_reg->r0 = (uint32_t)((uint64_t)v >> 32); \
856
894
  out_reg->r1 = (uint32_t)((uint64_t)v & 0xFFFFFFFFu); \
857
895
  } while (false)
858
896
  #define RETURN_INTEGER_64_SWAP(CType) \
859
897
  do { \
860
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
861
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
898
+ CType v; \
899
+ if (!TryNumber(value, &v)) [[unlikely]] { \
900
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for return value, expected number", GetValueType(instance, value)); \
862
901
  return; \
863
902
  } \
864
903
  \
865
- CType v = ReverseBytes(GetNumber<CType>(value)); \
866
- \
867
904
  out_reg->r0 = (uint32_t)((uint64_t)v >> 32); \
868
905
  out_reg->r1 = (uint32_t)((uint64_t)v & 0xFFFFFFFFu); \
869
906
  } while (false)
@@ -872,12 +909,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
872
909
  switch (type->primitive) {
873
910
  case PrimitiveKind::Void: {} break;
874
911
  case PrimitiveKind::Bool: {
875
- if (!value.IsBoolean()) [[unlikely]] {
912
+ bool b;
913
+ if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
876
914
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
877
915
  return;
878
916
  }
879
917
 
880
- bool b = value.As<Napi::Boolean>();
881
918
  out_reg->r0 = (uint32_t)b;
882
919
  } break;
883
920
  case PrimitiveKind::Int8: { RETURN_INTEGER_32(int8_t); } break;
@@ -916,24 +953,9 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
916
953
  out_reg->r0 = (uint32_t)str32;
917
954
  } break;
918
955
  case PrimitiveKind::Pointer: {
919
- uint8_t *ptr;
920
-
921
- if (CheckValueTag(value, type->ref.marker)) {
922
- ptr = value.As<Napi::External<uint8_t>>().Data();
923
- } else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
924
- type->ref.type->primitive == PrimitiveKind::Union)) {
925
- Napi::Object obj = value.As<Napi::Object>();
926
-
927
- ptr = AllocHeap(type->ref.type->size, 16);
928
-
929
- if (!PushObject(obj, type->ref.type, ptr))
930
- return;
931
- } else if (IsNullOrUndefined(value)) {
932
- ptr = nullptr;
933
- } else {
934
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
956
+ void *ptr;
957
+ if (!PushPointer(value, type, 1, &ptr)) [[unlikely]]
935
958
  return;
936
- }
937
959
 
938
960
  out_reg->r0 = (uint32_t)ptr;
939
961
  } break;
@@ -958,12 +980,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
958
980
  } break;
959
981
  case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
960
982
  case PrimitiveKind::Float32: {
961
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
983
+ float f;
984
+ if (!TryNumber(value, &f)) [[unlikely]] {
962
985
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
963
986
  return;
964
987
  }
965
988
 
966
- float f = GetNumber<float>(value);
967
989
  #if defined(__ARM_PCS_VFP)
968
990
  memcpy(&out_reg->d0, &f, 4);
969
991
  #else
@@ -971,12 +993,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
971
993
  #endif
972
994
  } break;
973
995
  case PrimitiveKind::Float64: {
974
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
996
+ double d;
997
+ if (!TryNumber(value, &d)) [[unlikely]] {
975
998
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
976
999
  return;
977
1000
  }
978
1001
 
979
- double d = GetNumber<double>(value);
980
1002
  #if defined(__ARM_PCS_VFP)
981
1003
  out_reg->d0 = d;
982
1004
  #else
@@ -985,21 +1007,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
985
1007
  } break;
986
1008
  case PrimitiveKind::Callback: {
987
1009
  void *ptr;
988
-
989
- if (value.IsFunction()) {
990
- Napi::Function func2 = value.As<Napi::Function>();
991
-
992
- ptr = ReserveTrampoline(type->ref.proto, func2);
993
- if (!ptr) [[unlikely]]
994
- return;
995
- } else if (CheckValueTag(value, type->ref.marker)) {
996
- ptr = value.As<Napi::External<void>>().Data();
997
- } else if (IsNullOrUndefined(value)) {
998
- ptr = nullptr;
999
- } else {
1000
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
1010
+ if (!PushCallback(value, type, &ptr)) [[unlikely]]
1001
1011
  return;
1002
- }
1003
1012
 
1004
1013
  out_reg->r0 = (uint32_t)ptr;
1005
1014
  } break;
@@ -1015,12 +1024,6 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
1015
1024
  err_guard.Disable();
1016
1025
  }
1017
1026
 
1018
- void *GetTrampoline(int16_t idx, const FunctionInfo *proto)
1019
- {
1020
- bool vec = proto->forward_fp || IsFloat(proto->ret.type);
1021
- return Trampolines[idx][vec];
1022
- }
1023
-
1024
1027
  }
1025
1028
 
1026
1029
  #endif