koffi 2.2.3-beta.1 → 2.2.3-beta.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 (35) hide show
  1. package/package.json +1 -1
  2. package/src/koffi/build/2.2.3-beta.2/koffi_darwin_arm64.tar.gz +0 -0
  3. package/src/koffi/build/2.2.3-beta.2/koffi_darwin_x64.tar.gz +0 -0
  4. package/src/koffi/build/2.2.3-beta.2/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/src/koffi/build/2.2.3-beta.2/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/src/koffi/build/2.2.3-beta.2/koffi_freebsd_x64.tar.gz +0 -0
  7. package/src/koffi/build/2.2.3-beta.2/koffi_linux_arm32hf.tar.gz +0 -0
  8. package/src/koffi/build/2.2.3-beta.2/koffi_linux_arm64.tar.gz +0 -0
  9. package/src/koffi/build/2.2.3-beta.2/koffi_linux_ia32.tar.gz +0 -0
  10. package/src/koffi/build/2.2.3-beta.2/koffi_linux_riscv64hf64.tar.gz +0 -0
  11. package/src/koffi/build/2.2.3-beta.2/koffi_linux_x64.tar.gz +0 -0
  12. package/src/koffi/build/2.2.3-beta.2/koffi_openbsd_ia32.tar.gz +0 -0
  13. package/src/koffi/build/2.2.3-beta.2/koffi_openbsd_x64.tar.gz +0 -0
  14. package/src/koffi/build/2.2.3-beta.2/koffi_win32_arm64.tar.gz +0 -0
  15. package/src/koffi/build/2.2.3-beta.2/koffi_win32_ia32.tar.gz +0 -0
  16. package/src/koffi/build/2.2.3-beta.2/koffi_win32_x64.tar.gz +0 -0
  17. package/src/koffi/src/abi_x64_win.cc +30 -23
  18. package/src/koffi/src/abi_x86.cc +32 -25
  19. package/src/koffi/src/ffi.cc +64 -10
  20. package/src/koffi/src/ffi.hh +6 -2
  21. package/src/koffi/build/2.2.3-beta.1/koffi_darwin_arm64.tar.gz +0 -0
  22. package/src/koffi/build/2.2.3-beta.1/koffi_darwin_x64.tar.gz +0 -0
  23. package/src/koffi/build/2.2.3-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
  24. package/src/koffi/build/2.2.3-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
  25. package/src/koffi/build/2.2.3-beta.1/koffi_freebsd_x64.tar.gz +0 -0
  26. package/src/koffi/build/2.2.3-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
  27. package/src/koffi/build/2.2.3-beta.1/koffi_linux_arm64.tar.gz +0 -0
  28. package/src/koffi/build/2.2.3-beta.1/koffi_linux_ia32.tar.gz +0 -0
  29. package/src/koffi/build/2.2.3-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  30. package/src/koffi/build/2.2.3-beta.1/koffi_linux_x64.tar.gz +0 -0
  31. package/src/koffi/build/2.2.3-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
  32. package/src/koffi/build/2.2.3-beta.1/koffi_openbsd_x64.tar.gz +0 -0
  33. package/src/koffi/build/2.2.3-beta.1/koffi_win32_arm64.tar.gz +0 -0
  34. package/src/koffi/build/2.2.3-beta.1/koffi_win32_ia32.tar.gz +0 -0
  35. package/src/koffi/build/2.2.3-beta.1/koffi_win32_x64.tar.gz +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.2.3-beta.1",
3
+ "version": "2.2.3-beta.2",
4
4
  "stable": "2.2.2",
