koffi 3.0.1 → 3.1.0

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/CHANGELOG.md +32 -3
  2. package/cnoke.cjs +2 -2
  3. package/doc/benchmarks.md +1 -1
  4. package/doc/callbacks.md +7 -26
  5. package/doc/{input.md → composites.md} +161 -147
  6. package/doc/contribute.md +3 -2
  7. package/doc/index.md +0 -14
  8. package/doc/{functions.md → load.md} +54 -113
  9. package/doc/migration.md +4 -7
  10. package/doc/misc.md +0 -103
  11. package/doc/output.md +5 -11
  12. package/doc/pointers.md +76 -17
  13. package/doc/primitives.md +151 -0
  14. package/doc/start.md +3 -13
  15. package/doc/types.md +88 -0
  16. package/doc/unions.md +0 -186
  17. package/doc/values.md +134 -0
  18. package/index.d.ts +375 -308
  19. package/lib/native/base/base.cc +66 -24
  20. package/lib/native/base/base.hh +55 -153
  21. package/package.json +16 -16
  22. package/src/koffi/CMakeLists.txt +20 -17
  23. package/src/koffi/index.cjs +30 -111
  24. package/src/koffi/index.js +22 -96
  25. package/src/koffi/indirect.cjs +30 -111
  26. package/src/koffi/indirect.js +24 -24
  27. package/src/koffi/src/abi/arm64.cc +48 -62
  28. package/src/koffi/src/abi/riscv64.cc +39 -57
  29. package/src/koffi/src/abi/x64sysv.cc +39 -57
  30. package/src/koffi/src/abi/x64win.cc +48 -65
  31. package/src/koffi/src/abi/x86.cc +47 -59
  32. package/src/koffi/src/call.cc +426 -209
  33. package/src/koffi/src/call.hh +7 -11
  34. package/src/koffi/src/ffi.cc +534 -303
  35. package/src/koffi/src/ffi.hh +71 -15
  36. package/src/koffi/src/parser.cc +5 -3
  37. package/src/koffi/src/parser.hh +2 -2
  38. package/src/koffi/src/static.cjs +122 -0
  39. package/src/koffi/src/static.js +125 -0
  40. package/src/koffi/src/type.cc +725 -0
  41. package/src/koffi/src/type.hh +71 -0
  42. package/src/koffi/src/util.cc +117 -1202
  43. package/src/koffi/src/util.hh +158 -156
  44. package/src/koffi/src/uv.cc +17 -11
  45. package/src/koffi/src/uv.hh +2 -1
  46. package/vendor/node-addon-api/README.md +1 -1
  47. package/vendor/node-addon-api/napi-inl.h +213 -35
  48. package/vendor/node-addon-api/napi.h +118 -7
  49. package/doc/variables.md +0 -102
  50. package/indirect.d.ts +0 -322
@@ -6,6 +6,7 @@
6
6
  #include "lib/native/base/base.hh"
7
7
  #include "../ffi.hh"
8
8
  #include "../call.hh"
9
+ #include "../type.hh"
9
10
  #include "../util.hh"
10
11
 
11
12
  #include <napi.h>
@@ -683,13 +684,8 @@ namespace {
683
684
  OP(PushAggregateReg) {
684
685
  napi_value arg = args[inst->a];
685
686
 
686
- if (!IsObject(call->env, arg)) [[unlikely]] {
687
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, args[inst->a]));
688
- return call->env.Null();
689
- }
690
-
691
687
  uint64_t buf[2];
692
- if (!call->PushObject(arg, inst->type, (uint8_t *)buf))
688
+ if (!call->PushObject(arg, inst->type, (uint8_t *)buf)) [[unlikely]]
693
689
  return call->env.Null();
694
690
 
695
691
  // The second part might be useless (if object fits in one register), in
