koffi 2.15.0 → 2.16.0-beta.1
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.
- package/CHANGELOG.md +7 -0
- package/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_armhf/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_loong64/koffi.node +0 -0
- package/build/koffi/linux_riscv64d/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/musl_arm64/koffi.node +0 -0
- package/build/koffi/musl_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/doc/pages/index.md +4 -2
- package/doc/pages/misc.md +2 -0
- package/doc/templates/code.html +1 -2
- package/doc/templates/page.html +1 -2
- package/index.d.ts +11 -9
- package/index.js +9 -9
- package/indirect.js +9 -9
- package/lib/native/base/base.cc +79 -44
- package/lib/native/base/base.hh +31 -33
- package/package.json +2 -2
- package/src/cnoke/assets/FindCNoke.cmake +16 -10
- package/src/cnoke/assets/win_delay_hook.c +4 -0
- package/src/cnoke/src/builder.js +49 -46
- package/src/koffi/CMakeLists.txt +18 -8
- package/src/koffi/src/abi_arm32.cc +222 -219
- package/src/koffi/src/abi_arm32_asm.S +1 -29
- package/src/koffi/src/abi_arm64.cc +257 -235
- package/src/koffi/src/abi_arm64_asm.S +1 -32
- package/src/koffi/src/abi_arm64_asm.asm +1 -23
- package/src/koffi/src/abi_loong64_asm.S +1 -25
- package/src/koffi/src/abi_riscv64.cc +220 -217
- package/src/koffi/src/abi_riscv64_asm.S +1 -25
- package/src/koffi/src/abi_x64_sysv.cc +196 -192
- package/src/koffi/src/abi_x64_sysv_asm.S +1 -31
- package/src/koffi/src/abi_x64_win.cc +188 -172
- package/src/koffi/src/abi_x64_win_asm.S +144 -0
- package/src/koffi/src/abi_x64_win_asm.asm +1 -21
- package/src/koffi/src/abi_x86.cc +224 -189
- package/src/koffi/src/abi_x86_asm.S +6 -25
- package/src/koffi/src/abi_x86_asm.asm +9 -22
- package/src/koffi/src/call.cc +246 -428
- package/src/koffi/src/call.hh +9 -8
- package/src/koffi/src/ffi.cc +142 -88
- package/src/koffi/src/ffi.hh +13 -59
- package/src/koffi/src/primitives.inc +39 -0
- package/src/koffi/src/trampolines/armasm.inc +0 -32770
- package/src/koffi/src/trampolines/gnu.inc +0 -24578
- package/src/koffi/src/trampolines/masm32.inc +0 -32770
- package/src/koffi/src/trampolines/masm64.inc +0 -32770
- package/src/koffi/src/trampolines/prototypes.inc +16385 -16385
- package/src/koffi/src/util.cc +155 -112
- package/src/koffi/src/util.hh +77 -40
- package/vendor/node-api-headers/CHANGELOG.md +22 -0
- package/vendor/node-api-headers/README.md +6 -17
- package/vendor/node-api-headers/include/js_native_api.h +3 -13
- package/vendor/node-api-headers/include/js_native_api_types.h +15 -0
- package/vendor/node-api-headers/include/node_api.h +0 -4
- package/vendor/node-api-headers/include/node_api_types.h +6 -0
- package/vendor/node-api-headers/package.json +1 -1
- package/vendor/node-api-headers/scripts/update-headers.js +6 -0
package/src/koffi/src/call.hh
CHANGED
|
@@ -77,8 +77,10 @@ public:
|
|
|
77
77
|
#if defined(UNITY_BUILD)
|
|
78
78
|
#if defined(_MSC_VER)
|
|
79
79
|
#define INLINE_IF_UNITY __forceinline
|
|
80
|
-
#
|
|
80
|
+
#elif defined(__clang__)
|
|
81
81
|
#define INLINE_IF_UNITY __attribute__((always_inline)) inline
|
|
82
|
+
#else
|
|
83
|
+
#define INLINE_IF_UNITY
|
|
82
84
|
#endif
|
|
83
85
|
#else
|
|
84
86
|
#define INLINE_IF_UNITY
|
|
@@ -116,7 +118,7 @@ public:
|
|
|
116
118
|
|
|
117
119
|
private:
|
|
118
120
|
template <typename T>
|
|
119
|
-
|
|
121
|
+
T *AllocStack(Size size);
|
|
120
122
|
template <typename T = uint8_t>
|
|
121
123
|
T *AllocHeap(Size size, Size align);
|
|
122
124
|
|
|
@@ -126,15 +128,15 @@ private:
|
|
|
126
128
|
};
|
|
127
129
|
|
|
128
130
|
template <typename T>
|
|
129
|
-
inline
|
|
131
|
+
inline T *CallData::AllocStack(Size size)
|
|
130
132
|
{
|
|
131
|
-
uint8_t *ptr = AlignDown(mem->stack.end() - size,
|
|
133
|
+
uint8_t *ptr = AlignDown(mem->stack.end() - size, 16);
|
|
132
134
|
Size delta = mem->stack.end() - ptr;
|
|
133
135
|
|
|
134
136
|
// Keep 512 bytes for redzone (required in some ABIs)
|
|
135
137
|
if (mem->stack.len - 512 < delta) [[unlikely]] {
|
|
136
138
|
ThrowError<Napi::Error>(env, "FFI call is taking up too much memory");
|
|
137
|
-
return
|
|
139
|
+
return nullptr;
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
#if defined(K_DEBUG)
|
|
@@ -143,8 +145,7 @@ inline bool CallData::AllocStack(Size size, Size align, T **out_ptr)
|
|
|
143
145
|
|
|
144
146
|
mem->stack.len -= delta;
|
|
145
147
|
|
|
146
|
-
|
|
147
|
-
return true;
|
|
148
|
+
return (T *)ptr;
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
template <typename T>
|
|
@@ -176,6 +177,6 @@ inline T *CallData::AllocHeap(Size size, Size align)
|
|
|
176
177
|
}
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
void *GetTrampoline(int16_t idx
|
|
180
|
+
void *GetTrampoline(int16_t idx);
|
|
180
181
|
|
|
181
182
|
}
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -138,6 +138,20 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
|
|
|
138
138
|
} else if (key == "max_type_size") {
|
|
139
139
|
if (!ChangeSize(key.c_str(), value, 32, Mebibytes(512), &new_config.max_type_size))
|
|
140
140
|
return env.Null();
|
|
141
|
+
} else if (key == "fast_pointers") {
|
|
142
|
+
if (!value.IsBoolean()) {
|
|
143
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for '%2', expected boolean", GetValueType(instance, value), key.c_str());
|
|
144
|
+
return env.Null();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
new_config.fast_pointers = value.As<Napi::Boolean>();
|
|
148
|
+
} else if (key == "fast_callbacks") {
|
|
149
|
+
if (!value.IsBoolean()) {
|
|
150
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for '%2', expected boolean", GetValueType(instance, value), key.c_str());
|
|
151
|
+
return env.Null();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
new_config.fast_callbacks = value.As<Napi::Boolean>();
|
|
141
155
|
} else {
|
|
142
156
|
ThrowError<Napi::Error>(env, "Unexpected config member '%1'", key.c_str());
|
|
143
157
|
return env.Null();
|
|
@@ -162,6 +176,8 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
|
|
|
162
176
|
obj.Set("resident_async_pools", instance->config.resident_async_pools);
|
|
163
177
|
obj.Set("max_async_calls", instance->config.resident_async_pools + instance->config.max_temporaries);
|
|
164
178
|
obj.Set("max_type_size", instance->config.max_type_size);
|
|
179
|
+
obj.Set("fast_pointers", instance->config.fast_pointers);
|
|
180
|
+
obj.Set("fast_callbacks", instance->config.fast_callbacks);
|
|
165
181
|
|
|
166
182
|
return obj;
|
|
167
183
|
}
|
|
@@ -790,13 +806,10 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
|
|
|
790
806
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
791
807
|
const Napi::FunctionReference &ref = type->dispose_ref;
|
|
792
808
|
|
|
793
|
-
Napi::
|
|
794
|
-
SetValueTag(external, type->ref.marker);
|
|
809
|
+
Napi::Value p = WrapPointer(env, type->ref.type, (void *)ptr);
|
|
795
810
|
|
|
796
|
-
|
|
797
|
-
napi_value args[] = {
|
|
798
|
-
external
|
|
799
|
-
};
|
|
811
|
+
napi_value self = env.Null();
|
|
812
|
+
napi_value args[] = { p };
|
|
800
813
|
|
|
801
814
|
ref.Call(self, K_LEN(args), args);
|
|
802
815
|
instance->stats.disposed++;
|
|
@@ -842,21 +855,12 @@ static inline bool GetExternalPointer(Napi::Env env, Napi::Value value, void **o
|
|
|
842
855
|
{
|
|
843
856
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
844
857
|
|
|
845
|
-
if (
|
|
846
|
-
|
|
847
|
-
return true;
|
|
848
|
-
} else if (value.IsExternal() && !CheckValueTag(value, &TypeInfoMarker) &&
|
|
849
|
-
!CheckValueTag(value, &CastMarker) &&
|
|
850
|
-
!CheckValueTag(value, &MagicUnionMarker)) {
|
|
851
|
-
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
852
|
-
void *ptr = external.Data();
|
|
853
|
-
|
|
854
|
-
*out_ptr = ptr;
|
|
855
|
-
return true;
|
|
856
|
-
} else {
|
|
857
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for ptr, expected external pointer", GetValueType(instance, value));
|
|
858
|
+
if (!TryPointer(value, out_ptr)) {
|
|
859
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for ptr, expected pointer", GetValueType(instance, value));
|
|
858
860
|
return false;
|
|
859
861
|
}
|
|
862
|
+
|
|
863
|
+
return true;
|
|
860
864
|
}
|
|
861
865
|
|
|
862
866
|
static Napi::Value CallAlloc(const Napi::CallbackInfo &info)
|
|
@@ -902,10 +906,7 @@ static Napi::Value CallAlloc(const Napi::CallbackInfo &info)
|
|
|
902
906
|
return env.Null();
|
|
903
907
|
}
|
|
904
908
|
|
|
905
|
-
|
|
906
|
-
SetValueTag(external, type);
|
|
907
|
-
|
|
908
|
-
return external;
|
|
909
|
+
return WrapPointer(env, type, ptr);
|
|
909
910
|
}
|
|
910
911
|
|
|
911
912
|
static Napi::Value CallFree(const Napi::CallbackInfo &info)
|
|
@@ -1167,6 +1168,14 @@ static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
|
|
|
1167
1168
|
if (!AnalyseFunction(env, instance, func))
|
|
1168
1169
|
return env.Null();
|
|
1169
1170
|
|
|
1171
|
+
// Branchless push loop
|
|
1172
|
+
for (const ParameterInfo ¶m: func->parameters) {
|
|
1173
|
+
func->primitives.Append(param.type->primitive);
|
|
1174
|
+
}
|
|
1175
|
+
if (!func->variadic) {
|
|
1176
|
+
func->primitives.Append(PrimitiveKind::Prototype);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1170
1179
|
// Adjust parameter offsets for koffi.call()
|
|
1171
1180
|
for (ParameterInfo ¶m: func->parameters) {
|
|
1172
1181
|
param.offset += 2;
|
|
@@ -1517,62 +1526,105 @@ static Napi::Value TranslateVariadicCall(const FunctionInfo *func, void *native,
|
|
|
1517
1526
|
Napi::Env env = info.Env();
|
|
1518
1527
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1519
1528
|
|
|
1520
|
-
FunctionInfo
|
|
1521
|
-
|
|
1522
|
-
copy.lib = nullptr;
|
|
1529
|
+
FunctionInfo *variadic = nullptr;
|
|
1530
|
+
K_DEFER_N(err_guard) { delete variadic; };
|
|
1523
1531
|
|
|
1524
|
-
//
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
copy.parameters.Leak();
|
|
1528
|
-
};
|
|
1532
|
+
// Try cached function
|
|
1533
|
+
{
|
|
1534
|
+
FunctionInfo *prev = instance->variadic_func;
|
|
1529
1535
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1536
|
+
if (prev && prev->native == native) {
|
|
1537
|
+
Size specified = (info.Length() - prev->required_parameters);
|
|
1538
|
+
Size processed = (prev->parameters.len - prev->required_parameters) * 2;
|
|
1539
|
+
|
|
1540
|
+
if (specified == processed) {
|
|
1541
|
+
bool match = true;
|
|
1542
|
+
|
|
1543
|
+
for (Size i = prev->required_parameters, j = prev->required_parameters; i < (Size)info.Length(); i += 2, j++) {
|
|
1544
|
+
int directions;
|
|
1545
|
+
const TypeInfo *type = ResolveType(info[(uint32_t)i], &directions);
|
|
1546
|
+
|
|
1547
|
+
if (type != prev->parameters[j].type || directions != prev->parameters[j].directions) [[unlikely]] {
|
|
1548
|
+
match = false;
|
|
1549
|
+
break;
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
if (match) [[likely]] {
|
|
1554
|
+
variadic = prev;
|
|
1555
|
+
|
|
1556
|
+
// If an error happens it'll get destroyed, so don't keep it around
|
|
1557
|
+
instance->variadic_func = nullptr;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1537
1561
|
}
|
|
1538
1562
|
|
|
1539
|
-
|
|
1540
|
-
|
|
1563
|
+
if (!variadic) {
|
|
1564
|
+
variadic = new FunctionInfo();
|
|
1541
1565
|
|
|
1542
|
-
|
|
1566
|
+
memcpy((void *)variadic, func, K_SIZE(*func));
|
|
1567
|
+
memset((void *)&variadic->parameters, 0, K_SIZE(variadic->parameters));
|
|
1568
|
+
memset((void *)&variadic->primitives, 0, K_SIZE(variadic->primitives));
|
|
1543
1569
|
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1570
|
+
variadic->parameters = func->parameters;
|
|
1571
|
+
variadic->primitives = func->primitives;
|
|
1572
|
+
variadic->lib = nullptr;
|
|
1573
|
+
|
|
1574
|
+
if (info.Length() < (uint32_t)variadic->required_parameters) [[unlikely]] {
|
|
1575
|
+
ThrowError<Napi::TypeError>(env, "Expected %1 arguments or more, got %2", variadic->parameters.len, info.Length());
|
|
1548
1576
|
return env.Null();
|
|
1549
1577
|
}
|
|
1550
|
-
if (
|
|
1551
|
-
ThrowError<Napi::
|
|
1578
|
+
if ((info.Length() - variadic->required_parameters) % 2) [[unlikely]] {
|
|
1579
|
+
ThrowError<Napi::Error>(env, "Missing value argument for variadic call");
|
|
1552
1580
|
return env.Null();
|
|
1553
1581
|
}
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1582
|
+
|
|
1583
|
+
for (Size i = variadic->required_parameters; i < (Size)info.Length(); i += 2) {
|
|
1584
|
+
ParameterInfo param = {};
|
|
1585
|
+
|
|
1586
|
+
param.type = ResolveType(info[(uint32_t)i], ¶m.directions);
|
|
1587
|
+
|
|
1588
|
+
if (!param.type) [[unlikely]]
|
|
1589
|
+
return env.Null();
|
|
1590
|
+
if (!CanPassType(param.type, param.directions)) [[unlikely]] {
|
|
1591
|
+
ThrowError<Napi::TypeError>(env, "Type %1 cannot be used as a parameter", param.type->name);
|
|
1592
|
+
return env.Null();
|
|
1593
|
+
}
|
|
1594
|
+
if (variadic->parameters.len >= MaxParameters) [[unlikely]] {
|
|
1595
|
+
ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 parameters", MaxParameters);
|
|
1596
|
+
return env.Null();
|
|
1597
|
+
}
|
|
1598
|
+
if ((param.directions & 2) && ++variadic->out_parameters >= MaxParameters) [[unlikely]] {
|
|
1599
|
+
ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 output parameters", MaxParameters);
|
|
1600
|
+
return env.Null();
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
param.variadic = true;
|
|
1604
|
+
param.offset = (int8_t)(i + 1);
|
|
1605
|
+
|
|
1606
|
+
variadic->parameters.Append(param);
|
|
1557
1607
|
}
|
|
1558
1608
|
|
|
1559
|
-
|
|
1560
|
-
|
|
1609
|
+
if (!AnalyseFunction(env, instance, variadic)) [[unlikely]]
|
|
1610
|
+
return env.Null();
|
|
1561
1611
|
|
|
1562
|
-
|
|
1612
|
+
// Branchless push loop
|
|
1613
|
+
for (Size i = func->parameters.len; i < variadic->parameters.len; i++) {
|
|
1614
|
+
const ParameterInfo ¶m = variadic->parameters[i];
|
|
1615
|
+
variadic->primitives.Append(param.type->primitive);
|
|
1616
|
+
}
|
|
1617
|
+
variadic->primitives.Append(PrimitiveKind::Prototype);
|
|
1563
1618
|
}
|
|
1564
1619
|
|
|
1565
|
-
if (!AnalyseFunction(env, instance, ©)) [[unlikely]]
|
|
1566
|
-
return env.Null();
|
|
1567
|
-
|
|
1568
1620
|
InstanceMemory *mem = instance->memories[0];
|
|
1569
1621
|
CallData call(env, instance, mem);
|
|
1570
1622
|
|
|
1571
|
-
if (!call.Prepare(
|
|
1623
|
+
if (!call.Prepare(variadic, info)) [[unlikely]]
|
|
1572
1624
|
return env.Null();
|
|
1573
1625
|
|
|
1574
1626
|
if (instance->debug) {
|
|
1575
|
-
call.DumpForward(
|
|
1627
|
+
call.DumpForward(variadic);
|
|
1576
1628
|
}
|
|
1577
1629
|
|
|
1578
1630
|
// Execute call
|
|
@@ -1580,10 +1632,17 @@ static Napi::Value TranslateVariadicCall(const FunctionInfo *func, void *native,
|
|
|
1580
1632
|
K_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1581
1633
|
exec_call = &call;
|
|
1582
1634
|
|
|
1583
|
-
call.Execute(
|
|
1635
|
+
call.Execute(variadic, native);
|
|
1584
1636
|
}
|
|
1585
1637
|
|
|
1586
|
-
|
|
1638
|
+
if (variadic != instance->variadic_func) {
|
|
1639
|
+
err_guard.Disable();
|
|
1640
|
+
|
|
1641
|
+
delete instance->variadic_func;
|
|
1642
|
+
instance->variadic_func = variadic;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
return call.Complete(variadic);
|
|
1587
1646
|
}
|
|
1588
1647
|
|
|
1589
1648
|
Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
@@ -1640,11 +1699,8 @@ void AsyncCall::OnOK()
|
|
|
1640
1699
|
|
|
1641
1700
|
Napi::FunctionReference &callback = Callback();
|
|
1642
1701
|
|
|
1643
|
-
|
|
1644
|
-
napi_value args[] = {
|
|
1645
|
-
env.Null(),
|
|
1646
|
-
call.Complete(func)
|
|
1647
|
-
};
|
|
1702
|
+
napi_value self = env.Null();
|
|
1703
|
+
napi_value args[] = { env.Null(), call.Complete(func) };
|
|
1648
1704
|
|
|
1649
1705
|
callback.Call(self, K_LEN(args), args);
|
|
1650
1706
|
}
|
|
@@ -1755,9 +1811,16 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info)
|
|
|
1755
1811
|
|
|
1756
1812
|
if (!AnalyseFunction(env, instance, func))
|
|
1757
1813
|
return env.Null();
|
|
1814
|
+
|
|
1815
|
+
// Branchless push loop
|
|
1816
|
+
for (const ParameterInfo ¶m: func->parameters) {
|
|
1817
|
+
func->primitives.Append(param.type->primitive);
|
|
1818
|
+
}
|
|
1758
1819
|
if (func->variadic) {
|
|
1759
|
-
// Minimize reallocations
|
|
1760
1820
|
func->parameters.Grow(32);
|
|
1821
|
+
func->primitives.Grow(32);
|
|
1822
|
+
} else {
|
|
1823
|
+
func->primitives.Append(PrimitiveKind::Prototype);
|
|
1761
1824
|
}
|
|
1762
1825
|
|
|
1763
1826
|
#if defined(_WIN32)
|
|
@@ -1822,10 +1885,7 @@ static Napi::Value FindSymbol(const Napi::CallbackInfo &info)
|
|
|
1822
1885
|
return env.Null();
|
|
1823
1886
|
}
|
|
1824
1887
|
|
|
1825
|
-
|
|
1826
|
-
SetValueTag(external, &type);
|
|
1827
|
-
|
|
1828
|
-
return external;
|
|
1888
|
+
return WrapPointer(env, type, ptr);
|
|
1829
1889
|
}
|
|
1830
1890
|
|
|
1831
1891
|
static Napi::Value UnloadLibrary(const Napi::CallbackInfo &info)
|
|
@@ -1992,15 +2052,12 @@ static Napi::Value RegisterCallback(const Napi::CallbackInfo &info)
|
|
|
1992
2052
|
}
|
|
1993
2053
|
trampoline->generation = -1;
|
|
1994
2054
|
|
|
1995
|
-
void *ptr = GetTrampoline(idx
|
|
1996
|
-
|
|
1997
|
-
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
1998
|
-
SetValueTag(external, type->ref.marker);
|
|
2055
|
+
void *ptr = GetTrampoline(idx);
|
|
1999
2056
|
|
|
2000
2057
|
// Cache index for fast unregistration
|
|
2001
2058
|
instance->trampolines_map.Set(ptr, idx);
|
|
2002
2059
|
|
|
2003
|
-
return
|
|
2060
|
+
return WrapCallback(env, type->ref.type, ptr);
|
|
2004
2061
|
}
|
|
2005
2062
|
|
|
2006
2063
|
static Napi::Value UnregisterCallback(const Napi::CallbackInfo &info)
|
|
@@ -2012,14 +2069,13 @@ static Napi::Value UnregisterCallback(const Napi::CallbackInfo &info)
|
|
|
2012
2069
|
ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
|
|
2013
2070
|
return env.Null();
|
|
2014
2071
|
}
|
|
2015
|
-
|
|
2072
|
+
|
|
2073
|
+
void *ptr;
|
|
2074
|
+
if (!TryPointer(info[0], &ptr)) {
|
|
2016
2075
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for id, expected registered callback", GetValueType(instance, info[0]));
|
|
2017
2076
|
return env.Null();
|
|
2018
2077
|
}
|
|
2019
2078
|
|
|
2020
|
-
Napi::External<void> external = info[0].As<Napi::External<void>>();
|
|
2021
|
-
void *ptr = external.Data();
|
|
2022
|
-
|
|
2023
2079
|
int16_t idx;
|
|
2024
2080
|
{
|
|
2025
2081
|
int16_t *it = instance->trampolines_map.Find(ptr);
|
|
@@ -2375,10 +2431,8 @@ static void RegisterPrimitiveType(Napi::Env env, Napi::Object map, std::initiali
|
|
|
2375
2431
|
}
|
|
2376
2432
|
|
|
2377
2433
|
if (ref) {
|
|
2378
|
-
|
|
2379
|
-
K_ASSERT(
|
|
2380
|
-
|
|
2381
|
-
type->ref.marker = marker;
|
|
2434
|
+
type->ref.type = instance->types_map.FindValue(ref, nullptr);
|
|
2435
|
+
K_ASSERT(type->ref.type);
|
|
2382
2436
|
}
|
|
2383
2437
|
|
|
2384
2438
|
Napi::Value wrapper = WrapType(env, type);
|
|
@@ -2582,7 +2636,8 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
|
|
|
2582
2636
|
instance->str16_type = instance->types_map.FindValue("char16_t *", nullptr);
|
|
2583
2637
|
instance->str32_type = instance->types_map.FindValue("char32_t *", nullptr);
|
|
2584
2638
|
|
|
2585
|
-
|
|
2639
|
+
Napi::Symbol symbol = Napi::Symbol::New(env, "active");
|
|
2640
|
+
instance->active_symbol.Reset(symbol, 1);
|
|
2586
2641
|
|
|
2587
2642
|
instance->base_types_count = instance->types.count;
|
|
2588
2643
|
}
|
|
@@ -2592,10 +2647,7 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
|
|
|
2592
2647
|
Napi::Object node = Napi::Object::New(env);
|
|
2593
2648
|
exports.Set("node", node);
|
|
2594
2649
|
|
|
2595
|
-
|
|
2596
|
-
SetValueTag(external, instance->void_type);
|
|
2597
|
-
|
|
2598
|
-
node.Set("env", external);
|
|
2650
|
+
node.Set("env", WrapPointer(env, instance->void_type, (napi_env)env));
|
|
2599
2651
|
|
|
2600
2652
|
node.Set("poll", Napi::Function::New(env, &Poll, "poll"));
|
|
2601
2653
|
node.Set("PollHandle", PollHandle::Define(env));
|
|
@@ -2608,6 +2660,8 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
|
|
|
2608
2660
|
|
|
2609
2661
|
InstanceData::~InstanceData()
|
|
2610
2662
|
{
|
|
2663
|
+
delete variadic_func;
|
|
2664
|
+
|
|
2611
2665
|
for (InstanceMemory *mem: memories) {
|
|
2612
2666
|
delete mem;
|
|
2613
2667
|
}
|
package/src/koffi/src/ffi.hh
CHANGED
|
@@ -22,64 +22,12 @@ static const Size MaxParameters = 64;
|
|
|
22
22
|
static const Size MaxTrampolines = 8192;
|
|
23
23
|
|
|
24
24
|
enum class PrimitiveKind {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Bool,
|
|
28
|
-
Void,
|
|
29
|
-
Int8,
|
|
30
|
-
UInt8,
|
|
31
|
-
Int16,
|
|
32
|
-
Int16S, // Keep behind Int16
|
|
33
|
-
UInt16,
|
|
34
|
-
UInt16S, // Keep behind UInt16
|
|
35
|
-
Int32,
|
|
36
|
-
Int32S, // Keep behind Int32
|
|
37
|
-
UInt32,
|
|
38
|
-
UInt32S, // Keep behind UInt32
|
|
39
|
-
Int64,
|
|
40
|
-
Int64S, // Keep behind Int64
|
|
41
|
-
UInt64,
|
|
42
|
-
UInt64S, // Keep behind UInt64
|
|
43
|
-
String,
|
|
44
|
-
String16,
|
|
45
|
-
String32,
|
|
46
|
-
Pointer,
|
|
47
|
-
Record,
|
|
48
|
-
Union,
|
|
49
|
-
Array,
|
|
50
|
-
Float32,
|
|
51
|
-
Float64,
|
|
52
|
-
Prototype,
|
|
53
|
-
Callback
|
|
25
|
+
#define PRIMITIVE(Name) Name,
|
|
26
|
+
#include "primitives.inc"
|
|
54
27
|
};
|
|
55
28
|
static const char *const PrimitiveKindNames[] = {
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
"Int8",
|
|
59
|
-
"UInt8",
|
|
60
|
-
"Int16",
|
|
61
|
-
"Int16S",
|
|
62
|
-
"UInt16",
|
|
63
|
-
"UInt16S",
|
|
64
|
-
"Int32",
|
|
65
|
-
"Int32S",
|
|
66
|
-
"UInt32",
|
|
67
|
-
"UInt32S",
|
|
68
|
-
"Int64",
|
|
69
|
-
"Int64S",
|
|
70
|
-
"UInt64",
|
|
71
|
-
"UInt64S",
|
|
72
|
-
"String",
|
|
73
|
-
"String16",
|
|
74
|
-
"String32",
|
|
75
|
-
"Pointer",
|
|
76
|
-
"Record",
|
|
77
|
-
"Union",
|
|
78
|
-
"Array",
|
|
79
|
-
"Float32",
|
|
80
|
-
"Float64",
|
|
81
|
-
"Prototype",
|
|
82
|
-
"Callback"
|
|
29
|
+
#define PRIMITIVE(Name) K_STRINGIFY(Name),
|
|
30
|
+
#include "primitives.inc"
|
|
83
31
|
};
|
|
84
32
|
|
|
85
33
|
struct TypeInfo;
|
|
@@ -109,7 +57,7 @@ static const char *const ArrayHintNames[] = {
|
|
|
109
57
|
struct TypeInfo {
|
|
110
58
|
const char *name;
|
|
111
59
|
|
|
112
|
-
// Make sure
|
|
60
|
+
// Make sure primitive ends up as the upper N-API tag value when we cast TypeInfo pointers to
|
|
113
61
|
// napi_type_tag pointers. Yes, I want to do this. We don't do strict aliasing here.
|
|
114
62
|
// N.B. Some node versions don't like when one of the two tag values is 0, so make sure
|
|
115
63
|
// this does not happen! It would happen if primitive is 0 and size is 0. To avoid this
|
|
@@ -124,7 +72,6 @@ struct TypeInfo {
|
|
|
124
72
|
|
|
125
73
|
HeapArray<RecordMember> members; // Record only
|
|
126
74
|
union {
|
|
127
|
-
const void *marker;
|
|
128
75
|
const TypeInfo *type; // Pointer or array
|
|
129
76
|
const FunctionInfo *proto; // Callback only
|
|
130
77
|
} ref;
|
|
@@ -223,6 +170,7 @@ struct FunctionInfo {
|
|
|
223
170
|
|
|
224
171
|
ParameterInfo ret;
|
|
225
172
|
HeapArray<ParameterInfo> parameters;
|
|
173
|
+
HeapArray<PrimitiveKind> primitives;
|
|
226
174
|
int8_t required_parameters;
|
|
227
175
|
int8_t out_parameters;
|
|
228
176
|
bool variadic;
|
|
@@ -274,12 +222,15 @@ struct InstanceData {
|
|
|
274
222
|
const TypeInfo *str16_type;
|
|
275
223
|
const TypeInfo *str32_type;
|
|
276
224
|
|
|
277
|
-
Napi::Symbol active_symbol;
|
|
225
|
+
Napi::Reference<Napi::Symbol> active_symbol;
|
|
278
226
|
|
|
279
227
|
std::mutex mem_mutex;
|
|
280
228
|
LocalArray<InstanceMemory *, 17> memories;
|
|
281
229
|
int temporaries = 0;
|
|
282
230
|
|
|
231
|
+
// Variadic cache
|
|
232
|
+
FunctionInfo *variadic_func = nullptr;
|
|
233
|
+
|
|
283
234
|
std::thread::id main_thread_id;
|
|
284
235
|
napi_threadsafe_function broker = nullptr;
|
|
285
236
|
|
|
@@ -305,6 +256,9 @@ struct InstanceData {
|
|
|
305
256
|
int resident_async_pools = DefaultResidentAsyncPools;
|
|
306
257
|
int max_temporaries = DefaultMaxAsyncCalls - DefaultResidentAsyncPools;
|
|
307
258
|
Size max_type_size = DefaultMaxTypeSize;
|
|
259
|
+
|
|
260
|
+
bool fast_pointers = false;
|
|
261
|
+
bool fast_callbacks = false;
|
|
308
262
|
} config;
|
|
309
263
|
|
|
310
264
|
struct {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
|
|
3
|
+
|
|
4
|
+
#if !defined(PRIMITIVE)
|
|
5
|
+
#error Please define PRIMITIVE() before including primitives.inc
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
// Void is explictly not first so that it is not 0, for reasons related to N-API type tags.
|
|
9
|
+
// Look at TypeInfo definition for more information!
|
|
10
|
+
|
|
11
|
+
PRIMITIVE(Bool)
|
|
12
|
+
PRIMITIVE(Void)
|
|
13
|
+
PRIMITIVE(Int8)
|
|
14
|
+
PRIMITIVE(UInt8)
|
|
15
|
+
PRIMITIVE(Int16)
|
|
16
|
+
PRIMITIVE(Int16S) // Keep behind Int16
|
|
17
|
+
PRIMITIVE(UInt16)
|
|
18
|
+
PRIMITIVE(UInt16S) // Keep behind UInt16
|
|
19
|
+
PRIMITIVE(Int32)
|
|
20
|
+
PRIMITIVE(Int32S) // Keep behind Int32
|
|
21
|
+
PRIMITIVE(UInt32)
|
|
22
|
+
PRIMITIVE(UInt32S) // Keep behind UInt32
|
|
23
|
+
PRIMITIVE(Int64)
|
|
24
|
+
PRIMITIVE(Int64S) // Keep behind Int64
|
|
25
|
+
PRIMITIVE(UInt64)
|
|
26
|
+
PRIMITIVE(UInt64S) // Keep behind UInt64
|
|
27
|
+
PRIMITIVE(String)
|
|
28
|
+
PRIMITIVE(String16)
|
|
29
|
+
PRIMITIVE(String32)
|
|
30
|
+
PRIMITIVE(Pointer)
|
|
31
|
+
PRIMITIVE(Record)
|
|
32
|
+
PRIMITIVE(Union)
|
|
33
|
+
PRIMITIVE(Array)
|
|
34
|
+
PRIMITIVE(Float32)
|
|
35
|
+
PRIMITIVE(Float64)
|
|
36
|
+
PRIMITIVE(Callback)
|
|
37
|
+
PRIMITIVE(Prototype)
|
|
38
|
+
|
|
39
|
+
#undef PRIMITIVE
|