koffi 2.2.3-beta.3 → 2.2.4

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 (51) hide show
  1. package/ChangeLog.md +23 -3
  2. package/doc/calls.md +277 -0
  3. package/doc/functions.md +17 -275
  4. package/doc/index.rst +3 -1
  5. package/doc/misc.md +97 -0
  6. package/doc/pointers.md +135 -0
  7. package/doc/types.md +3 -193
  8. package/package.json +2 -2
  9. package/src/koffi/build/2.2.4/koffi_darwin_arm64.tar.gz +0 -0
  10. package/src/koffi/build/2.2.4/koffi_darwin_x64.tar.gz +0 -0
  11. package/src/koffi/build/2.2.4/koffi_freebsd_arm64.tar.gz +0 -0
  12. package/src/koffi/build/2.2.4/koffi_freebsd_ia32.tar.gz +0 -0
  13. package/src/koffi/build/2.2.4/koffi_freebsd_x64.tar.gz +0 -0
  14. package/src/koffi/build/2.2.4/koffi_linux_arm32hf.tar.gz +0 -0
  15. package/src/koffi/build/2.2.4/koffi_linux_arm64.tar.gz +0 -0
  16. package/src/koffi/build/2.2.4/koffi_linux_ia32.tar.gz +0 -0
  17. package/src/koffi/build/2.2.4/koffi_linux_riscv64hf64.tar.gz +0 -0
  18. package/src/koffi/build/2.2.4/koffi_linux_x64.tar.gz +0 -0
  19. package/src/koffi/build/2.2.4/koffi_openbsd_ia32.tar.gz +0 -0
  20. package/src/koffi/build/2.2.4/koffi_openbsd_x64.tar.gz +0 -0
  21. package/src/koffi/build/2.2.4/koffi_win32_arm64.tar.gz +0 -0
  22. package/src/koffi/build/2.2.4/koffi_win32_ia32.tar.gz +0 -0
  23. package/src/koffi/build/2.2.4/koffi_win32_x64.tar.gz +0 -0
  24. package/src/koffi/src/abi_arm64.cc +39 -0
  25. package/src/koffi/src/abi_x64_sysv_fwd.S +9 -9
  26. package/src/koffi/src/abi_x64_win_fwd.asm +12 -12
  27. package/src/koffi/src/abi_x86_fwd.S +13 -13
  28. package/src/koffi/src/abi_x86_fwd.asm +11 -11
  29. package/src/koffi/src/ffi.cc +29 -52
  30. package/src/koffi/src/ffi.hh +0 -4
  31. package/src/koffi/test/CMakeLists.txt +7 -0
  32. package/src/koffi/test/win32.c +39 -0
  33. package/src/koffi/test/win32.js +70 -0
  34. package/src/koffi/tools/qemu.js +20 -9
  35. package/src/koffi/tools/registry/machines.json +10 -2
  36. package/doc/memory.md +0 -33
  37. package/src/koffi/build/2.2.3-beta.3/koffi_darwin_arm64.tar.gz +0 -0
  38. package/src/koffi/build/2.2.3-beta.3/koffi_darwin_x64.tar.gz +0 -0
  39. package/src/koffi/build/2.2.3-beta.3/koffi_freebsd_arm64.tar.gz +0 -0
  40. package/src/koffi/build/2.2.3-beta.3/koffi_freebsd_ia32.tar.gz +0 -0
  41. package/src/koffi/build/2.2.3-beta.3/koffi_freebsd_x64.tar.gz +0 -0
  42. package/src/koffi/build/2.2.3-beta.3/koffi_linux_arm32hf.tar.gz +0 -0
  43. package/src/koffi/build/2.2.3-beta.3/koffi_linux_arm64.tar.gz +0 -0
  44. package/src/koffi/build/2.2.3-beta.3/koffi_linux_ia32.tar.gz +0 -0
  45. package/src/koffi/build/2.2.3-beta.3/koffi_linux_riscv64hf64.tar.gz +0 -0
  46. package/src/koffi/build/2.2.3-beta.3/koffi_linux_x64.tar.gz +0 -0
  47. package/src/koffi/build/2.2.3-beta.3/koffi_openbsd_ia32.tar.gz +0 -0
  48. package/src/koffi/build/2.2.3-beta.3/koffi_openbsd_x64.tar.gz +0 -0
  49. package/src/koffi/build/2.2.3-beta.3/koffi_win32_arm64.tar.gz +0 -0
  50. package/src/koffi/build/2.2.3-beta.3/koffi_win32_ia32.tar.gz +0 -0
  51. package/src/koffi/build/2.2.3-beta.3/koffi_win32_x64.tar.gz +0 -0
