koffi 2.16.1 → 3.0.0-alpha.2

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 (84) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +8 -8
  3. package/build/koffi/darwin_arm64/koffi.node +0 -0
  4. package/build/koffi/darwin_x64/koffi.node +0 -0
  5. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  6. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  7. package/build/koffi/freebsd_x64/koffi.node +0 -0
  8. package/build/koffi/linux_arm64/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_x64/koffi.node +0 -0
  11. package/build/koffi/musl_arm64/koffi.node +0 -0
  12. package/build/koffi/musl_x64/koffi.node +0 -0
  13. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  14. package/build/koffi/openbsd_x64/koffi.node +0 -0
  15. package/build/koffi/win32_ia32/koffi.node +0 -0
  16. package/build/koffi/win32_x64/koffi.node +0 -0
  17. package/doc/benchmarks.md +33 -33
  18. package/doc/benchmarks.xlsx +0 -0
  19. package/doc/contribute.md +37 -25
  20. package/doc/index.md +8 -8
  21. package/doc/variables.md +1 -1
  22. package/index.d.ts +11 -9
  23. package/index.js +1 -634
  24. package/indirect.js +1 -533
  25. package/lib/native/base/base.cc +63 -85
  26. package/lib/native/base/base.hh +178 -151
  27. package/package.json +3 -4
  28. package/src/build.js +1178 -0
  29. package/src/koffi/CMakeLists.txt +97 -34
  30. package/src/koffi/index.js +359 -0
  31. package/src/koffi/indirect.js +216 -0
  32. package/src/koffi/src/{abi_arm32.cc → abi/arm32.cc} +279 -275
  33. package/src/koffi/src/{abi_arm32_asm.S → abi/arm32_asm.S} +2 -5
  34. package/src/koffi/src/abi/arm64.cc +1511 -0
  35. package/src/koffi/src/{abi_arm64_asm.S → abi/arm64_asm.S} +44 -23
  36. package/src/koffi/src/{abi_arm64_asm.asm → abi/arm64_asm.asm} +32 -25
  37. package/src/koffi/src/{abi_loong64_asm.S → abi/loong64_asm.S} +1 -5
  38. package/src/koffi/src/{abi_riscv64.cc → abi/riscv64.cc} +279 -273
  39. package/src/koffi/src/{abi_riscv64_asm.S → abi/riscv64_asm.S} +1 -4
  40. package/src/koffi/src/abi/x64sysv.cc +1456 -0
  41. package/src/koffi/src/{abi_x64_sysv_asm.S → abi/x64sysv_asm.S} +30 -33
  42. package/src/koffi/src/abi/x64win.cc +1121 -0
  43. package/src/koffi/src/{abi_x64_win_asm.S → abi/x64win_asm.S} +8 -12
  44. package/src/koffi/src/{abi_x64_win_asm.asm → abi/x64win_asm.asm} +11 -14
  45. package/src/koffi/src/abi/x86.cc +1233 -0
  46. package/src/koffi/src/{abi_x86_asm.S → abi/x86_asm.S} +49 -25
  47. package/src/koffi/src/{abi_x86_asm.asm → abi/x86_asm.asm} +11 -14
  48. package/src/koffi/src/call.cc +458 -598
  49. package/src/koffi/src/call.hh +61 -82
  50. package/src/koffi/src/ffi.cc +595 -309
  51. package/src/koffi/src/ffi.hh +103 -89
  52. package/src/koffi/src/parser.cc +0 -4
  53. package/src/koffi/src/primitives.inc +39 -0
  54. package/src/koffi/{tools/write_trampolines.js → src/trampolines.js} +1 -1
  55. package/src/koffi/src/util.cc +503 -446
  56. package/src/koffi/src/util.hh +269 -57
  57. package/src/koffi/src/uv.cc +2 -2
  58. package/src/koffi/src/uv.def +3 -0
  59. package/src/koffi/src/win32.hh +30 -1
  60. package/vendor/node-addon-api/napi-inl.h +4 -0
  61. package/vendor/node-addon-api/napi.h +1 -0
  62. package/build/koffi/linux_armhf/koffi.node +0 -0
  63. package/build/koffi/linux_loong64/koffi.node +0 -0
  64. package/build/koffi/linux_riscv64d/koffi.node +0 -0
  65. package/build/koffi/win32_arm64/koffi.exp +0 -0
  66. package/build/koffi/win32_arm64/koffi.lib +0 -0
  67. package/build/koffi/win32_arm64/koffi.node +0 -0
  68. package/doc/platforms.md +0 -36
  69. package/src/cnoke/LICENSE.txt +0 -22
  70. package/src/cnoke/README.md +0 -99
  71. package/src/cnoke/assets/FindCNoke.cmake +0 -127
  72. package/src/cnoke/assets/toolchains.json +0 -126
  73. package/src/cnoke/assets/win_delay_hook.c +0 -36
  74. package/src/cnoke/cnoke.js +0 -170
  75. package/src/cnoke/package.json +0 -24
  76. package/src/cnoke/src/builder.js +0 -511
  77. package/src/cnoke/src/index.js +0 -10
  78. package/src/cnoke/src/tools.js +0 -407
  79. package/src/koffi/src/abi_arm64.cc +0 -1295
  80. package/src/koffi/src/abi_x64_sysv.cc +0 -939
  81. package/src/koffi/src/abi_x64_win.cc +0 -715
  82. package/src/koffi/src/abi_x86.cc +0 -860
  83. package/src/koffi/src/init.js +0 -105
  84. /package/src/koffi/src/{abi_loong64.cc → abi/loong64.cc} +0 -0