@@ -704,12 +700,7 @@ namespace {
704
700
  OP(PushAggregateStack) {
705
701
  napi_value arg = args[inst->a];
706
702
 
707
- if (!IsObject(call->env, arg)) [[unlikely]] {
708
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
709
- return call->env.Null();
710
- }
711
-
712
- if (!call->PushObject(arg, inst->type, base + inst->b1))
703
+ if (!call->PushObject(arg, inst->type, base + inst->b1)) [[unlikely]]
713
704
  return call->env.Null();
714
705
 
715
706
  NEXT();
@@ -733,7 +724,7 @@ namespace {
733
724
  #define DISPOSE(Ptr) \
734
725
  do { \
735
726
  if (inst->type->dispose) { \
736
- inst->type->dispose(call->env, inst->type, (Ptr)); \
727
+ inst->type->dispose(call->instance, inst->type, (Ptr)); \
737
728
  } \
738
729
  } while (false)
739
730
 
@@ -761,42 +752,42 @@ namespace {
761
752
  OP(RunUInt64S) { INTEGER_SWAP(GG, uint64_t); }
762
753
  OP(RunString) {
763
754
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
764
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
755
+ napi_value value = NewString(call->env, (const char *)rax);
765
756
  DISPOSE((void *)rax);
766
757
  return value;
767
758
  }
768
759
  OP(RunString16) {
769
760
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
770
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
761
+ napi_value value = NewString(call->env, (const char16_t *)rax);
771
762
  DISPOSE((void *)rax);
772
763
  return value;
773
764
  }
774
765
  OP(RunString32) {
775
766
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
776
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
767
+ napi_value value = NewString(call->env, (const char32_t *)rax);
777
768
  DISPOSE((void *)rax);
778
769
  return value;
779
770
  }
780
771
  OP(RunPointer) {
781
772
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
782
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
773
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
783
774
  DISPOSE((void *)rax);
784
775
  return value;
785
776
  }
786
777
  OP(RunCallback) {
787
778
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
788
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
779
+ return WrapPointer(call->env, inst->type, (void *)rax);
789
780
  }
790
781
  OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
791
782
  OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
792
783
  OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
793
784
  OP(RunFloat32) {
794
785
  float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
795
- return Napi::Number::New(call->env, (double)f);
786
+ return NewFloat(call->env, f);
796
787
  }
797
788
  OP(RunFloat64) {
798
789
  double d = WRAP(ForwardCallDD(call->native, base, &call->saved_sp).xmm0);
799
- return Napi::Number::New(call->env, d);
790
+ return NewFloat(call->env, d);
800
791
  }
801
792
  OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
802
793
  OP(RunAggregateGG) {
@@ -845,42 +836,42 @@ namespace {
845
836
  OP(RunUInt64SX) { INTEGER_SWAP(GGX, uint64_t); }
846
837
  OP(RunStringX) {
847
838
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
848
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
839
+ napi_value value = NewString(call->env, (const char *)rax);
849
840
  DISPOSE((void *)rax);
850
841
  return value;
851
842
  }
852
843
  OP(RunString16X) {
853
844
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
854
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
845
+ napi_value value = NewString(call->env, (const char16_t *)rax);
855
846
  DISPOSE((void *)rax);
856
847
  return value;
857
848
  }
858
849
  OP(RunString32X) {
859
850
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
860
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
851
+ napi_value value = NewString(call->env, (const char32_t *)rax);
861
852
  DISPOSE((void *)rax);
862
853
  return value;
863
854
  }
864
855
  OP(RunPointerX) {
865
856
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
866
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
857
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
867
858
  DISPOSE((void *)rax);
868
859
  return value;
869
860
  }
870
861
  OP(RunCallbackX) {
871
862
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
872
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
863
+ return WrapPointer(call->env, inst->type, (void *)rax);
873
864
  }
874
865
  OP(RunRecordX) { K_UNREACHABLE(); return call->env.Null(); }
875
866
  OP(RunUnionX) { K_UNREACHABLE(); return call->env.Null(); }
876
867
  OP(RunArrayX) { K_UNREACHABLE(); return call->env.Null(); }
877
868
  OP(RunFloat32X) {
878
869
  float f = WRAP(ForwardCallFX(call->native, base, &call->saved_sp));
879
- return Napi::Number::New(call->env, (double)f);
870
+ return NewFloat(call->env, f);
880
871
  }
881
872
  OP(RunFloat64X) {
882
873
  double d = WRAP(ForwardCallDDX(call->native, base, &call->saved_sp).xmm0);
883
- return Napi::Number::New(call->env, d);
874
+ return NewFloat(call->env, d);
884
875
  }
885
876
  OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
886
877
  OP(RunAggregateGGX) {
@@ -919,7 +910,7 @@ namespace {
919
910
  do { \
920
911
  if (inst->type->dispose) { \
921
912
  void *ptr = *(void **)base; \
922
- inst->type->dispose(call->env, inst->type, ptr); \
913
+ inst->type->dispose(call->instance, inst->type, ptr); \
923
914
  } \
924
915
  } while (false)
925
916
  #define INTEGER(CType) \
@@ -982,42 +973,42 @@ namespace {
982
973
  OP(ReturnUInt64S) { INTEGER_SWAP(uint64_t); }
983
974
  OP(ReturnString) {
984
975
  uint64_t rax = *(uint64_t *)base;
985
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
976
+ napi_value value = NewString(call->env, (const char *)rax);
986
977
  DISPOSE();
987
978
  return value;
988
979
  }
989
980
  OP(ReturnString16) {
990
981
  uint64_t rax = *(uint64_t *)base;
991
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
982
+ napi_value value = NewString(call->env, (const char16_t *)rax);
992
983
  DISPOSE();
993
984
  return value;
994
985
  }
995
986
  OP(ReturnString32) {
996
987
  uint64_t rax = *(uint64_t *)base;
997
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
988
+ napi_value value = NewString(call->env, (const char32_t *)rax);
998
989
  DISPOSE();
999
990
  return value;
1000
991
  }
1001
992
  OP(ReturnPointer) {
1002
993
  uint64_t rax = *(uint64_t *)base;
1003
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
994
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
1004
995
  DISPOSE();
1005
996
  return value;
1006
997
  }
1007
998
  OP(ReturnCallback) {
1008
999
  uint64_t rax = *(uint64_t *)base;
1009
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
1000
+ return WrapPointer(call->env, inst->type, (void *)rax);
1010
1001
  }
1011
1002
  OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
1012
1003
  OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
1013
1004
  OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
1014
1005
  OP(ReturnFloat32) {
1015
1006
  float f = *(float *)base;
1016
- return Napi::Number::New(call->env, (double)f);
1007
+ return NewFloat(call->env, f);
1017
1008
  }
1018
1009
  OP(ReturnFloat64) {
1019
1010
  double d = *(double *)base;
1020
- return Napi::Number::New(call->env, d);
1011
+ return NewFloat(call->env, d);
1021
1012
  }
1022
1013
  OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
1023
1014
  OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
@@ -1187,30 +1178,30 @@ void CallData::Relay(Size idx, uint8_t *sp)
1187
1178
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1188
1179
  const char *str = *(const char **)src;
1189
1180
 
1190
- arguments[i] = str ? Napi::String::New(env, str) : env.Null();
1181
+ arguments[i] = NewString(env, str);
1191
1182
 
1192
1183
  if (param.type->dispose) {
1193
- param.type->dispose(env, param.type, str);
1184
+ param.type->dispose(instance, param.type, str);
1194
1185
  }
1195
1186
  } break;
1196
1187
  case PrimitiveKind::String16: {
1197
1188
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1198
1189
  const char16_t *str16 = *(const char16_t **)src;
1199
1190
 
1200
- arguments[i] = str16 ? Napi::String::New(env, str16) : env.Null();
1191
+ arguments[i] = NewString(env, str16);
1201
1192
 
1202
1193
  if (param.type->dispose) {
1203
- param.type->dispose(env, param.type, str16);
1194
+ param.type->dispose(instance, param.type, str16);
1204
1195
  }
1205
1196
  } break;
1206
1197
  case PrimitiveKind::String32: {
1207
1198
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1208
1199
  const char32_t *str32 = *(const char32_t **)src;
1209
1200
 
1210
- arguments[i] = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
1201
+ arguments[i] = NewString(env, str32);
1211
1202
 
1212
1203
  if (param.type->dispose) {
1213
- param.type->dispose(env, param.type, str32);
1204
+ param.type->dispose(instance, param.type, str32);
1214
1205
  }
1215
1206
  } break;
1216
1207
 
@@ -1218,10 +1209,10 @@ void CallData::Relay(Size idx, uint8_t *sp)
1218
1209
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1219
1210
  void *ptr2 = *(void **)src;
1220
1211
 
1221
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1212
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1222
1213
 
1223
1214
  if (param.type->dispose) {
1224
- param.type->dispose(env, param.type, ptr2);
1215
+ param.type->dispose(instance, param.type, ptr2);
1225
1216
  }
1226
1217
  } break;
1227
1218
 
@@ -1243,24 +1234,20 @@ void CallData::Relay(Size idx, uint8_t *sp)
1243
1234
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1244
1235
  float f = *(float *)src;
1245
1236
 
1246
- arguments[i] = Napi::Number::New(env, (double)f);
1237
+ arguments[i] = NewFloat(env, f);
1247
1238
  } break;
1248
1239
  case PrimitiveKind::Float64: {
1249
1240
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1250
1241
  double d = *(double *)src;
1251
1242
 
1252
- arguments[i] = Napi::Number::New(env, d);
1243
+ arguments[i] = NewFloat(env, d);
1253
1244
  } break;
1254
1245
 
1255
1246
  case PrimitiveKind::Callback: {
1256
1247
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1257
1248
  void *ptr2 = *(void **)src;
1258
1249
 
1259
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1260
-
1261
- if (param.type->dispose) {
1262
- param.type->dispose(env, param.type, ptr2);
1263
- }
1250
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1264
1251
  } break;
1265
1252
 
1266
1253
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
@@ -1360,16 +1347,11 @@ void CallData::Relay(Size idx, uint8_t *sp)
1360
1347
 
1361
1348
  case PrimitiveKind::Record:
1362
1349
  case PrimitiveKind::Union: {
1363
- if (!IsObject(env, value)) [[unlikely]] {
1364
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1365
- return;
1366
- }
1367
-
1368
1350
  if (proto->ret.abi.method == AbiMethod::Stack) {
1369
1351
  uint64_t *gpr_ptr = (uint64_t *)in_ptr;
1370
1352
  uint8_t *dest = (uint8_t *)gpr_ptr[0];
1371
1353
 
1372
- if (!PushObject(value, type, dest))
1354
+ if (!PushObject(value, type, dest)) [[unlikely]]
1373
1355
  return;
1374
1356
 
1375
1357
  out_reg->rax = (uint64_t)dest;
@@ -1377,7 +1359,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
1377
1359
  K_ASSERT(type->size <= 16);
1378
1360
 
1379
1361
  uint8_t buf[16] = {};
1380
- if (!PushObject(value, type, buf))
1362
+ if (!PushObject(value, type, buf)) [[unlikely]]
1381
1363
  return;
1382
1364
 
1383
1365
  switch (proto->ret.abi.method) {
@@ -6,6 +6,7 @@
6
6
  #include "lib/native/base/base.hh"
7
7
  #include "../ffi.hh"
8
8
  #include "../call.hh"
9
+ #include "../type.hh"
9
10
  #include "../util.hh"
10
11
  #include "../win32.hh"
11
12
 
@@ -73,16 +74,16 @@ inline void *Code2Op(AbiOpcode code)
73
74
 
74
75
  bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
75
76
  {
76
- func->ret.regular = IsRegularSize(func->ret.type->size, 8);
77
+ func->ret.abi.regular = IsRegularSize(func->ret.type->size, 8);
77
78
 
78
79
  for (Size i = 0; i < func->parameters.len; i++) {
79
- int16_t arg = (int16_t)(!func->ret.regular + i);
80
+ int16_t arg = (int16_t)(!func->ret.abi.regular + i);
80
81
  ParameterInfo &param = func->parameters[i];
81
82
 
82
- param.regular = IsRegularSize(param.type->size, 8);
83
+ param.abi.regular = IsRegularSize(param.type->size, 8);
83
84
 
84
85
  if (param.type->primitive == PrimitiveKind::Record || param.type->primitive == PrimitiveKind::Union) {
85
- AbiOpcode code = param.regular ? AbiOpcode::PushAggregateReg : AbiOpcode::PushAggregateMem;
86
+ AbiOpcode code = param.abi.regular ? AbiOpcode::PushAggregateReg : AbiOpcode::PushAggregateMem;
86
87
 
87
88
  func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
88
89
  func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
@@ -99,7 +100,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
99
100
 
100
101
  // At least 4 parameter registers
101
102
  {
102
- Size count = std::max((Size)4, func->parameters.len + !func->ret.regular);
103
+ Size count = std::max((Size)4, func->parameters.len + !func->ret.abi.regular);
103
104
  func->stk_size = AlignLen(8 * count, 16);
104
105
  }
105
106
 
@@ -167,7 +168,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
167
168
 
168
169
  case PrimitiveKind::Record:
169
170
  case PrimitiveKind::Union: {
170
- if (func->ret.regular) {
171
+ if (func->ret.abi.regular) {
171
172
  AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateRegX : AbiOpcode::RunAggregateReg;
172
173
  AbiOpcode call = func->forward_fp ? AbiOpcode::CallGX : AbiOpcode::CallG;
173
174
 
@@ -369,14 +370,9 @@ namespace {
369
370
  OP(PushAggregateReg) {
370
371
  napi_value arg = args[inst->a];
371
372
 
372
- if (!IsObject(call->env, arg)) [[unlikely]] {
373
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
374
- return call->env.Null();
375
- }
376
-
377
373
  uint8_t *ptr = (uint8_t *)(base + inst->b1);
378
374
 
379
- if (!call->PushObject(arg, inst->type, ptr))
375
+ if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
380
376
  return call->env.Null();
381
377
 
382
378
  NEXT();
@@ -384,15 +380,10 @@ namespace {
384
380
  OP(PushAggregateMem) {
385
381
  napi_value arg = args[inst->a];
386
382
 
387
- if (!IsObject(call->env, arg)) [[unlikely]] {
388
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
389
- return call->env.Null();
390
- }
391
-
392
383
  uint8_t *ptr = call->AllocHeap(inst->type->size);
393
384
  *(uint8_t **)(base + inst->b1) = ptr;
394
385
 
395
- if (!call->PushObject(arg, inst->type, ptr))
386
+ if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
396
387
  return call->env.Null();
397
388
 
398
389
  NEXT();
@@ -414,7 +405,7 @@ namespace {
414
405
  #define DISPOSE(Ptr) \
415
406
  do { \
416
407
  if (inst->type->dispose) { \
417
- inst->type->dispose(call->env, inst->type, (Ptr)); \
408
+ inst->type->dispose(call->instance, inst->type, (Ptr)); \
418
409
  } \
419
410
  } while (false)
420
411
 
@@ -442,42 +433,42 @@ namespace {
442
433
  OP(RunUInt64S) { INTEGER_SWAP(G, uint64_t); }
443
434
  OP(RunString) {
444
435
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
445
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
436
+ napi_value value = NewString(call->env, (const char *)rax);
446
437
  DISPOSE((void *)rax);
447
438
  return value;
448
439
  }
449
440
  OP(RunString16) {
450
441
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
451
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
442
+ napi_value value = NewString(call->env, (const char16_t *)rax);
452
443
  DISPOSE((void *)rax);
453
444
  return value;
454
445
  }
455
446
  OP(RunString32) {
456
447
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
457
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
448
+ napi_value value = NewString(call->env, (const char32_t *)rax);
458
449
  DISPOSE((void *)rax);
459
450
  return value;
460
451
  }
461
452
  OP(RunPointer) {
462
453
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
463
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
454
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
464
455
  DISPOSE((void *)rax);
465
456
  return value;
466
457
  }
467
458
  OP(RunCallback) {
468
459
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
469
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
460
+ return WrapPointer(call->env, inst->type, (void *)rax);
470
461
  }
471
462
  OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
472
463
  OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
473
464
  OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
474
465
  OP(RunFloat32) {
475
466
  float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
476
- return Napi::Number::New(call->env, (double)f);
467
+ return NewFloat(call->env, f);
477
468
  }
478
469
  OP(RunFloat64) {
479
470
  double d = WRAP(ForwardCallD(call->native, base, &call->saved_sp));
480
- return Napi::Number::New(call->env, d);
471
+ return NewFloat(call->env, d);
481
472
  }
482
473
  OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
483
474
  OP(RunAggregateReg) {
@@ -513,42 +504,42 @@ namespace {
513
504
  OP(RunUInt64SX) { INTEGER_SWAP(GX, uint64_t); }
514
505
  OP(RunStringX) {
515
506
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
516
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
507
+ napi_value value = NewString(call->env, (const char *)rax);
517
508
  DISPOSE((void *)rax);
518
509
  return value;
519
510
  }
520
511
  OP(RunString16X) {
521
512
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
522
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
513
+ napi_value value = NewString(call->env, (const char16_t *)rax);
523
514
  DISPOSE((void *)rax);
524
515
  return value;
525
516
  }
526
517
  OP(RunString32X) {
527
518
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
528
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
519
+ napi_value value = NewString(call->env, (const char32_t *)rax);
529
520
  DISPOSE((void *)rax);
530
521
  return value;
531
522
  }
532
523
  OP(RunPointerX) {
533
524
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
534
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
525
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
535
526
  DISPOSE((void *)rax);
536
527
  return value;
537
528
  }
538
529
  OP(RunCallbackX) {
539
530
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
540
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
531
+ return WrapPointer(call->env, inst->type, (void *)rax);
541
532
  }
542
533
  OP(RunRecordX) { K_UNREACHABLE(); return call->env.Null(); }
543
534
  OP(RunUnionX) { K_UNREACHABLE(); return call->env.Null(); }
544
535
  OP(RunArrayX) { K_UNREACHABLE(); return call->env.Null(); }
545
536
  OP(RunFloat32X) {
546
537
  float f = WRAP(ForwardCallFX(call->native, base, &call->saved_sp));
547
- return Napi::Number::New(call->env, (double)f);
538
+ return NewFloat(call->env, f);
548
539
  }
549
540
  OP(RunFloat64X) {
550
541
  double d = WRAP(ForwardCallDX(call->native, base, &call->saved_sp));
551
- return Napi::Number::New(call->env, d);
542
+ return NewFloat(call->env, d);
552
543
  }
553
544
  OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
554
545
  OP(RunAggregateRegX) {
@@ -574,7 +565,7 @@ namespace {
574
565
  do { \
575
566
  if (inst->type->dispose) { \
576
567
  void *ptr = *(void **)base; \
577
- inst->type->dispose(call->env, inst->type, ptr); \
568
+ inst->type->dispose(call->instance, inst->type, ptr); \
578
569
  } \
579
570
  } while (false)
580
571
  #define INTEGER(CType) \
@@ -631,42 +622,42 @@ namespace {
631
622
  OP(ReturnUInt64S) { INTEGER_SWAP(uint64_t); }
632
623
  OP(ReturnString) {
633
624
  uint64_t rax = *(uint64_t *)base;
634
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
625
+ napi_value value = NewString(call->env, (const char *)rax);
635
626
  DISPOSE();
636
627
  return value;
637
628
  }
638
629
  OP(ReturnString16) {
639
630
  uint64_t rax = *(uint64_t *)base;
640
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
631
+ napi_value value = NewString(call->env, (const char16_t *)rax);
641
632
  DISPOSE();
642
633
  return value;
643
634
  }
644
635
  OP(ReturnString32) {
645
636
  uint64_t rax = *(uint64_t *)base;
646
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
637
+ napi_value value = NewString(call->env, (const char32_t *)rax);
647
638
  DISPOSE();
648
639
  return value;
649
640
  }
650
641
  OP(ReturnPointer) {
651
642
  uint64_t rax = *(uint64_t *)base;
652
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
643
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
653
644
  DISPOSE();
654
645
  return value;
655
646
  }
656
647
  OP(ReturnCallback) {
657
648
  uint64_t rax = *(uint64_t *)base;
658
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
649
+ return WrapPointer(call->env, inst->type, (void *)rax);
659
650
  }
660
651
  OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
661
652
  OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
662
653
  OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
663
654
  OP(ReturnFloat32) {
664
655
  float f = *(float *)base;
665
- return Napi::Number::New(call->env, (double)f);
656
+ return NewFloat(call->env, f);
666
657
  }
667
658
  OP(ReturnFloat64) {
668
659
  double d = *(double *)base;
669
- return Napi::Number::New(call->env, d);
660
+ return NewFloat(call->env, d);
670
661
  }
671
662
  OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
672
663
  OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
@@ -777,7 +768,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
777
768
  uint64_t *xmm_ptr = gpr_ptr + 4;
778
769
  uint64_t *stk_ptr = (uint64_t *)caller_sp;
779
770
 
780
- uint8_t *return_ptr = !proto->ret.regular ? (uint8_t *)gpr_ptr[0] : nullptr;
771
+ uint8_t *return_ptr = !proto->ret.abi.regular ? (uint8_t *)gpr_ptr[0] : nullptr;
781
772
 
782
773
  K_DEFER_N(err_guard) {
783
774
  trampoline->state = -1;
@@ -888,56 +879,52 @@ void CallData::Relay(Size idx, uint8_t *sp)
888
879
  const char *str = *(const char **)(j < 4 ? gpr_ptr + j : stk_ptr);
889
880
  stk_ptr += (j >= 4);
890
881
 
891
- arguments[i] = str ? Napi::String::New(env, str) : env.Null();
882
+ arguments[i] = NewString(env, str);
892
883
 
893
884
  if (param.type->dispose) {
894
- param.type->dispose(env, param.type, str);
885
+ param.type->dispose(instance, param.type, str);
895
886
  }
896
887
  } break;
897
888
  case PrimitiveKind::String16: {
898
889
  const char16_t *str16 = *(const char16_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
899
890
  stk_ptr += (j >= 4);
900
891
 
901
- arguments[i] = str16 ? Napi::String::New(env, str16) : env.Null();
892
+ arguments[i] = NewString(env, str16);
902
893
 
903
894
  if (param.type->dispose) {
904
- param.type->dispose(env, param.type, str16);
895
+ param.type->dispose(instance, param.type, str16);
905
896
  }
906
897
  } break;
907
898
  case PrimitiveKind::String32: {
908
899
  const char32_t *str32 = *(const char32_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
909
900
  stk_ptr += (j >= 4);
910
901
 
911
- arguments[i] = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
902
+ arguments[i] = NewString(env, str32);
912
903
 
913
904
  if (param.type->dispose) {
914
- param.type->dispose(env, param.type, str32);
905
+ param.type->dispose(instance, param.type, str32);
915
906
  }
916
907
  } break;
917
908
  case PrimitiveKind::Pointer: {
918
909
  void *ptr2 = *(void **)(j < 4 ? gpr_ptr + j : stk_ptr);
919
910
  stk_ptr += (j >= 4);
920
911
 
921
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
912
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
922
913
 
923
914
  if (param.type->dispose) {
924
- param.type->dispose(env, param.type, ptr2);
915
+ param.type->dispose(instance, param.type, ptr2);
925
916
  }
926
917
  } break;
927
918
  case PrimitiveKind::Callback: {
928
919
  void *ptr2 = *(void **)(j < 4 ? gpr_ptr + j : stk_ptr);
929
920
  stk_ptr += (j >= 4);
930
921
 
931
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
932
-
933
- if (param.type->dispose) {
934
- param.type->dispose(env, param.type, ptr2);
935
- }
922
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
936
923
  } break;
937
924
  case PrimitiveKind::Record:
938
925
  case PrimitiveKind::Union: {
939
926
  uint8_t *ptr;
940
- if (param.regular) {
927
+ if (param.abi.regular) {
941
928
  ptr = (uint8_t *)(j < 4 ? gpr_ptr + j : stk_ptr);
942
929
  } else {
943
930
  ptr = *(uint8_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
@@ -951,13 +938,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
951
938
  float f = *(float *)(j < 4 ? xmm_ptr + j : stk_ptr);
952
939
  stk_ptr += (j >= 4);
953
940
 
954
- arguments[i] = Napi::Number::New(env, (double)f);
941
+ arguments[i] = NewFloat(env, f);
955
942
  } break;
956
943
  case PrimitiveKind::Float64: {
957
944
  double d = *(double *)(j < 4 ? xmm_ptr + j : stk_ptr);
958
945
  stk_ptr += (j >= 4);
959
946
 
960
- arguments[i] = Napi::Number::New(env, d);
947
+ arguments[i] = NewFloat(env, d);
961
948
  } break;
962
949
 
963
950
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
@@ -1048,17 +1035,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
1048
1035
  } break;
1049
1036
  case PrimitiveKind::Record:
1050
1037
  case PrimitiveKind::Union: {
1051
- if (!IsObject(env, value)) [[unlikely]] {
1052
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1053
- return;
1054
- }
1055
-
1056
1038
  if (return_ptr) {
1057
- if (!PushObject(value, type, return_ptr))
1039
+ if (!PushObject(value, type, return_ptr)) [[unlikely]]
1058
1040
  return;
1059
1041
  out_reg->rax = (uint64_t)return_ptr;
1060
1042
  } else {
1061
- PushObject(value, type, (uint8_t *)&out_reg->rax);
1043
+ if (!PushObject(value, type, (uint8_t *)&out_reg->rax)) [[unlikely]]
1044
+ return;
1062
1045
  }
1063
1046
  } break;
1064
1047
  case PrimitiveKind::Array: { K_UNREACHABLE(); } break;