koffi 2.15.2 → 2.15.3

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 (45) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/koffi/darwin_arm64/koffi.node +0 -0
  3. package/build/koffi/darwin_x64/koffi.node +0 -0
  4. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  5. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  6. package/build/koffi/freebsd_x64/koffi.node +0 -0
  7. package/build/koffi/linux_arm64/koffi.node +0 -0
  8. package/build/koffi/linux_armhf/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_loong64/koffi.node +0 -0
  11. package/build/koffi/linux_riscv64d/koffi.node +0 -0
  12. package/build/koffi/linux_x64/koffi.node +0 -0
  13. package/build/koffi/musl_arm64/koffi.node +0 -0
  14. package/build/koffi/musl_x64/koffi.node +0 -0
  15. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  16. package/build/koffi/openbsd_x64/koffi.node +0 -0
  17. package/build/koffi/win32_arm64/koffi.node +0 -0
  18. package/build/koffi/win32_ia32/koffi.node +0 -0
  19. package/build/koffi/win32_x64/koffi.node +0 -0
  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 +7 -14
  24. package/src/koffi/src/abi_arm32_asm.S +6 -10
  25. package/src/koffi/src/abi_arm64.cc +7 -14
  26. package/src/koffi/src/abi_arm64_asm.S +4 -7
  27. package/src/koffi/src/abi_arm64_asm.asm +5 -7
  28. package/src/koffi/src/abi_loong64_asm.S +4 -7
  29. package/src/koffi/src/abi_riscv64.cc +7 -14
  30. package/src/koffi/src/abi_riscv64_asm.S +4 -7
  31. package/src/koffi/src/abi_x64_sysv.cc +7 -14
  32. package/src/koffi/src/abi_x64_sysv_asm.S +4 -7
  33. package/src/koffi/src/abi_x64_win.cc +7 -14
  34. package/src/koffi/src/abi_x64_win_asm.S +29 -24
  35. package/src/koffi/src/abi_x64_win_asm.asm +28 -25
  36. package/src/koffi/src/abi_x86.cc +17 -15
  37. package/src/koffi/src/abi_x86_asm.S +11 -17
  38. package/src/koffi/src/abi_x86_asm.asm +6 -14
  39. package/src/koffi/src/call.cc +37 -46
  40. package/src/koffi/src/call.hh +7 -9
  41. package/src/koffi/src/ffi.cc +41 -20
  42. package/src/koffi/src/ffi.hh +1 -1
  43. package/src/koffi/src/util.cc +7 -11
  44. package/src/koffi/src/win32.cc +13 -0
  45. package/src/koffi/src/win32.hh +2 -0
@@ -39,6 +39,8 @@ SharedData shared;
39
39
 
40
40
  static thread_local CallData *exec_call;
41
41
 
42
+ extern "C" napi_value SwitchAndRelay(CallData *call, Size idx, uint8_t *sp, uint8_t *saved_sp, Span<uint8_t> *new_stack);
43
+
42
44
  static bool ChangeSize(const char *name, Napi::Value value, Size min_size, Size max_size, Size *out_size)
43
45
  {
44
46
  Napi::Env env = value.Env();
@@ -1690,35 +1692,54 @@ Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info)
1690
1692
  return TranslateAsyncCall(func, func->native, info);
1691
1693
  }
1692
1694
 
1693
- extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
1695
+ extern "C" void RelayCallback(Size idx, uint8_t *sp)
1694
1696
  {
1695
- if (exec_call) [[likely]] {
1696
- exec_call->RelaySafe(idx, own_sp, caller_sp, false, out_reg);
1697
- } else {
1698
- // This happens if the callback pointer is called from a different thread
1699
- // than the one that runs the FFI call (sync or async).
1697
+ CallData *call = exec_call;
1700
1698
 
1701
- TrampolineInfo *trampoline = &shared.trampolines[idx];
1699
+ // Try the fast path first: we are on the main thread and we are running a native call through Koffi.
1700
+ // It should be easy, but in this case we are running on the custom Koffi stack, which will trip up
1701
+ // Node and V8. So we need to switch back to the normal/main stack.
1702
+ if (call && std::this_thread::get_id() == call->instance->main_thread_id) {
1703
+ SwitchAndRelay(call, idx, sp, call->old_sp, &call->mem->stack);
1704
+ return;
1705
+ }
1702
1706
 
1703
- Napi::Env env = trampoline->func.Env();
1704
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1707
+ // Otherwise, we need to allocate memory to perform the callback.
1708
+ // Since the necessary machinery live in CallData, just use a temporary instance.
1709
+ // In some cases we would reuse the existing call (exec_call may be not null),
1710
+ // but it is rare so let's ignore this for simplicity.
1705
1711
 
1706
- InstanceMemory *mem = AllocateMemory(instance, instance->config.async_stack_size, instance->config.async_heap_size);
1707
- if (!mem) [[unlikely]] {
1708
- ThrowError<Napi::Error>(env, "Too many asynchronous calls are running");
1709
- return;
1710
- }
1712
+ TrampolineInfo *trampoline = &shared.trampolines[idx];
1713
+ Napi::Env env = trampoline->func.Env();
1714
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
1715
+
1716
+ InstanceMemory *mem = AllocateMemory(instance, instance->config.async_stack_size, instance->config.async_heap_size);
1717
+ if (!mem) [[unlikely]] {
1718
+ ThrowError<Napi::Error>(env, "Too many asynchronous calls are running");
1719
+ return;
1720
+ }
1711
1721
 
1712
- // Avoid triggering the "use callback beyond FFI" check
1713
- K_DEFER_C(generation = trampoline->generation) { trampoline->generation = generation; };
1714
- trampoline->generation = -1;
1722
+ // Avoid triggering the "use callback beyond FFI" check
1723
+ K_DEFER_C(generation = trampoline->generation) { trampoline->generation = generation; };
1724
+ trampoline->generation = -1;
1715
1725
 
1716
- // We set dispose_call to true so that the main thread will dispose of CallData itself
1726
+ if (std::this_thread::get_id() == instance->main_thread_id) {
1717
1727
  CallData call(env, instance, mem);
1718
- call.RelaySafe(idx, own_sp, caller_sp, true, out_reg);
1728
+
1729
+ Napi::HandleScope scope(env);
1730
+ call.Relay(idx, sp);
1731
+ } else {
1732
+ CallData call(env, instance, mem);
1733
+ call.RelayAsync(idx, sp);
1719
1734
  }
1720
1735
  }
1721
1736
 
1737
+ extern "C" void RelayDirect(CallData *call, Size idx, uint8_t *sp)
1738
+ {
1739
+ Napi::HandleScope scope(call->env);
1740
+ call->Relay(idx, sp);
1741
+ }
1742
+
1722
1743
  static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info)