@@ -4,9 +4,9 @@
4
4
  #if __riscv_xlen == 64 || defined(__loongarch64)
5
5
 
6
6
  #include "lib/native/base/base.hh"
7
- #include "ffi.hh"
8
- #include "call.hh"
9
- #include "util.hh"
7
+ #include "../ffi.hh"
8
+ #include "../call.hh"
9
+ #include "../util.hh"
10
10
 
11
11
  #include <napi.h>
12
12
 
@@ -48,10 +48,11 @@ extern "C" Fa0A0Ret ForwardCallXDG(const void *func, uint8_t *sp, uint8_t **out_
48
48
  extern "C" A0Fa0Ret ForwardCallXGD(const void *func, uint8_t *sp, uint8_t **out_old_sp);
49
49
  extern "C" Fa0Fa1Ret ForwardCallXDD(const void *func, uint8_t *sp, uint8_t **out_old_sp);
50
50
 
51
- extern "C" uint8_t Trampoline0;
52
- extern "C" uint8_t TrampolineEnd;
53
- extern "C" void *FindTrampolineStart();
54
- extern "C" void *FindTrampolineEnd();
51
+ enum class AbiOpcode : int8_t {
52
+ #define PRIMITIVE(Name) Name,
53
+ #include "../primitives.inc"
54
+ End
55
+ };
55
56
 
56
57
  static inline void ExpandPair(const uint8_t raw[16], int size1, int size2, uint64_t out_regs[2])
57
58
  {
@@ -65,7 +66,8 @@ static inline void CompactPair(const uint64_t regs[2], int size1, int size2, uin
65
66
  memcpy(out_raw + size1, regs + 1, size2);
66
67
  }
67
68
 
68
- static void AnalyseParameter(ParameterInfo *param, int gpr_avail, int vec_avail)
69
+ template <typename T>
70
+ void AnalyseParameter(T *param, int gpr_avail, int vec_avail)
69
71
  {
70
72
  // Too big, pass pointer to struct
71
73
  if (param->type->size > 16) {
@@ -139,8 +141,11 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
139
141
 
140
142
  gpr_avail = std::max(0, gpr_avail - param.gpr_count);
141
143
  vec_avail = std::max(0, vec_avail - param.vec_count);
144
+
145
+ func->instructions.Append((AbiOpcode)param.type->primitive);
142
146
  }
143
147
 
148
+ func->instructions.Append(AbiOpcode::End);
144
149
  func->args_size = 8 * func->parameters.len;
145
150
  func->forward_fp = (vec_avail < 8);
146
151
 
@@ -149,213 +154,261 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
149
154
 
150
155
  bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
151
156
  {
152
- uint64_t *args_ptr = nullptr;
153
- uint64_t *gpr_ptr = nullptr;
154
- uint64_t *vec_ptr = nullptr;
157
+ uint64_t *vec_ptr = AllocStack<uint64_t>(16 * 8 + func->args_size);
158
+ uint64_t *gpr_ptr = vec_ptr + 8;
159
+ uint64_t *args_ptr = vec_ptr + 16;
155
160
 
156
- // Return through registers unless it's too big
157
- if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]]
158
- return false;
159
- if (!AllocStack(8 * 8, 8, &gpr_ptr)) [[unlikely]]
160
- return false;
161
- if (!AllocStack(8 * 8, 8, &vec_ptr)) [[unlikely]]
161
+ if (!vec_ptr) [[unlikely]]
162
162
  return false;
163
163
  if (func->ret.use_memory) {
164
- return_ptr = AllocHeap(func->ret.type->size, 16);
164
+ return_ptr = AllocHeap(func->ret.type->size);
165
165
  *(uint8_t **)(gpr_ptr++) = return_ptr;
166
166
  }
167
167
 
168
+ Size i = -1;
169
+
170
+ static const void *const DispatchTable[] = {
171
+ #define PRIMITIVE(Name) && Name,
172
+ #include "../primitives.inc"
173
+ && End
174
+ };
175
+
176
+ #define LOOP
177
+ #define CASE(Primitive) \
178
+ do { \
179
+ AbiOpcode next = func->instructions[++i]; \
180
+ goto *DispatchTable[(int)next]; \
181
+ } while (false); \
182
+ Primitive:
183
+ #define OR(Primitive) \
184
+ Primitive:
185
+
168
186
  #define PUSH_INTEGER(CType) \
169
187
  do { \
170
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
188
+ const ParameterInfo &param = func->parameters[i]; \
189
+ Napi::Value value = info[param.offset]; \
190
+ \
191
+ CType v; \
192
+ if (!TryNumber(value, &v)) [[unlikely]] { \
171
193
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
172
194
  return false; \
173
195
  } \
174
196
  \
175
- CType v = GetNumber<CType>(value); \
176
197
  *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)v; \
177
198
  } while (false)
178
199
  #define PUSH_INTEGER_SWAP(CType) \
179
200
  do { \
180
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
201
+ const ParameterInfo &param = func->parameters[i]; \
202
+ Napi::Value value = info[param.offset]; \
203
+ \
204
+ CType v; \
205
+ if (!TryNumber(value, &v)) [[unlikely]] { \
181
206
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
182
207
  return false; \
183
208
  } \
184
209
  \
185
- CType v = GetNumber<CType>(value); \
186
210
  *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)ReverseBytes(v); \
187
211
  } while (false)