@@ -27,10 +27,10 @@
27
27
  .cfi_startproc
28
28
  .cfi_def_cfa esp, 4
29
29
  ENDBR32
30
- push %ebx
30
+ push %ebp
31
31
  .cfi_def_cfa esp, 8
32
- movl %esp, %ebx
33
- .cfi_def_cfa ebx, 8
32
+ movl %esp, %ebp
33
+ .cfi_def_cfa ebp, 8
34
34
  movl 16(%esp), %eax
35
35
  movl %esp, 0(%eax)
36
36
  movl 8(%esp), %eax
@@ -48,8 +48,8 @@
48
48
  # The return value is passed back untouched.
49
49
  .macro epilogue
50
50
  call *%eax
51
- movl %ebx, %esp
52
- pop %ebx
51
+ movl %ebp, %esp
52
+ pop %ebp
53
53
  .cfi_def_cfa esp, 4
54
54
  ret
55
55
  .cfi_endproc
@@ -168,10 +168,10 @@ CallSwitchStack:
168
168
  .cfi_startproc
169
169
  .cfi_def_cfa esp, 4
170
170
  ENDBR32
171
- push %ebx
171
+ push %ebp
172
172
  .cfi_def_cfa esp, 8
173
- movl %esp, %ebx
174
- .cfi_def_cfa ebx, 8
173
+ movl %esp, %ebp
174
+ .cfi_def_cfa ebp, 8
175
175
  movl 28(%esp), %edx
176
176
  movl 24(%esp), %ecx
177
177
  movl %esp, %eax
@@ -180,16 +180,16 @@ CallSwitchStack:
180
180
  movl %eax, 4(%ecx)
181
181
  movl 20(%esp), %esp
182
182
  subl $28, %esp
183
- movl 8(%ebx), %eax
183
+ movl 8(%ebp), %eax
184
184
  movl %eax, 0(%esp)
185
- movl 12(%ebx), %eax
185
+ movl 12(%ebp), %eax
186
186
  movl %eax, 4(%esp)
187
- movl 16(%ebx), %eax
187
+ movl 16(%ebp), %eax
188
188
  movl %eax, 8(%esp)
189
189
  call *%edx
190
- mov %ebx, %esp
190
+ mov %ebp, %esp
191
191
  .cfi_def_cfa esp, 8
192
- pop %ebx
192
+ pop %ebp
193
193
  .cfi_def_cfa esp, 4
194
194
  ret
195
195
  .cfi_endproc
@@ -29,8 +29,8 @@ public ForwardCallRD
29
29
  ; Save ESP in EBX (non-volatile), and use carefully assembled stack provided by caller.
30
30
  prologue macro
31
31
  endbr32
32
- push ebx
33
- mov ebx, esp
32
+ push ebp
33
+ mov ebp, esp
34
34
  mov eax, dword ptr [esp+16]
35
35
  mov dword ptr [eax+0], esp
36
36
  mov eax, dword ptr [esp+8]
@@ -48,8 +48,8 @@ endm
48
48
  ; The return value is passed back untouched.
49
49
  epilogue macro
50
50
  call eax
51
- mov esp, ebx
52
- pop ebx
51
+ mov esp, ebp
52
+ pop ebp
53
53
  ret
54
54
  endm
55
55
 
@@ -153,8 +153,8 @@ endm
153
153
  ; stack pointer, call Node.js/V8 and go back to ours.
154
154
  CallSwitchStack proc
155
155
  endbr32
156
- push ebx
157
- mov ebx, esp
156
+ push ebp
157
+ mov ebp, esp
158
158
  mov edx, dword ptr [esp+28]
159
159
  mov ecx, dword ptr [esp+24]
160
160
  mov eax, esp
@@ -163,15 +163,15 @@ CallSwitchStack proc
163
163
  mov dword ptr [ecx+4], eax
164
164
  mov esp, dword ptr [esp+20]
165
165
  sub esp, 28
166
- mov eax, dword ptr [ebx+8]
166
+ mov eax, dword ptr [ebp+8]
167
167
  mov dword ptr [esp+0], eax