1723
1744
  {
1724
1745
  Napi::Env env = info.Env();
@@ -2338,7 +2359,7 @@ bool InitAsyncBroker(Napi::Env env, InstanceData *instance)
2338
2359
  if (napi_create_threadsafe_function(env, nullptr, nullptr,
2339
2360
  Napi::String::New(env, "Koffi Async Callback Broker"),
2340
2361
  0, 1, nullptr, nullptr, nullptr,
2341
- CallData::RelayAsync, &instance->broker) != napi_ok) {
2362
+ PerformAsyncRelay, &instance->broker) != napi_ok) {
2342
2363
  LogError("Failed to create async callback broker");
2343
2364
  return false;
2344
2365
  }
@@ -85,7 +85,7 @@ static const char *const PrimitiveKindNames[] = {
85
85
  struct TypeInfo;
86
86
  struct RecordMember;
87
87
  struct FunctionInfo;
88
- class CallData;
88
+ struct CallData;
89
89
 
90
90
  typedef void DisposeFunc (Napi::Env env, const TypeInfo *type, const void *ptr);
91
91
 
@@ -1683,19 +1683,15 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
1683
1683
  #undef PUSH_INTEGER
1684
1684
 
1685
1685
  // Keep memory around if any was allocated
1686
- {
1687
- BlockAllocator *alloc = call.GetAllocator();
1688
-
1689
- if (alloc->IsUsed()) {
1690
- BlockAllocator *copy = instance->encode_map.FindValue(origin, nullptr);
1686
+ if (call.alloc.IsUsed()) {
1687
+ BlockAllocator *copy = instance->encode_map.FindValue(origin, nullptr);
1691
1688
 
1692
- if (!copy) {
1693
- copy = instance->encode_allocators.AppendDefault();
1694
- instance->encode_map.Set(origin, copy);
1695
- }
1696
-
1697
- std::swap(*alloc, *copy);
1689
+ if (!copy) {
1690
+ copy = instance->encode_allocators.AppendDefault();
1691
+ instance->encode_map.Set(origin, copy);
1698
1692
  }
1693
+
1694
+ std::swap(call.alloc, *copy);
1699
1695
  }
1700
1696
 
1701
1697
  return true;
@@ -180,6 +180,19 @@ int GetDllMachine(const wchar_t *filename)
180
180
  return GetFileMachine(h, true);
181
181
  }
182
182
 
183
+ extern "C" int __cdecl SehHandler(void *ptr, void *, void *ctx, void *)
184
+ {
185
+ EXCEPTION_RECORD *rec = (EXCEPTION_RECORD *)ptr;
186
+
187
+ if (!(rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))) {
188
+ EXCEPTION_POINTERS ep = { rec, (CONTEXT *)ctx };
189
+ UnhandledExceptionFilter(&ep);
190
+ ExitProcess(rec->ExceptionCode);
191
+ }
192
+
193
+ return ExceptionContinueSearch;
194
+ }
195
+
183
196
  }
184
197
 
185
198
  #endif
@@ -109,4 +109,6 @@ void *LoadWindowsLibrary(Napi::Env env, Span<const char> path); // Returns HANDL
109
109
  int GetSelfMachine();
110
110
  int GetDllMachine(const wchar_t *filename);
111
111
 
112
+ extern "C" int __cdecl SehHandler(void *ptr, void *, void *ctx, void *);
113
+
112
114
  }