188
212
 
189
213
  // Push arguments
190
- for (Size i = 0; i < func->parameters.len; i++) {
191
- const ParameterInfo &param = func->parameters[i];
192
- K_ASSERT(param.directions >= 1 && param.directions <= 3);
214
+ LOOP {
215
+ CASE(Void) { K_UNREACHABLE(); };
193
216
 
194
- Napi::Value value = info[param.offset];
217
+ CASE(Bool) {
218
+ const ParameterInfo &param = func->parameters[i];
219
+ Napi::Value value = info[param.offset];
195
220
 
196
- switch (param.type->primitive) {
197
- case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
221
+ bool b;
222
+ if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
223
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
224
+ return false;
225
+ }
198
226
 
199
- case PrimitiveKind::Bool: {
200
- if (!value.IsBoolean()) [[unlikely]] {
201
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
202
- return false;
203
- }
227
+ *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)b;
228
+ };
229
+
230
+ CASE(Int8) { PUSH_INTEGER(int8_t); };
231
+ CASE(UInt8) { PUSH_INTEGER(uint8_t); };
232
+ CASE(Int16) { PUSH_INTEGER(int16_t); };
233
+ CASE(Int16S) { PUSH_INTEGER_SWAP(int16_t); };
234
+ CASE(UInt16) { PUSH_INTEGER(uint16_t); };
235
+ CASE(UInt16S) { PUSH_INTEGER_SWAP(uint16_t); };
236
+ CASE(Int32) { PUSH_INTEGER(int32_t); };
237
+ CASE(Int32S) { PUSH_INTEGER_SWAP(int32_t); };
238
+ CASE(UInt32) { PUSH_INTEGER(uint32_t); };
239
+ CASE(UInt32S) { PUSH_INTEGER_SWAP(uint32_t); };
240
+ CASE(Int64) { PUSH_INTEGER(int64_t); };
241
+ CASE(Int64S) { PUSH_INTEGER_SWAP(int64_t); };
242
+ CASE(UInt64) { PUSH_INTEGER(uint64_t); };
243
+ CASE(UInt64S) { PUSH_INTEGER_SWAP(uint64_t); };
244
+
245
+ CASE(String) {
246
+ const ParameterInfo &param = func->parameters[i];
247
+ Napi::Value value = info[param.offset];
204
248
 
205
- bool b = value.As<Napi::Boolean>();
206
- *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)b;
207
- } break;
208
- case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
209
- case PrimitiveKind::UInt8: { PUSH_INTEGER(uint8_t); } break;
210
- case PrimitiveKind::Int16: { PUSH_INTEGER(int16_t); } break;
211
- case PrimitiveKind::Int16S: { PUSH_INTEGER_SWAP(int16_t); } break;
212
- case PrimitiveKind::UInt16: { PUSH_INTEGER(uint16_t); } break;
213
- case PrimitiveKind::UInt16S: { PUSH_INTEGER_SWAP(uint16_t); } break;
214
- case PrimitiveKind::Int32: { PUSH_INTEGER(int32_t); } break;
215
- case PrimitiveKind::Int32S: { PUSH_INTEGER_SWAP(int32_t); } break;
216
- case PrimitiveKind::UInt32: { PUSH_INTEGER(uint32_t); } break;
217
- case PrimitiveKind::UInt32S: { PUSH_INTEGER_SWAP(uint32_t); } break;
218
- case PrimitiveKind::Int64: { PUSH_INTEGER(int64_t); } break;
219
- case PrimitiveKind::Int64S: { PUSH_INTEGER_SWAP(int64_t); } break;
220
- case PrimitiveKind::UInt64: { PUSH_INTEGER(uint64_t); } break;
221
- case PrimitiveKind::UInt64S: { PUSH_INTEGER_SWAP(uint64_t); } break;
222
- case PrimitiveKind::String: {
223
- const char *str;
224
- if (!PushString(value, param.directions, &str)) [[unlikely]]
225
- return false;
249
+ const char *str;
250
+ if (!PushString(value, param.directions, &str)) [[unlikely]]
251
+ return false;
226
252
 
227
- *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
228
- } break;
229
- case PrimitiveKind::String16: {
230
- const char16_t *str16;
231
- if (!PushString16(value, param.directions, &str16)) [[unlikely]]
232
- return false;
253
+ *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
254
+ };
255
+ CASE(String16) {
256
+ const ParameterInfo &param = func->parameters[i];
257
+ Napi::Value value = info[param.offset];
233
258
 
234
- *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
235
- } break;
236
- case PrimitiveKind::String32: {
237
- const char32_t *str32;
238
- if (!PushString32(value, param.directions, &str32)) [[unlikely]]
239
- return false;
259
+ const char16_t *str16;
260
+ if (!PushString16(value, param.directions, &str16)) [[unlikely]]
261
+ return false;
240
262
 
241
- *(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
242
- } break;
243
- case PrimitiveKind::Pointer: {
244
- void *ptr;
245
- if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
246
- return false;
263
+ *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
264
+ };
265
+ CASE(String32) {
266
+ const ParameterInfo &param = func->parameters[i];
267
+ Napi::Value value = info[param.offset];
247
268
 
248
- *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
249
- } break;
250
- case PrimitiveKind::Record:
251
- case PrimitiveKind::Union: {
252
- if (!IsObject(value)) [[unlikely]] {
253
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
254
- return false;
255
- }
269
+ const char32_t *str32;
270
+ if (!PushString32(value, param.directions, &str32)) [[unlikely]]
271
+ return false;
256
272
 
257
- Napi::Object obj = value.As<Napi::Object>();
273
+ *(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
274
+ };
258
275
 
259
- if (!param.use_memory) {
260
- K_ASSERT(param.type->size <= 16);
261
-
262
- uint64_t regs[2] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull };
263
- {
264
- uint8_t buf[16] = {};
265
- if (!PushObject(obj, param.type, buf))
266
- return false;
267
- ExpandPair(buf, param.reg_size[0], param.reg_size[1], regs);
268
- }
276
+ CASE(Pointer) {
277
+ const ParameterInfo &param = func->parameters[i];
278
+ Napi::Value value = info[param.offset];
269
279
 
270
- if (param.gpr_first) {
271
- *(gpr_ptr++) = regs[0];
272
- if (param.gpr_count == 2) {
273
- *(gpr_ptr++) = regs[1];
274
- } else if (param.vec_count == 1) {
275
- *(vec_ptr++) = regs[1];
276
- }
277
-
278
- args_ptr = std::max(gpr_ptr, args_ptr);
279
- } else if (param.vec_count) {
280
- *(vec_ptr++) = regs[0];
281
- if (param.vec_count == 2) {
282
- *(vec_ptr++) = regs[1];
283
- } else if (param.gpr_count == 1) {
284
- *(gpr_ptr++) = regs[1];
285
- }
286
- } else {
287
- K_ASSERT(param.type->align <= 8);
280
+ void *ptr;
281
+ if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
282
+ return false;
288
283
 
289
- MemCpy(args_ptr, regs, param.type->size);
290
- args_ptr += (param.type->size + 7) / 8;
291
- }
292
- } else {
293
- uint8_t *ptr = AllocHeap(param.type->size, 16);
284
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
285
+ };
294
286
 
295
- if (param.gpr_count) {
296
- K_ASSERT(param.gpr_count == 1);
297
- K_ASSERT(param.vec_count == 0);
287
+ CASE(Record) OR(Union) {
288
+ const ParameterInfo &param = func->parameters[i];
289
+ Napi::Value value = info[param.offset];
298
290
 
299
- *(uint8_t **)(gpr_ptr++) = ptr;
300
- } else {
301
- *(uint8_t **)(args_ptr++) = ptr;
302
- }
291
+ if (!IsObject(value)) [[unlikely]] {
292
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
293
+ return false;
294
+ }
295
+
296
+ Napi::Object obj = value.As<Napi::Object>();
297
+
298
+ if (!param.use_memory) {
299
+ K_ASSERT(param.type->size <= 16);
303
300
 
304
- if (!PushObject(obj, param.type, ptr))
301
+ uint64_t regs[2] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull };
302
+ {
303
+ uint8_t buf[16] = {};
304
+ if (!PushObject(obj, param.type, buf))
305
305
  return false;
306
- }
307
- } break;
308
- case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
309
- case PrimitiveKind::Float32: {
310
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
311
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
312
- return false;
306
+ ExpandPair(buf, param.reg_size[0], param.reg_size[1], regs);
313
307
  }
314
308
 
315
- float f = GetNumber<float>(value);
309
+ if (param.gpr_first) {
310
+ *(gpr_ptr++) = regs[0];
311
+ if (param.gpr_count == 2) {
312
+ *(gpr_ptr++) = regs[1];
313
+ } else if (param.vec_count == 1) {
314
+ *(vec_ptr++) = regs[1];
315
+ }
316
316
 
317
- if (param.vec_count) [[likely]] {
318
- memset((uint8_t *)vec_ptr + 4, 0xFF, 4);
319
- *(float *)(vec_ptr++) = f;
320
- } else if (param.gpr_count) {
321
- memset((uint8_t *)gpr_ptr + 4, 0xFF, 4);
322
- *(float *)(gpr_ptr++) = f;
317
+ args_ptr = std::max(gpr_ptr, args_ptr);
318
+ } else if (param.vec_count) {
319
+ *(vec_ptr++) = regs[0];
320
+ if (param.vec_count == 2) {
321
+ *(vec_ptr++) = regs[1];
322
+ } else if (param.gpr_count == 1) {
323
+ *(gpr_ptr++) = regs[1];
324
+ }
323
325
  } else {
324
- memset(args_ptr, 0xFF, 8);
325
- *(float *)(args_ptr++) = f;
326
- }
327
- } break;
328
- case PrimitiveKind::Float64: {
329
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
330
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
331
- return false;
326
+ K_ASSERT(param.type->align <= 8);
327
+
328
+ MemCpy(args_ptr, regs, param.type->size);
329
+ args_ptr += (param.type->size + 7) / 8;
332
330
  }
331
+ } else {
332
+ uint8_t *ptr = AllocHeap(param.type->size);
333
333
 
334
- double d = GetNumber<double>(value);
334
+ if (param.gpr_count) {
335
+ K_ASSERT(param.gpr_count == 1);
336
+ K_ASSERT(param.vec_count == 0);
335
337
 
336
- if (param.vec_count) [[likely]] {
337
- *(double *)(vec_ptr++) = d;
338
- } else if (param.gpr_count) {
339
- *(double *)(gpr_ptr++) = d;
338
+ *(uint8_t **)(gpr_ptr++) = ptr;
340
339
  } else {
341
- *(double *)(args_ptr++) = d;
340
+ *(uint8_t **)(args_ptr++) = ptr;
342
341
  }
343
- } break;
344
- case PrimitiveKind::Callback: {
345
- void *ptr;
346
- if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
342
+
343
+ if (!PushObject(obj, param.type, ptr))
347
344
  return false;
345
+ }
346
+ };
347
+ CASE(Array) { K_UNREACHABLE(); };
348
348
 
349
- *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
350
- } break;
349
+ CASE(Float32) {
350
+ const ParameterInfo &param = func->parameters[i];
351
+ Napi::Value value = info[param.offset];
351
352
 
352
- case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
353
- }
353
+ float f;
354
+ if (!TryNumber(value, &f)) [[unlikely]] {
355
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
356
+ return false;
357
+ }
358
+
359
+ if (param.vec_count) [[likely]] {
360
+ memset((uint8_t *)vec_ptr + 4, 0xFF, 4);
361
+ *(float *)(vec_ptr++) = f;
362
+ } else if (param.gpr_count) {
363
+ memset((uint8_t *)gpr_ptr + 4, 0xFF, 4);
364
+ *(float *)(gpr_ptr++) = f;
365
+ } else {
366
+ memset(args_ptr, 0xFF, 8);
367
+ *(float *)(args_ptr++) = f;
368
+ }
369
+ };
370
+ CASE(Float64) {
371
+ const ParameterInfo &param = func->parameters[i];
372
+ Napi::Value value = info[param.offset];
373
+
374
+ double d;
375
+ if (!TryNumber(value, &d)) [[unlikely]] {
376
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
377
+ return false;
378
+ }
379
+
380
+ if (param.vec_count) [[likely]] {
381
+ *(double *)(vec_ptr++) = d;
382
+ } else if (param.gpr_count) {
383
+ *(double *)(gpr_ptr++) = d;
384
+ } else {
385
+ *(double *)(args_ptr++) = d;
386
+ }
387
+ };
388
+
389
+ CASE(Callback) {
390
+ const ParameterInfo &param = func->parameters[i];
391
+ Napi::Value value = info[param.offset];
392
+
393
+ void *ptr;
394
+ if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
395
+ return false;
396
+
397
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
398
+ };
399
+
400
+ CASE(Prototype) { K_UNREACHABLE(); };
401
+
402
+ CASE(End) { /* End loop */ };
354
403
  }