168
- mov eax, dword ptr [ebx+12]
168
+ mov eax, dword ptr [ebp+12]
169
169
  mov dword ptr [esp+4], eax
170
- mov eax, dword ptr [ebx+16]
170
+ mov eax, dword ptr [ebp+16]
171
171
  mov dword ptr [esp+8], eax
172
172
  call edx
173
- mov esp, ebx
174
- pop ebx
173
+ mov esp, ebp
174
+ pop ebp
175
175
  ret
176
176
  CallSwitchStack endp
177
177
 
@@ -33,6 +33,9 @@
33
33
  #include <dlfcn.h>
34
34
  #include <unistd.h>
35
35
  #include <sys/mman.h>
36
+ #ifndef MAP_STACK
37
+ #define MAP_STACK 0
38
+ #endif
36
39
  #endif
37
40
 
38
41
  #include <napi.h>
@@ -1019,60 +1022,39 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
1019
1022
  InstanceMemory *mem = new InstanceMemory();
1020
1023
  RG_DEFER_N(mem_guard) { delete mem; };
1021
1024
 
1022
- #if defined(_WIN32)
1023
- {
1024
- struct FiberContext {
1025
- InstanceMemory *mem;
1026
- void *self;
1027
- bool was_fiber;
1028
- };
1025
+ stack_size = AlignLen(stack_size, Kibibytes(64));
1029
1026
 
1030
- FiberContext ctx;
1031
- bool is_fiber = IsThreadAFiber();
1027
+ #if defined(_WIN32)
1028
+ static const int PageSize = ([]() {
1029
+ SYSTEM_INFO info = {};
1032
1030
 
1033
- ctx.mem = mem;
1034
- ctx.self = is_fiber ? GetCurrentFiber() : ConvertThreadToFiber(nullptr);
1035
- if (!ctx.self) {
1036
- LogError("Failed to make initial fiber: %1", GetWin32ErrorString());
1037
- return nullptr;
1038
- }
1039
- RG_DEFER {
1040
- if (!is_fiber) {
1041
- ConvertFiberToThread();
1042
- }
1043
- };
1031
+ GetNativeSystemInfo(&info);
1032
+ RG_ASSERT(info.dwPageSize);
1044
1033
 
1045
- // Work around issue with CreateFiber() API and stack size
1046
- // See here: https://github.com/google/marl/issues/12
1047
- mem->fiber = CreateFiberEx(stack_size - 1, stack_size,
1048
- FIBER_FLAG_FLOAT_SWITCH, [](void *udata) {
1049
- FiberContext *ctx = (FiberContext *)udata;
1034
+ return (int)info.dwPageSize;
1035
+ })();
1050
1036
 
1051
- TEB *teb = GetTEB();
1037
+ // Allocate stack memory
1038
+ {
1039
+ mem->stack.len = stack_size;
1040
+ mem->stack.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->stack.len + 2 * PageSize, MEM_RESERVE, PAGE_NOACCESS);
1052
1041
 
1053
- ctx->mem->stack.ptr = (uint8_t *)teb->DeallocationStack;
1054
- ctx->mem->stack.len = (uint8_t *)teb->StackBase - ctx->mem->stack.ptr;
1042
+ RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
1055
1043
 
1056
- SwitchToFiber(ctx->self);
1057
- }, &ctx);
1044
+ bool success = true;
1058
1045
 
1059
- if (!mem->fiber) {
1060
- LogError("Failed to create Win32 fiber: %1", GetWin32ErrorString());
1061
- return nullptr;
1062
- }
1046
+ success &= !!VirtualAlloc(mem->stack.ptr + 0 * PageSize, PageSize, MEM_COMMIT, PAGE_NOACCESS);
1047
+ success &= !!VirtualAlloc(mem->stack.ptr + 1 * PageSize, PageSize, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD);
1048
+ success &= !!VirtualAlloc(mem->stack.ptr + 2 * PageSize, mem->stack.len, MEM_COMMIT, PAGE_READWRITE);
1063
1049
 
1064
- SwitchToFiber(mem->fiber);
1050
+ RG_CRITICAL(success, "Cannot commit stack memory: %1", GetWin32ErrorString());
1065
1051
  }
1066
-
1067
- RG_ASSERT(mem->stack.ptr);
1068
- #elif defined(__APPLE__)
1069
- mem->stack.len = stack_size;
1070
- mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1071
1052
  #else