5
5
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
6
  "keywords": [
@@ -18,14 +18,6 @@
18
18
  #include "call.hh"
19
19
  #include "util.hh"
20
20
 
21
- #ifndef NOMINMAX
22
- #define NOMINMAX
23
- #endif
24
- #ifndef WIN32_LEAN_AND_MEAN
25
- #define WIN32_LEAN_AND_MEAN
26
- #endif
27
- #include <windows.h>
28
-
29
21
  #include <napi.h>
30
22
 
31
23
  namespace RG {
@@ -48,6 +40,10 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
48
40
 
49
41
  #include "abi_trampolines.inc"
50
42
 
43
+ #define TEB_STACK_BASE(TEB) (*(void **)((uint8_t *)(TEB) + 0x08))
44
+ #define TEB_STACK_LIMIT(TEB) (*(void **)((uint8_t *)(TEB) + 0x10))
45
+ #define TEB_DEALLOCATION_STACK(TEB) (*(void **)((uint8_t *)(TEB) + 0x1478))
46
+
51
47
  bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
52
48
  {
53
49
  func->ret.regular = IsRegularSize(func->ret.type->size, 8);
@@ -224,15 +220,21 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
224
220
 
225
221
  void CallData::Execute(const FunctionInfo *func)
226
222
  {
227
- NT_TIB *tib = (NT_TIB *)__readgsqword(0x30);
228
-
229
- // Adjust TIB stack limits so SEH works correctly
230
- RG_DEFER_C(base = tib->StackBase, limit = tib->StackLimit) {
231
- tib->StackBase = base;
232
- tib->StackLimit = limit;
223
+ void *teb = (void *)__readgsqword(0x30);
224
+
225
+ // Store current stack limits
226
+ RG_DEFER_C(base = TEB_STACK_BASE(teb),
227
+ limit = TEB_STACK_LIMIT(teb),
228
+ dealloc = TEB_DEALLOCATION_STACK(teb)) {
229
+ TEB_STACK_BASE(teb) = base;
230
+ TEB_STACK_LIMIT(teb) = limit;
231
+ TEB_DEALLOCATION_STACK(teb) = dealloc;
233
232
  };
234
- tib->StackBase = mem->stack0.end();
235
- tib->StackLimit = mem->stack0.ptr;
233
+
234
+ // Adjust stack limits so SEH works correctly
235
+ TEB_STACK_BASE(teb) = mem->stack0.end();
236
+ TEB_STACK_LIMIT(teb) = mem->stack0.ptr;
237
+ TEB_DEALLOCATION_STACK(teb) = mem->stack0.ptr;
236
238
 
237
239
  #define PERFORM_CALL(Suffix) \
238
240
  ([&]() { \
@@ -335,15 +337,20 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
335
337
  if (RG_UNLIKELY(env.IsExceptionPending()))
336
338
  return;
337
339
 
338
- NT_TIB *tib = (NT_TIB *)__readgsqword(0x30);
340
+ void *teb = (void *)__readgsqword(0x30);
339
341
 
340
- // Restore real thread stack limits
341
- RG_DEFER_C(base = tib->StackBase, limit = tib->StackLimit) {
342
- tib->StackBase = base;
343
- tib->StackLimit = limit;
342
+ RG_DEFER_C(base = TEB_STACK_BASE(teb),
343
+ limit = TEB_STACK_LIMIT(teb),
344
+ dealloc = TEB_DEALLOCATION_STACK(teb)) {
345
+ TEB_STACK_BASE(teb) = base;
346
+ TEB_STACK_LIMIT(teb) = limit;
347
+ TEB_DEALLOCATION_STACK(teb) = dealloc;
344
348
  };
345
- tib->StackBase = instance->main_stack_base;
346
- tib->StackLimit = instance->main_stack_limit;
349
+
350
+ // Restore real thread stack limits
351
+ TEB_STACK_BASE(teb) = instance->main_stack_max;
352
+ TEB_STACK_LIMIT(teb) = instance->main_stack_min;
353
+ TEB_DEALLOCATION_STACK(teb) = instance->main_stack_min;
347
354
 
348
355
  const TrampolineInfo &trampoline = shared.trampolines[idx];
349
356
 
@@ -18,16 +18,6 @@
18
18
  #include "call.hh"
19
19
  #include "util.hh"
20
20
 
21
- #ifdef _WIN32
22
- #ifndef NOMINMAX
23
- #define NOMINMAX
24
- #endif
25
- #ifndef WIN32_LEAN_AND_MEAN
26
- #define WIN32_LEAN_AND_MEAN
27
- #endif
28
- #include <windows.h>
29
- #endif
30
-
31
21
  #include <napi.h>
32
22
 
33
23
  namespace RG {
@@ -56,6 +46,12 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
56
46
 
57
47
  #include "abi_trampolines.inc"
58
48
 
49
+ #ifdef _WIN32
50
+ #define TEB_STACK_BASE(TEB) (*(void **)((uint8_t *)(TEB) + 0x04))
51
+ #define TEB_STACK_LIMIT(TEB) (*(void **)((uint8_t *)(TEB) + 0x08))
52
+ #define TEB_DEALLOCATION_STACK(TEB) (*(void **)((uint8_t *)(TEB) + 0xE0C))
53
+ #endif
54
+
59
55
  bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
60
56
  {
61
57
  if (!func->lib && func->convention != CallConvention::Cdecl &&
@@ -308,15 +304,21 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
308
304
  void CallData::Execute(const FunctionInfo *func)
309
305
  {
310
306
  #ifdef _WIN32
311
- NT_TIB *tib = (NT_TIB *)__readfsdword(0x18);
312
-
313
- // Adjust TIB stack limits so SEH works correctly
314
- RG_DEFER_C(base = tib->StackBase, limit = tib->StackLimit) {
315
- tib->StackBase = base;
316
- tib->StackLimit = limit;
307
+ void *teb = (void *)__readfsdword(0x18);
308
+
309
+ // Store current stack limits
310
+ RG_DEFER_C(base = TEB_STACK_BASE(teb),
311
+ limit = TEB_STACK_LIMIT(teb),
312
+ dealloc = TEB_DEALLOCATION_STACK(teb)) {
313
+ TEB_STACK_BASE(teb) = base;
314
+ TEB_STACK_LIMIT(teb) = limit;
315
+ TEB_DEALLOCATION_STACK(teb) = dealloc;
317
316
  };
318
- tib->StackBase = mem->stack0.end();
319
- tib->StackLimit = mem->stack0.ptr;
317
+
318
+ // Adjust stack limits so SEH works correctly
319
+ TEB_STACK_BASE(teb) = mem->stack0.end();
320
+ TEB_STACK_LIMIT(teb) = mem->stack0.ptr;
321
+ TEB_DEALLOCATION_STACK(teb) = mem->stack0.ptr;
320
322
  #endif
321
323
 
322
324
  #define PERFORM_CALL(Suffix) \
@@ -422,15 +424,20 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool async, BackRe
422
424
  return;
423
425
 
424
426
  #ifdef _WIN32
425
- NT_TIB *tib = (NT_TIB *)__readfsdword(0x18);
427
+ void *teb = (void *)__readfsdword(0x18);
428
+
429
+ RG_DEFER_C(base = TEB_STACK_BASE(teb),
430
+ limit = TEB_STACK_LIMIT(teb),
431
+ dealloc = TEB_DEALLOCATION_STACK(teb)) {
432
+ TEB_STACK_BASE(teb) = base;
433
+ TEB_STACK_LIMIT(teb) = limit;
434
+ TEB_DEALLOCATION_STACK(teb) = dealloc;
435
+ };
426
436
 
427
437
  // Restore real thread stack limits
428
- RG_DEFER_C(base = tib->StackBase, limit = tib->StackLimit) {
429
- tib->StackBase = base;
430
- tib->StackLimit = limit;
431
- };
432
- tib->StackBase = instance->main_stack_base;
433
- tib->StackLimit = instance->main_stack_limit;
438
+ TEB_STACK_BASE(teb) = instance->main_stack_max;
439
+ TEB_STACK_LIMIT(teb) = instance->main_stack_min;
440
+ TEB_DEALLOCATION_STACK(teb) = instance->main_stack_min;
434
441
  #endif
435
442
 
436
443
  const TrampolineInfo &trampoline = shared.trampolines[idx];
@@ -1014,13 +1014,66 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
1014
1014
  return nullptr;
1015
1015
 
1016
1016
  InstanceMemory *mem = new InstanceMemory();
1017
+ RG_DEFER_N(mem_guard) { delete mem; };
1017
1018
 
1018
- mem->stack.len = stack_size;
1019
1019
  #if defined(_WIN32)
1020
- mem->stack.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->stack.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
1020
+ {
1021
+ struct FiberContext {
1022
+ InstanceMemory *mem;
1023
+ void *self;
1024
+ bool was_fiber;
1025
+ };
1026
+
1027
+ FiberContext ctx;
1028
+ bool is_fiber = IsThreadAFiber();
1029
+
1030
+ ctx.mem = mem;
1031
+ ctx.self = is_fiber ? GetCurrentFiber() : ConvertThreadToFiber(nullptr);
1032
+ if (!ctx.self) {
1033
+ LogError("Failed to make initial fiber: %1", GetWin32ErrorString());
1034
+ return nullptr;
1035
+ }
1036
+ RG_DEFER {
1037
+ if (!is_fiber) {
1038
+ ConvertFiberToThread();
1039
+ }
1040
+ };
1041
+
1042
+ // Work around issue with CreateFiber() API and stack size
1043
+ // See here: https://github.com/google/marl/issues/12
1044
+ mem->fiber = CreateFiberEx(stack_size - 1, stack_size,
1045
+ FIBER_FLAG_FLOAT_SWITCH, [](void *udata) {
1046
+ FiberContext *ctx = (FiberContext *)udata;
1047
+
1048
+ // Handle initial call just below
1049
+ #if defined(__aarch64__) || defined(_M_ARM64)
1050
+ NT_TIB *tib = (NT_TIB *)__getReg(18);
1051
+ #elif defined(__x86_64__) || defined(_M_AMD64)
1052
+ NT_TIB *tib = (NT_TIB *)__readgsqword(0x30);
1053
+ #else
1054
+ NT_TIB *tib = (NT_TIB *)__readfsdword(0x18);
1055
+ #endif
1056
+
1057
+ ctx->mem->stack.ptr = (uint8_t *)tib->StackLimit;
1058
+ ctx->mem->stack.len = (uint8_t *)tib->StackBase - ctx->mem->stack.ptr;
1059
+
1060
+ SwitchToFiber(ctx->self);
1061
+ }, &ctx);
1062
+
1063
+ if (!mem->fiber) {
1064
+ LogError("Failed to create Win32 fiber: %1", GetWin32ErrorString());
1065
+ return nullptr;
1066
+ }
1067
+
1068
+ SwitchToFiber(mem->fiber);
1069
+ }
1070
+
1071
+ RG_ASSERT(mem->stack.ptr);
1021
1072
  #elif defined(__APPLE__)
1073
+ mem->stack.len = stack_size;
1022
1074
  mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1023
1075
  #else
1076
+ mem->stack.len = stack_size;
1024
1077
  mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
1025
1078
  #endif
1026
1079
  RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
@@ -1051,6 +1104,7 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
1051
1104
  mem->temporary = true;
1052
1105
  }
1053
1106
 
1107
+ mem_guard.Disable();
1054
1108
  return mem;
1055
1109
  }
1056
1110
 
@@ -1691,8 +1745,8 @@ void FunctionInfo::Unref() const
1691
1745
  InstanceMemory::~InstanceMemory()
1692
1746
  {
1693
1747
  #ifdef _WIN32
1694
- if (stack.ptr) {
1695
- VirtualFree(stack.ptr, 0, MEM_RELEASE);
1748
+ if (fiber) {
1749
+ DeleteFiber(fiber);
1696
1750
  }
1697
1751
  if (heap.ptr) {
1698
1752
  VirtualFree(heap.ptr, 0, MEM_RELEASE);
@@ -1933,15 +1987,15 @@ static InstanceData *CreateInstance(Napi::Env env)
1933
1987
  napi_unref_threadsafe_function(env, instance->broker);
1934
1988
 
1935
1989
  #if defined(_WIN32) && (defined(__x86_64__) || defined(_M_AMD64))
1936
- NT_TIB *tib = (NT_TIB *)__readgsqword(0x30);
1990
+ void *teb = (void *)__readgsqword(0x30);
1937
1991
 
1938
- instance->main_stack_base = tib->StackBase;
1939
- instance->main_stack_limit = tib->StackLimit;
1992
+ instance->main_stack_max = *(void **)((uint8_t *)teb + 0x08); // StackBase
1993
+ instance->main_stack_min = *(void **)((uint8_t *)teb + 0x1478); // DeallocationStack
1940
1994
  #elif defined(_WIN32) && (defined(__i386__) || defined(_M_IX86))
1941
- NT_TIB *tib = (NT_TIB *)__readfsdword(0x18);
1995
+ void *teb = (void *)__readfsdword(0x18);
1942
1996
 
1943
- instance->main_stack_base = tib->StackBase;
1944
- instance->main_stack_limit = tib->StackLimit;
1997
+ instance->main_stack_max = *(void **)((uint8_t *)teb + 0x04); // StackBase
1998
+ instance->main_stack_min = *(void **)((uint8_t *)teb + 0xE0C); // DeallocationStack
1945
1999
  #endif
1946
2000
 
1947
2001
  err_guard.Disable();
@@ -232,6 +232,10 @@ struct InstanceMemory {
232
232
 
233
233
  int16_t depth;
234
234
  bool temporary;
235
+
236
+ #ifdef _WIN32
237
+ void *fiber;
238
+ #endif
235
239
  };
236
240
 
237
241
  struct InstanceData {
@@ -256,8 +260,8 @@ struct InstanceData {
256
260
  napi_threadsafe_function broker = nullptr;
257
261
 
258
262
  #ifdef _WIN32
259
- void *main_stack_base;
260
- void *main_stack_limit;
263
+ void *main_stack_max;
264
+ void *main_stack_min;
261
265
  #endif
262
266
 
263
267
  HashMap<void *, int16_t> trampolines_map;