355
404
 
356
405
  #undef PUSH_INTEGER_SWAP
357
406
  #undef PUSH_INTEGER
358
407
 
408
+ #undef OR
409
+ #undef CASE
410
+ #undef LOOP
411
+
359
412
  new_sp = mem->stack.end();
360
413
 
361
414
  return true;
@@ -422,8 +475,6 @@ void CallData::Execute(const FunctionInfo *func, void *native)
422
475
  Napi::Value CallData::Complete(const FunctionInfo *func)
423
476
  {
424
477
  K_DEFER {
425
- PopOutArguments();
426
-
427
478
  if (func->ret.type->dispose) {
428
479
  func->ret.type->dispose(env, func->ret.type, result.ptr);
429
480
  }
@@ -432,34 +483,25 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
432
483
  switch (func->ret.type->primitive) {
433
484
  case PrimitiveKind::Void: return env.Undefined();
434
485
  case PrimitiveKind::Bool: return Napi::Boolean::New(env, result.u8 & 0x1);
435
- case PrimitiveKind::Int8: return Napi::Number::New(env, (double)result.i8);
436
- case PrimitiveKind::UInt8: return Napi::Number::New(env, (double)result.u8);
437
- case PrimitiveKind::Int16: return Napi::Number::New(env, (double)result.i16);
438
- case PrimitiveKind::Int16S: return Napi::Number::New(env, (double)ReverseBytes(result.i16));
439
- case PrimitiveKind::UInt16: return Napi::Number::New(env, (double)result.u16);
440
- case PrimitiveKind::UInt16S: return Napi::Number::New(env, (double)ReverseBytes(result.u16));
441
- case PrimitiveKind::Int32: return Napi::Number::New(env, (double)result.i32);
442
- case PrimitiveKind::Int32S: return Napi::Number::New(env, (double)ReverseBytes(result.i32));
443
- case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)result.u32);
444
- case PrimitiveKind::UInt32S: return Napi::Number::New(env, (double)ReverseBytes(result.u32));
445
- case PrimitiveKind::Int64: return NewBigInt(env, result.i64);
446
- case PrimitiveKind::Int64S: return NewBigInt(env, ReverseBytes(result.i64));
447
- case PrimitiveKind::UInt64: return NewBigInt(env, result.u64);
448
- case PrimitiveKind::UInt64S: return NewBigInt(env, ReverseBytes(result.u64));
486
+ case PrimitiveKind::Int8: return NewInt(env, result.i8);
487
+ case PrimitiveKind::UInt8: return NewInt(env, result.u8);
488
+ case PrimitiveKind::Int16: return NewInt(env, result.i16);
489
+ case PrimitiveKind::Int16S: return NewInt(env, ReverseBytes(result.i16));
490
+ case PrimitiveKind::UInt16: return NewInt(env, result.u16);
491
+ case PrimitiveKind::UInt16S: return NewInt(env, ReverseBytes(result.u16));
492
+ case PrimitiveKind::Int32: return NewInt(env, result.i32);
493
+ case PrimitiveKind::Int32S: return NewInt(env, ReverseBytes(result.i32));
494
+ case PrimitiveKind::UInt32: return NewInt(env, result.u32);
495
+ case PrimitiveKind::UInt32S: return NewInt(env, ReverseBytes(result.u32));
496
+ case PrimitiveKind::Int64: return NewInt(env, result.i64);
497
+ case PrimitiveKind::Int64S: return NewInt(env, ReverseBytes(result.i64));
498
+ case PrimitiveKind::UInt64: return NewInt(env, result.u64);
499
+ case PrimitiveKind::UInt64S: return NewInt(env, ReverseBytes(result.u64));
449
500
  case PrimitiveKind::String: return result.ptr ? Napi::String::New(env, (const char *)result.ptr) : env.Null();
450
501
  case PrimitiveKind::String16: return result.ptr ? Napi::String::New(env, (const char16_t *)result.ptr) : env.Null();
451
502
  case PrimitiveKind::String32: return result.ptr ? MakeStringFromUTF32(env, (const char32_t *)result.ptr) : env.Null();
452
- case PrimitiveKind::Pointer:
453
- case PrimitiveKind::Callback: {
454
- if (result.ptr) {
455
- Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
456
- SetValueTag(external, func->ret.type->ref.marker);
457
-
458
- return external;
459
- } else {
460
- return env.Null();
461
- }
462
- } break;
503
+ case PrimitiveKind::Pointer: return result.ptr ? WrapPointer(env, func->ret.type->ref.type, result.ptr) : env.Null();
504
+ case PrimitiveKind::Callback: return result.ptr ? WrapCallback(env, func->ret.type->ref.type, result.ptr) : env.Null();
463
505
  case PrimitiveKind::Record:
464
506
  case PrimitiveKind::Union: {
465
507
  if (return_ptr) {
@@ -485,14 +527,14 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
485
527
 
486
528
  void CallData::Relay(Size idx, uint8_t *sp)
487
529
  {
488
- const TrampolineInfo &trampoline = shared.trampolines[idx];
530
+ TrampolineInfo *trampoline = &shared.trampolines[idx];
489
531
 
490
532
  uint8_t *own_sp = sp;
491
533
  uint8_t *caller_sp = sp + 168;
492
534
  BackRegisters *out_reg = (BackRegisters *)(sp + 128);
493
535
 
494
- const FunctionInfo *proto = trampoline.proto;
495
- Napi::Function func = trampoline.func.Value();
536
+ const FunctionInfo *proto = trampoline->proto;
537
+ Napi::Function func = trampoline->func.Value();
496
538
 
497
539
  uint64_t *gpr_ptr = (uint64_t *)own_sp;
498
540
  uint64_t *vec_ptr = gpr_ptr + 8;
@@ -501,11 +543,14 @@ void CallData::Relay(Size idx, uint8_t *sp)
501
543
  uint8_t *return_ptr = proto->ret.use_memory ? (uint8_t *)gpr_ptr[0] : nullptr;
502
544
  gpr_ptr += proto->ret.use_memory;
503
545
 
504
- K_DEFER_N(err_guard) { memset(out_reg, 0, K_SIZE(*out_reg)); };
546
+ K_DEFER_N(err_guard) {
547
+ trampoline->state = -1;
548
+ memset(out_reg, 0, K_SIZE(*out_reg));
549
+ };
505
550
 
506
551
  LocalArray<napi_value, MaxParameters + 1> arguments;
507
552
 
508
- arguments.Append(!trampoline.recv.IsEmpty() ? trampoline.recv.Value() : env.Undefined());
553
+ arguments.Append(!trampoline->recv.IsEmpty() ? trampoline->recv.Value() : env.Undefined());
509
554
 
510
555
  // Convert to JS arguments
511
556
  for (Size i = 0; i < proto->parameters.len; i++) {
@@ -522,91 +567,87 @@ void CallData::Relay(Size idx, uint8_t *sp)
522
567
  arguments.Append(arg);
523
568
  } break;
524
569
  case PrimitiveKind::Int8: {
525
- double d = (double)*(int8_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
570
+ int8_t v = *(int8_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
526
571
 
527
- Napi::Value arg = Napi::Number::New(env, d);
572
+ Napi::Value arg = NewInt(env, v);
528
573
  arguments.Append(arg);
529
574
  } break;
530
575
  case PrimitiveKind::UInt8: {
531
- double d = (double)*(uint8_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
576
+ uint8_t v = *(uint8_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
532
577
 
533
- Napi::Value arg = Napi::Number::New(env, d);
578
+ Napi::Value arg = NewInt(env, v);
534
579
  arguments.Append(arg);
535
580
  } break;
536
581
  case PrimitiveKind::Int16: {
537
- double d = (double)*(int16_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
582
+ int16_t v = *(int16_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
538
583
 
539
- Napi::Value arg = Napi::Number::New(env, d);
584
+ Napi::Value arg = NewInt(env, v);
540
585
  arguments.Append(arg);
541
586
  } break;
542
587
  case PrimitiveKind::Int16S: {
543
588
  int16_t v = *(int16_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
544
- double d = (double)ReverseBytes(v);
545
589
 
546
- Napi::Value arg = Napi::Number::New(env, d);
590
+ Napi::Value arg = NewInt(env, ReverseBytes(v));
547
591
  arguments.Append(arg);
548
592
  } break;
549
593
  case PrimitiveKind::UInt16: {
550
- double d = (double)*(uint16_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
594
+ uint16_t v = *(uint16_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
551
595
 
552
- Napi::Value arg = Napi::Number::New(env, d);
596
+ Napi::Value arg = NewInt(env, v);
553
597
  arguments.Append(arg);
554
598
  } break;
555
599
  case PrimitiveKind::UInt16S: {
556
600
  uint16_t v = *(uint16_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
557
- double d = (double)ReverseBytes(v);
558
601
 
559
- Napi::Value arg = Napi::Number::New(env, d);
602
+ Napi::Value arg = NewInt(env, ReverseBytes(v));
560
603
  arguments.Append(arg);
561
604
  } break;
562
605
  case PrimitiveKind::Int32: {
563
- double d = (double)*(int32_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
606
+ int32_t v = *(int32_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
564
607
 
565
- Napi::Value arg = Napi::Number::New(env, d);
608
+ Napi::Value arg = NewInt(env, v);
566
609
  arguments.Append(arg);
567
610
  } break;
568
611
  case PrimitiveKind::Int32S: {
569
612
  int32_t v = *(int32_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
570
- double d = (double)ReverseBytes(v);
571
613
 
572
- Napi::Value arg = Napi::Number::New(env, d);
614
+ Napi::Value arg = NewInt(env, ReverseBytes(v));
573
615
  arguments.Append(arg);
574
616
  } break;
575
617
  case PrimitiveKind::UInt32: {
576
- double d = (double)*(uint32_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
618
+ uint32_t v = *(uint32_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
577
619
 
578
- Napi::Value arg = Napi::Number::New(env, d);
620
+ Napi::Value arg = NewInt(env, v);
579
621
  arguments.Append(arg);
580
622
  } break;
581
623
  case PrimitiveKind::UInt32S: {
582
624
  uint32_t v = *(uint32_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
583
- double d = (double)ReverseBytes(v);
584
625
 
585
- Napi::Value arg = Napi::Number::New(env, d);
626
+ Napi::Value arg = NewInt(env, ReverseBytes(v));
586
627
  arguments.Append(arg);
587
628
  } break;
588
629
  case PrimitiveKind::Int64: {
589
630
  int64_t v = *(int64_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
590
631
 
591
- Napi::Value arg = NewBigInt(env, v);
632
+ Napi::Value arg = NewInt(env, v);
592
633
  arguments.Append(arg);
593
634
  } break;
594
635
  case PrimitiveKind::Int64S: {
595
636
  int64_t v = *(int64_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
596
637
 
597
- Napi::Value arg = NewBigInt(env, ReverseBytes(v));
638
+ Napi::Value arg = NewInt(env, ReverseBytes(v));
598
639
  arguments.Append(arg);
599
640
  } break;
600
641
  case PrimitiveKind::UInt64: {
601
642
  uint64_t v = *(uint64_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
602
643
 
603
- Napi::Value arg = NewBigInt(env, v);
644
+ Napi::Value arg = NewInt(env, v);
604
645
  arguments.Append(arg);
605
646
  } break;
606
647
  case PrimitiveKind::UInt64S: {
607
648
  uint64_t v = *(uint64_t *)((param.gpr_count ? gpr_ptr : args_ptr)++);
608
649
 
609
- Napi::Value arg = NewBigInt(env, ReverseBytes(v));
650
+ Napi::Value arg = NewInt(env, ReverseBytes(v));
610
651
  arguments.Append(arg);
611
652
  } break;
612
653
  case PrimitiveKind::String: {
@@ -635,18 +676,21 @@ void CallData::Relay(Size idx, uint8_t *sp)
635
676
  Napi::Value arg = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
636
677
  arguments.Append(arg);
637
678
  } break;
638
- case PrimitiveKind::Pointer:
639
- case PrimitiveKind::Callback: {
679
+ case PrimitiveKind::Pointer: {
640
680
  void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
641
681
 
642
- if (ptr2) {
643
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
644
- SetValueTag(external, param.type->ref.marker);
682
+ Napi::Value p = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
683
+ arguments.Append(p);
645
684
 
646
- arguments.Append(external);
647
- } else {
648
- arguments.Append(env.Null());
685
+ if (param.type->dispose) {
686
+ param.type->dispose(env, param.type, ptr2);
649
687
  }
688
+ } break;
689
+ case PrimitiveKind::Callback: {
690
+ void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
691
+
692
+ Napi::Value p = ptr2 ? WrapCallback(env, param.type->ref.type, ptr2) : env.Null();
693
+ arguments.Append(p);
650
694
 
651
695
  if (param.type->dispose) {
652
696
  param.type->dispose(env, param.type, ptr2);
@@ -725,22 +769,22 @@ void CallData::Relay(Size idx, uint8_t *sp)
725
769
 
726
770
  #define RETURN_INTEGER(CType) \
727
771
  do { \
728
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
772
+ CType v; \
773
+ if (!TryNumber(value, &v)) [[unlikely]] { \
729
774
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
730
775
  return; \
731
776
  } \
732
777
  \
733
- CType v = GetNumber<CType>(value); \
734
778
  out_reg->a0 = (uint64_t)v; \
735
779
  } while (false)
736
780
  #define RETURN_INTEGER_SWAP(CType) \
737
781
  do { \
738
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
782
+ CType v; \
783
+ if (!TryNumber(value, &v)) [[unlikely]] { \
739
784
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
740
785
  return; \
741
786
  } \
742
787
  \
743
- CType v = GetNumber<CType>(value); \
744
788
  out_reg->a0 = (uint64_t)ReverseBytes(v); \
745
789
  } while (false)
746
790
 
@@ -748,12 +792,12 @@ void CallData::Relay(Size idx, uint8_t *sp)
748
792
  switch (type->primitive) {
749
793
  case PrimitiveKind::Void: {} break;
750
794
  case PrimitiveKind::Bool: {
751
- if (!value.IsBoolean()) [[unlikely]] {
795
+ bool b;
796
+ if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
752
797
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
753
798
  return;
754
799
  }
755
800
 
756
- bool b = value.As<Napi::Boolean>();
757
801
  out_reg->a0 = (uint64_t)b;
758
802
  } break;
759
803
  case PrimitiveKind::Int8: { RETURN_INTEGER(int8_t); } break;
@@ -792,24 +836,9 @@ void CallData::Relay(Size idx, uint8_t *sp)
792
836
  out_reg->a0 = (uint64_t)str32;
793
837
  } break;
794
838
  case PrimitiveKind::Pointer: {
795
- uint8_t *ptr;
796
-
797
- if (CheckValueTag(value, type->ref.marker)) {
798
- ptr = value.As<Napi::External<uint8_t>>().Data();
799
- } else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
800
- type->ref.type->primitive == PrimitiveKind::Union)) {
801
- Napi::Object obj = value.As<Napi::Object>();
802
-
803
- ptr = AllocHeap(type->ref.type->size, 16);
804
-
805
- if (!PushObject(obj, type->ref.type, ptr))
806
- return;
807
- } else if (IsNullOrUndefined(value)) {
808
- ptr = nullptr;
809
- } else {
810
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
839
+ void *ptr;
840
+ if (!PushPointer(value, type, 1, &ptr)) [[unlikely]]
811
841
  return;
812
- }
813
842
 
814
843
  out_reg->a0 = (uint64_t)ptr;
815
844
  } break;
@@ -852,41 +881,28 @@ void CallData::Relay(Size idx, uint8_t *sp)
852
881
  } break;
853
882
  case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
854
883
  case PrimitiveKind::Float32: {
855
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
884
+ float f;
885
+ if (!TryNumber(value, &f)) [[unlikely]] {
856
886
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
857
887
  return;
858
888
  }
859
889
 
860
- float f = GetNumber<float>(value);
861
890
  memset((uint8_t *)&out_reg->fa0 + 4, 0xFF, 4);
862
891
  memcpy(&out_reg->fa0, &f, 4);
863
892
  } break;
864
893
  case PrimitiveKind::Float64: {
865
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
894
+ double d;
895
+ if (!TryNumber(value, &d)) [[unlikely]] {
866
896
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
867
897
  return;
868
898
  }
869
899
 
870
- double d = GetNumber<double>(value);
871
900
  out_reg->fa0 = d;
872
901
  } break;
873
902
  case PrimitiveKind::Callback: {
874
903
  void *ptr;
875
-
876
- if (value.IsFunction()) {
877
- Napi::Function func2 = value.As<Napi::Function>();
878
-
879
- ptr = ReserveTrampoline(type->ref.proto, func2);
880
- if (!ptr) [[unlikely]]
881
- return;
882
- } else if (CheckValueTag(value, type->ref.marker)) {
883
- ptr = value.As<Napi::External<void>>().Data();
884
- } else if (IsNullOrUndefined(value)) {
885
- ptr = nullptr;
886
- } else {
887
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
904
+ if (!PushCallback(value, type, &ptr)) [[unlikely]]
888
905
  return;
889
- }
890
906
 
891
907
  out_reg->a0 = (uint64_t)ptr;
892
908
  } break;
@@ -900,16 +916,6 @@ void CallData::Relay(Size idx, uint8_t *sp)
900
916
  err_guard.Disable();
901
917
  }
902
918
 
903
- void *FindTrampolineStart()
904
- {
905
- return &Trampoline0;
906
- }
907
-
908
- void *FindTrampolineEnd()
909
- {
910
- return &TrampolineEnd;
911
- }
912
-
913
919
  }
914
920
 
915
921
  #endif