1072
1053
  mem->stack.len = stack_size;
1073
1054
  mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
1074
- #endif
1055
+
1075
1056
  RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
1057
+ #endif
1076
1058
 
1077
1059
  #ifdef __OpenBSD__
1078
1060
  // Make sure the SP points inside the MAP_STACK area, or (void) functions may crash on OpenBSD i386
@@ -1741,8 +1723,8 @@ void FunctionInfo::Unref() const
1741
1723
  InstanceMemory::~InstanceMemory()
1742
1724
  {
1743
1725
  #ifdef _WIN32
1744
- if (fiber) {
1745
- DeleteFiber(fiber);
1726
+ if (stack.ptr) {
1727
+ VirtualFree(stack.ptr, 0, MEM_RELEASE);
1746
1728
  }
1747
1729
  if (heap.ptr) {
1748
1730
  VirtualFree(heap.ptr, 0, MEM_RELEASE);
@@ -1773,16 +1755,11 @@ static InstanceData *CreateInstance(Napi::Env env)
1773
1755
  }
1774
1756
  napi_unref_threadsafe_function(env, instance->broker);
1775
1757
 
1776
- #if defined(_WIN32) && (defined(__x86_64__) || defined(_M_AMD64))
1777
- void *teb = (void *)__readgsqword(0x30);
1778
-
1779
- instance->main_stack_max = *(void **)((uint8_t *)teb + 0x08); // StackBase
1780
- instance->main_stack_min = *(void **)((uint8_t *)teb + 0x1478); // DeallocationStack
1781
- #elif defined(_WIN32) && (defined(__i386__) || defined(_M_IX86))
1782
- void *teb = (void *)__readfsdword(0x18);
1758
+ #ifdef _WIN32
1759
+ TEB *teb = GetTEB();
1783
1760
 
1784
- instance->main_stack_max = *(void **)((uint8_t *)teb + 0x04); // StackBase
1785
- instance->main_stack_min = *(void **)((uint8_t *)teb + 0xE0C); // DeallocationStack
1761
+ instance->main_stack_max = teb->StackBase;
1762
+ instance->main_stack_min = teb->DeallocationStack;
1786
1763
  #endif
1787
1764
 
1788
1765
  err_guard.Disable();
@@ -232,10 +232,6 @@ struct InstanceMemory {
232
232
 
233
233
  int16_t depth;
234
234
  bool temporary;
235
-
236
- #ifdef _WIN32
237
- void *fiber;
238
- #endif
239
235
  };
240
236
 
241
237
  struct InstanceData {
@@ -116,3 +116,10 @@ if(MSVC)
116
116
  target_compile_options(misc PRIVATE /wd4116)
117
117
  target_link_options(misc PRIVATE "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/misc.def")
118
118
  endif()
119
+
120
+ # ---- Win32 ----
121
+
122
+ if(WIN32)
123
+ add_library(win32 SHARED win32.c)
124
+ set_target_properties(win32 PROPERTIES PREFIX "")
125
+ endif()
@@ -0,0 +1,39 @@
1
+ // This program is free software: you can redistribute it and/or modify
2
+ // it under the terms of the GNU Affero General Public License as published by
3
+ // the Free Software Foundation, either version 3 of the License, or
4
+ // (at your option) any later version.
5
+ //
6
+ // This program is distributed in the hope that it will be useful,
7
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
8
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9
+ // GNU Affero General Public License for more details.
10
+ //
11
+ // You should have received a copy of the GNU Affero General Public License
12
+ // along with this program. If not, see https://www.gnu.org/licenses/.
13
+
14
+ #include <stdlib.h>
15
+ #include <stdio.h>
16
+ #include <inttypes.h>
17
+ #include <string.h>
18
+ #include <stdarg.h>
19
+
20
+ #define NOMINMAX
21
+ #define WIN32_LEAN_AND_MEAN
22
+ #include <windows.h>
23
+
24
+ #define EXPORT __declspec(dllexport)
25
+
26
+ EXPORT int DivideBySafe(int a, int b)
27
+ {
28
+ __try {
29
+ return a / b;
30
+ } __except (GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) {
31
+ return -42;
32
+ }
33
+ }
34
+
35
+ EXPORT int CallThrough(int (*func)(void))
36
+ {
37
+ int ret = func();
38
+ return ret;
39
+ }
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+
3
+ // This program is free software: you can redistribute it and/or modify
4
+ // it under the terms of the GNU Affero General Public License as published by
5
+ // the Free Software Foundation, either version 3 of the License, or
6
+ // (at your option) any later version.
7
+ //
8
+ // This program is distributed in the hope that it will be useful,
9
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ // GNU Affero General Public License for more details.
12
+ //
13
+ // You should have received a copy of the GNU Affero General Public License
14
+ // along with this program. If not, see https://www.gnu.org/licenses/.
15
+
16
+ const koffi = require('./build/koffi.node');
17
+ const assert = require('assert');
18
+ const util = require('util');
19
+
20
+ const CallThroughFunc = koffi.callback('int CallThroughFunc()');
21
+
22
+ main();
23
+
24
+ async function main() {
25
+ try {
26
+ await test();
27
+ console.log('Success!');
28
+ } catch (err) {
29
+ console.error(err);
30
+ process.exit(1);
31
+ }
32
+ }
33
+
34
+ async function test() {
35
+ let lib_filename = __dirname + '/build/win32.dll';
36
+ let lib = koffi.load(lib_filename);
37
+
38
+ const DivideBySafe = lib.func('int DivideBySafe(int a, int b)');
39
+ const CallThrough = lib.func('int CallThrough(CallThroughFunc *func)');
40
+
41
+ // Sync SEH support
42
+ assert.equal(DivideBySafe(12, 3), 4);
43
+ assert.equal(DivideBySafe(84, 0), -42);
44
+
45
+ // Async SEH support
46
+ {
47
+ let results = await Promise.all([
48
+ util.promisify(DivideBySafe.async)(90, -9),
49
+ util.promisify(DivideBySafe.async)(227, 0)
50
+ ]);
51
+
52
+ assert.equal(results[0], -10);
53
+ assert.equal(results[1], -42);
54
+ }
55
+
56
+ // Test SEH inside callback
57
+ assert.equal(CallThrough(() => DivideBySafe(16, 2)), 8);
58
+ assert.equal(CallThrough(() => DivideBySafe(16 * 2, 0)), -42);
59
+
60
+ // Test SEH inside callback running async
61
+ {
62
+ let results = await Promise.all([
63
+ util.promisify(CallThrough.async)(() => DivideBySafe(75, -5)),
64
+ util.promisify(CallThrough.async)(() => DivideBySafe(7, 5 - 5))
65
+ ]);
66
+
67
+ assert.equal(results[0], -15);
68
+ assert.equal(results[1], -42);
69
+ }
70
+ }
@@ -571,7 +571,7 @@ async function upload(snapshot_dir, func) {
571
571
  }
572
572
 
573
573
  let status = copied ? chalk.bold.green('[ok]') : chalk.bold.red('[error]');
574
- log(machine, 'Copy', status);
574
+ log(machine, 'Upload', status);
575
575
  }));
576
576
 
577
577
  return success;
@@ -605,7 +605,7 @@ async function test() {
605
605
  let ret = await exec_remote(machine, cmd, cwd);
606
606
  let time = Number((process.hrtime.bigint() - start) / 1000000n);
607
607
 
608
- if (ret.code == 0) {
608
+ if (ret.code === 0) {
609
609
  log(machine, `${suite} > ${name}`, chalk.bold.green(`[${(time / 1000).toFixed(2)}s]`));
610
610
  } else {
611
611
  log(machine, `${suite} > ${name}`, chalk.bold.red('[error]'));
@@ -654,8 +654,6 @@ async function stop(all = true) {
654
654
 
655
655
  console.log('>> Sending shutdown commands...');
656
656
  await Promise.all(machines.map(async machine => {
657
- if (ignore.has(machine))
658
- return;
659
657
  if (machine.qemu == null)
660
658
  return;
661
659
  if (!machine.started && !all)
@@ -916,19 +914,32 @@ function log(machine, action, status) {
916
914
  }
917
915
 
918
916
  async function exec_remote(machine, cmd, cwd = null) {
917
+ if (typeof cmd == 'string') {
918
+ cmd = {
919
+ command: cmd,
920
+ repeat: 1
921
+ };
922
+ }
923
+
919
924
  try {
925
+ let ret = { code: 0 };
926
+
920
927
  if (machine.platform == 'win32') {
928
+ let cmd_line = cmd.command;
929
+
921
930
  if (cwd != null) {
922
931
  cwd = cwd.replaceAll('/', '\\');
923
- cmd = `cd "${cwd}" && ${cmd}`;
932
+ cmd_line = `cd "${cwd}" && ${cmd_line}`;
924
933
  }
925
934
 
926
- let ret = await machine.ssh.execCommand(cmd);
927
- return ret;
935
+ for (let i = 0; ret.code === 0 && i < cmd.repeat; i++)
936
+ ret = await machine.ssh.execCommand(cmd_line);
928
937
  } else {
929
- let ret = await machine.ssh.execCommand(cmd, { cwd: cwd });
930
- return ret;
938
+ for (let i = 0; ret.code === 0 && i < cmd.repeat; i++)
939
+ ret = await machine.ssh.execCommand(cmd.command, { cwd: cwd });
931
940
  }
941
+
942
+ return ret;
932
943
  } catch (err) {
933
944
  console.log(err);
934
945
  return err;
@@ -230,7 +230,11 @@
230
230
  "Test Async": "C:\\Node32\\node32.cmd node test/async.js",
231
231
  "Test Callbacks": "C:\\Node32\\node32.cmd node test/callbacks.js",
232
232
  "Test Raylib": "seatsh C:\\Node32\\node32.cmd node test/raylib.js",
233
- "Test SQLite": "C:\\Node32\\node32.cmd node test/sqlite.js"
233
+ "Test SQLite": "C:\\Node32\\node32.cmd node test/sqlite.js",
234
+ "Test Win32": {
235
+ "command": "C:\\Node32\\node32.cmd node test/win32.js",
236
+ "repeat": 8
237
+ }
234
238
  }
235
239
  },
236
240
 
@@ -244,7 +248,11 @@
244
248
  "Test Async": "C:\\Node64\\node64.cmd node test/async.js",
245
249
  "Test Callbacks": "C:\\Node64\\node64.cmd node test/callbacks.js",
246
250
  "Test Raylib": "seatsh C:\\Node64\\node64.cmd node test/raylib.js",
247
- "Test SQLite": "C:\\Node64\\node64.cmd node test/sqlite.js"
251
+ "Test SQLite": "C:\\Node64\\node64.cmd node test/sqlite.js",
252
+ "Test Win32": {
253
+ "command": "C:\\Node64\\node64.cmd node test/win32.js",
254
+ "repeat": 8
255
+ }
248
256
  }
249
257
  }
250
258
  }
package/doc/memory.md DELETED
@@ -1,33 +0,0 @@
1
- # Memory usage
2
-
3
- ## How it works
4
-
5
- For synchronous/normal calls, Koffi uses two preallocated memory blocks:
6
-
7
- - One to construct the C stack and assign registers, subsequently used by the platform-specific assembly code (1 MiB by default)
8
- - One to allocate strings and big objects/structs (2 MiB by default)
9
-
10
- Unless very big strings or objects (at least more than one page of memory) are used, Koffi does not directly allocate any extra memory during calls or callbacks. However, please note that the JS engine (V8) might.
11
-
12
- The size (in bytes) of these preallocated blocks can be changed. Use `koffi.config()` to get an object with the settings, and `koffi.config(obj)` to apply new settings.
13
-
14
- ```js
15
- let config = koffi.config();
16
- console.log(config);
17
- ```
18
-
19
- The same is true for asynchronous calls. When an asynchronous call is made, Koffi will allocate new blocks unless there is an unused (resident) set of blocks still available. Once the asynchronous call is finished, these blocks are freed if there are more than `resident_async_pools` sets of blocks left around.
20
-
21
- There cannot be more than `max_async_calls` running at the same time.
22
-
23
- ## Default settings
24
-
25
- Setting | Default | Description
26
- -------------------- | ------- | -----------------------------------------------
27
- sync_stack_size | 1 MiB | Stack size for synchronous calls
28
- sync_heap_size | 2 MiB | Heap size for synchronous calls
29
- async_stack_size | 256 kiB | Stack size for asynchronous calls
30
- async_heap_size | 512 kiB | Heap size for asynchronous calls
31
- resident_async_pools | 2 | Number of resident pools for asynchronous calls
32
- max_async_calls | 64 | Maximum number of ongoing asynchronous calls
33
- max_type_size | 64 MiB | Maximum size of Koffi types (for arrays and structs)