koffi 2.2.2-beta.4 → 2.2.2-beta.6
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/doc/callbacks.md +1 -1
- package/doc/contribute.md +1 -1
- package/package.json +1 -1
- package/src/koffi/build/2.2.2-beta.6/koffi_darwin_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_darwin_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_freebsd_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_freebsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_freebsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_linux_arm32hf.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_linux_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_linux_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_linux_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_openbsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_openbsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_win32_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_win32_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.6/koffi_win32_x64.tar.gz +0 -0
- package/src/koffi/src/abi_arm32.cc +3 -70
- package/src/koffi/src/abi_arm32_fwd.S +6054 -97
- package/src/koffi/src/abi_arm64.cc +3 -70
- package/src/koffi/src/abi_arm64_fwd.S +6050 -93
- package/src/koffi/src/abi_arm64_fwd.asm +8082 -141
- package/src/koffi/src/abi_riscv64.cc +3 -70
- package/src/koffi/src/abi_riscv64_fwd.S +6044 -87
- package/src/koffi/src/abi_trampolines.inc +2065 -0
- package/src/koffi/src/abi_x64_sysv.cc +3 -70
- package/src/koffi/src/abi_x64_sysv_fwd.S +6048 -91
- package/src/koffi/src/abi_x64_win.cc +4 -71
- package/src/koffi/src/abi_x64_win_fwd.asm +8018 -77
- package/src/koffi/src/abi_x86.cc +4 -71
- package/src/koffi/src/abi_x86_fwd.S +6056 -99
- package/src/koffi/src/abi_x86_fwd.asm +8027 -86
- package/src/koffi/src/call.cc +20 -16
- package/src/koffi/src/call.hh +2 -4
- package/src/koffi/src/ffi.cc +31 -29
- package/src/koffi/src/ffi.hh +16 -5
- package/src/koffi/src/index.js +3 -2
- package/src/koffi/test/callbacks.js +11 -10
- package/src/koffi/test/misc.c +30 -17
- package/src/koffi/{qemu → tools}/qemu/.gitkeep +0 -0
- package/src/koffi/{qemu → tools}/qemu.js +4 -1
- package/src/koffi/{qemu → tools}/registry/machines.json +0 -0
- package/src/koffi/{qemu → tools}/registry/sha256sum.txt +0 -0
- package/src/koffi/tools/write_trampolines.py +138 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_darwin_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_darwin_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_freebsd_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_freebsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_freebsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_linux_arm32hf.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_linux_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_linux_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_linux_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_openbsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_openbsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_win32_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_win32_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.2-beta.4/koffi_win32_x64.tar.gz +0 -0
package/src/koffi/src/call.cc
CHANGED
|
@@ -53,19 +53,20 @@ CallData::~CallData()
|
|
|
53
53
|
mem->stack = old_stack_mem;
|
|
54
54
|
mem->heap = old_heap_mem;
|
|
55
55
|
|
|
56
|
-
if (used_trampolines) {
|
|
56
|
+
if (used_trampolines.len) {
|
|
57
57
|
std::lock_guard<std::mutex> lock(shared.mutex);
|
|
58
58
|
|
|
59
|
-
for (Size i =
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
for (Size i = used_trampolines.len - 1; i >= 0; i--) {
|
|
60
|
+
int16_t idx = used_trampolines[i];
|
|
61
|
+
TrampolineInfo *trampoline = &shared.trampolines[idx];
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
trampoline->recv.Reset();
|
|
65
|
-
}
|
|
66
|
-
}
|
|
63
|
+
RG_ASSERT(!trampoline->func.IsEmpty());
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
trampoline->func.Reset();
|
|
66
|
+
trampoline->recv.Reset();
|
|
67
|
+
|
|
68
|
+
shared.available.Append(idx);
|
|
69
|
+
}
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
instance->temporaries -= mem->temporary;
|
|
@@ -1025,19 +1026,21 @@ void CallData::PopOutArguments()
|
|
|
1025
1026
|
|
|
1026
1027
|
void *CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func)
|
|
1027
1028
|
{
|
|
1028
|
-
|
|
1029
|
+
int16_t idx;
|
|
1029
1030
|
{
|
|
1030
1031
|
std::lock_guard<std::mutex> lock(shared.mutex);
|
|
1031
1032
|
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1033
|
+
if (RG_UNLIKELY(!shared.available.len)) {
|
|
1034
|
+
ThrowError<Napi::Error>(env, "Too many callbacks are in use (max = %1)", MaxTrampolines);
|
|
1035
|
+
return env.Null();
|
|
1036
|
+
}
|
|
1037
|
+
if (RG_UNLIKELY(!used_trampolines.Available())) {
|
|
1038
|
+
ThrowError<Napi::Error>(env, "This call uses too many temporary callbacks (max = %1)", RG_LEN(used_trampolines.data));
|
|
1036
1039
|
return env.Null();
|
|
1037
1040
|
}
|
|
1038
1041
|
|
|
1039
|
-
shared.
|
|
1040
|
-
used_trampolines
|
|
1042
|
+
idx = shared.available.data[--shared.available.len];
|
|
1043
|
+
used_trampolines.Append(idx);
|
|
1041
1044
|
}
|
|
1042
1045
|
|
|
1043
1046
|
TrampolineInfo *trampoline = &shared.trampolines[idx];
|
|
@@ -1048,6 +1051,7 @@ void *CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func
|
|
|
1048
1051
|
trampoline->generation = (int32_t)mem->generation;
|
|
1049
1052
|
|
|
1050
1053
|
void *ptr = GetTrampoline(idx, proto);
|
|
1054
|
+
|
|
1051
1055
|
return ptr;
|
|
1052
1056
|
}
|
|
1053
1057
|
|
package/src/koffi/src/call.hh
CHANGED
|
@@ -41,8 +41,7 @@ class alignas(8) CallData {
|
|
|
41
41
|
Span<uint8_t> old_stack_mem;
|
|
42
42
|
Span<uint8_t> old_heap_mem;
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
LocalArray<int16_t, 16> used_trampolines;
|
|
46
45
|
LocalArray<OutArgument, MaxOutParameters> out_arguments;
|
|
47
46
|
|
|
48
47
|
uint8_t *new_sp;
|
|
@@ -112,7 +111,6 @@ private:
|
|
|
112
111
|
|
|
113
112
|
void *ReserveTrampoline(const FunctionInfo *proto, Napi::Function func);
|
|
114
113
|
};
|
|
115
|
-
RG_STATIC_ASSERT(MaxTrampolines <= 32);
|
|
116
114
|
|
|
117
115
|
template <typename T>
|
|
118
116
|
inline bool CallData::AllocStack(Size size, Size align, T **out_ptr)
|
|
@@ -165,6 +163,6 @@ inline T *CallData::AllocHeap(Size size, Size align)
|
|
|
165
163
|
}
|
|
166
164
|
}
|
|
167
165
|
|
|
168
|
-
void *GetTrampoline(
|
|
166
|
+
void *GetTrampoline(int16_t idx, const FunctionInfo *proto);
|
|
169
167
|
|
|
170
168
|
}
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -1001,6 +1001,8 @@ static Napi::Value GetTypeDefinition(const Napi::CallbackInfo &info)
|
|
|
1001
1001
|
|
|
1002
1002
|
static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, Size heap_size)
|
|
1003
1003
|
{
|
|
1004
|
+
std::lock_guard<std::mutex> lock(instance->memories_mutex);
|
|
1005
|
+
|
|
1004
1006
|
for (Size i = 1; i < instance->memories.len; i++) {
|
|
1005
1007
|
InstanceMemory *mem = instance->memories[i];
|
|
1006
1008
|
|
|
@@ -1436,19 +1438,16 @@ static Napi::Value RegisterCallback(const Napi::CallbackInfo &info)
|
|
|
1436
1438
|
return env.Null();
|
|
1437
1439
|
}
|
|
1438
1440
|
|
|
1439
|
-
|
|
1441
|
+
int16_t idx;
|
|
1440
1442
|
{
|
|
1441
1443
|
std::lock_guard<std::mutex> lock(shared.mutex);
|
|
1442
1444
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
if (RG_UNLIKELY(idx >= MaxTrampolines)) {
|
|
1446
|
-
ThrowError<Napi::Error>(env, "Too many registered callbacks are in use (max = %1)", MaxTrampolines);
|
|
1445
|
+
if (RG_UNLIKELY(!shared.available.len)) {
|
|
1446
|
+
ThrowError<Napi::Error>(env, "Too many callbacks are in use (max = %1)", MaxTrampolines);
|
|
1447
1447
|
return env.Null();
|
|
1448
1448
|
}
|
|
1449
1449
|
|
|
1450
|
-
shared.
|
|
1451
|
-
idx += MaxTrampolines;
|
|
1450
|
+
idx = shared.available.data[--shared.available.len];
|
|
1452
1451
|
}
|
|
1453
1452
|
|
|
1454
1453
|
TrampolineInfo *trampoline = &shared.trampolines[idx];
|
|
@@ -1467,6 +1466,9 @@ static Napi::Value RegisterCallback(const Napi::CallbackInfo &info)
|
|
|
1467
1466
|
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
1468
1467
|
SetValueTag(instance, external, type->ref.marker);
|
|
1469
1468
|
|
|
1469
|
+
// Cache index for fast unregistration
|
|
1470
|
+
instance->trampolines_map.Set(ptr, idx);
|
|
1471
|
+
|
|
1470
1472
|
return external;
|
|
1471
1473
|
}
|
|
1472
1474
|
|
|
@@ -1487,31 +1489,33 @@ static Napi::Value UnregisterCallback(const Napi::CallbackInfo &info)
|
|
|
1487
1489
|
Napi::External<void> external = info[0].As<Napi::External<void>>();
|
|
1488
1490
|
void *ptr = external.Data();
|
|
1489
1491
|
|
|
1490
|
-
|
|
1492
|
+
int16_t idx;
|
|
1491
1493
|
{
|
|
1492
|
-
|
|
1494
|
+
int16_t *it = instance->trampolines_map.Find(ptr);
|
|
1493
1495
|
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
+
if (RG_UNLIKELY(!it)) {
|
|
1497
|
+
ThrowError<Napi::Error>(env, "Could not find matching registered callback");
|
|
1498
|
+
return env.Null();
|
|
1499
|
+
}
|
|
1496
1500
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1501
|
+
idx = *it;
|
|
1502
|
+
instance->trampolines_map.Remove(it);
|
|
1503
|
+
}
|
|
1499
1504
|
|
|
1500
|
-
|
|
1505
|
+
// Release shared trampoline safely
|
|
1506
|
+
{
|
|
1507
|
+
std::lock_guard<std::mutex> lock(shared.mutex);
|
|
1501
1508
|
|
|
1502
|
-
|
|
1503
|
-
|
|
1509
|
+
TrampolineInfo *trampoline = &shared.trampolines[idx];
|
|
1510
|
+
RG_ASSERT(!trampoline->func.IsEmpty());
|
|
1504
1511
|
|
|
1505
|
-
|
|
1506
|
-
|
|
1512
|
+
trampoline->func.Reset();
|
|
1513
|
+
trampoline->recv.Reset();
|
|
1507
1514
|
|
|
1508
|
-
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1515
|
+
shared.available.Append(idx);
|
|
1511
1516
|
}
|
|
1512
1517
|
|
|
1513
|
-
|
|
1514
|
-
return env.Null();
|
|
1518
|
+
return env.Undefined();
|
|
1515
1519
|
}
|
|
1516
1520
|
|
|
1517
1521
|
LibraryHolder::~LibraryHolder()
|
|
@@ -1709,18 +1713,16 @@ InstanceData::~InstanceData()
|
|
|
1709
1713
|
delete mem;
|
|
1710
1714
|
}
|
|
1711
1715
|
|
|
1712
|
-
// Clean-up leftover
|
|
1716
|
+
// Clean-up leftover trampoline references
|
|
1713
1717
|
{
|
|
1714
1718
|
std::lock_guard<std::mutex> lock(shared.mutex);
|
|
1715
1719
|
|
|
1716
|
-
for (
|
|
1717
|
-
|
|
1720
|
+
for (int16_t idx = 0; idx < MaxTrampolines; idx++) {
|
|
1721
|
+
TrampolineInfo *trampoline = &shared.trampolines[idx];
|
|
1718
1722
|
|
|
1719
|
-
if (
|
|
1723
|
+
if (trampoline->func.IsEmpty())
|
|
1720
1724
|
continue;
|
|
1721
1725
|
|
|
1722
|
-
TrampolineInfo *trampoline = &shared.trampolines[idx];
|
|
1723
|
-
|
|
1724
1726
|
if (trampoline->func.Env().GetInstanceData<InstanceData>() == this) {
|
|
1725
1727
|
trampoline->func.Reset();
|
|
1726
1728
|
trampoline->recv.Reset();
|
package/src/koffi/src/ffi.hh
CHANGED
|
@@ -30,7 +30,7 @@ static const Size DefaultMaxTypeSize = Mebibytes(64);
|
|
|
30
30
|
static const int MaxAsyncCalls = 256;
|
|
31
31
|
static const Size MaxParameters = 32;
|
|
32
32
|
static const Size MaxOutParameters = 16;
|
|
33
|
-
static const Size MaxTrampolines =
|
|
33
|
+
static const Size MaxTrampolines = 1024;
|
|
34
34
|
|
|
35
35
|
extern const int TypeInfoMarker;
|
|
36
36
|
extern const int CastMarker;
|
|
@@ -247,12 +247,15 @@ struct InstanceData {
|
|
|
247
247
|
const TypeInfo *char_type;
|
|
248
248
|
const TypeInfo *char16_type;
|
|
249
249
|
|
|
250
|
+
std::mutex memories_mutex;
|
|
250
251
|
LocalArray<InstanceMemory *, 9> memories;
|
|
251
252
|
int temporaries = 0;
|
|
252
253
|
|
|
253
254
|
std::thread::id main_thread_id;
|
|
254
255
|
napi_threadsafe_function broker = nullptr;
|
|
255
256
|
|
|
257
|
+
HashMap<void *, int16_t> trampolines_map;
|
|
258
|
+
|
|
256
259
|
BlockAllocator str_alloc;
|
|
257
260
|
|
|
258
261
|
Size sync_stack_size = DefaultSyncStackSize;
|
|
@@ -266,7 +269,6 @@ struct InstanceData {
|
|
|
266
269
|
RG_STATIC_ASSERT(DefaultResidentAsyncPools <= RG_LEN(InstanceData::memories.data) - 1);
|
|
267
270
|
RG_STATIC_ASSERT(DefaultMaxAsyncCalls >= DefaultResidentAsyncPools);
|
|
268
271
|
RG_STATIC_ASSERT(MaxAsyncCalls >= DefaultMaxAsyncCalls);
|
|
269
|
-
RG_STATIC_ASSERT(MaxTrampolines <= 16);
|
|
270
272
|
|
|
271
273
|
struct TrampolineInfo {
|
|
272
274
|
const FunctionInfo *proto;
|
|
@@ -279,10 +281,19 @@ struct TrampolineInfo {
|
|
|
279
281
|
struct SharedData {
|
|
280
282
|
std::mutex mutex;
|
|
281
283
|
|
|
282
|
-
TrampolineInfo trampolines[MaxTrampolines
|
|
283
|
-
|
|
284
|
-
|
|
284
|
+
TrampolineInfo trampolines[MaxTrampolines];
|
|
285
|
+
LocalArray<int16_t, MaxTrampolines> available;
|
|
286
|
+
|
|
287
|
+
SharedData()
|
|
288
|
+
{
|
|
289
|
+
available.len = MaxTrampolines;
|
|
290
|
+
|
|
291
|
+
for (int16_t i = 0; i < MaxTrampolines; i++) {
|
|
292
|
+
available[i] = i;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
285
295
|
};
|
|
296
|
+
RG_STATIC_ASSERT(MaxTrampolines <= INT16_MAX);
|
|
286
297
|
|
|
287
298
|
extern SharedData shared;
|
|
288
299
|
|
package/src/koffi/src/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
// This program is free software: you can redistribute it and/or modify
|
|
4
2
|
// it under the terms of the GNU Affero General Public License as published by
|
|
5
3
|
// the Free Software Foundation, either version 3 of the License, or
|
|
@@ -15,6 +13,9 @@
|
|
|
15
13
|
|
|
16
14
|
'use strict';
|
|
17
15
|
|
|
16
|
+
if (process.versions.napi == null || process.versions.napi < 8)
|
|
17
|
+
throw new Error('This platform does not support N-API 8');
|
|
18
|
+
|
|
18
19
|
const util = require('util');
|
|
19
20
|
|
|
20
21
|
let filename = __dirname + '/../build/koffi.node';
|
|
@@ -75,8 +75,7 @@ async function test() {
|
|
|
75
75
|
const ApplyStruct = lib.func('int ApplyStruct(int x, StructCallbacks callbacks)');
|
|
76
76
|
const SetIndirect = lib.func('void SetIndirect(IntCallback *func)');
|
|
77
77
|
const CallIndirect = lib.func('int CallIndirect(int x)');
|
|
78
|
-
const
|
|
79
|
-
const CallDirectThreaded = lib.func('int CallDirectThreaded(IntCallback *func, int x)');
|
|
78
|
+
const CallThreaded = lib.func('int CallThreaded(IntCallback *func, int x)');
|
|
80
79
|
const MakeVectors = lib.func('int MakeVectors(int len, VectorCallback *func)');
|
|
81
80
|
const CallQSort = lib.func('void CallQSort(_Inout_ void *base, size_t nmemb, size_t size, SortCallback *cb)');
|
|
82
81
|
const CallMeChar = lib.func('int CallMeChar(CharCallback *func)');
|
|
@@ -263,16 +262,18 @@ async function test() {
|
|
|
263
262
|
assert.equal(ret, 97 + 2 * 98);
|
|
264
263
|
}
|
|
265
264
|
|
|
266
|
-
// Use
|
|
267
|
-
for (let i = 0; i <
|
|
268
|
-
assert.equal(await util.promisify(CallDirectThreaded.async)(x => -x - 2, 27), -29);
|
|
269
|
-
|
|
270
|
-
// Use registered callback from secondary thread
|
|
271
|
-
for (let i = 0; i < 128; i++) {
|
|
265
|
+
// Use callbacks from secondary threads
|
|
266
|
+
for (let i = 0; i < 1024; i++) {
|
|
272
267
|
let cb = koffi.register(x => -x - 2, koffi.pointer(IntCallback));
|
|
273
|
-
|
|
274
268
|
SetIndirect(cb);
|
|
275
|
-
|
|
269
|
+
|
|
270
|
+
let results = await Promise.all([
|
|
271
|
+
util.promisify(CallThreaded.async)(x => -x - 4, 27),
|
|
272
|
+
util.promisify(CallThreaded.async)(null, 27)
|
|
273
|
+
]);
|
|
274
|
+
|
|
275
|
+
assert.equal(results[0], -31);
|
|
276
|
+
assert.equal(results[1], -29);
|
|
276
277
|
|
|
277
278
|
koffi.unregister(cb);
|
|
278
279
|
}
|
package/src/koffi/test/misc.c
CHANGED
|
@@ -681,17 +681,27 @@ EXPORT int CallIndirect(int x)
|
|
|
681
681
|
|
|
682
682
|
#ifdef _WIN32
|
|
683
683
|
|
|
684
|
-
|
|
684
|
+
typedef struct CallContext {
|
|
685
|
+
IntCallback *callback;
|
|
686
|
+
int *ptr;
|
|
687
|
+
} CallContext;
|
|
688
|
+
|
|
689
|
+
static DWORD WINAPI CallThreadedFunc(void *udata)
|
|
685
690
|
{
|
|
686
|
-
|
|
687
|
-
*ptr = callback(*ptr);
|
|
691
|
+
CallContext *ctx = (CallContext *)udata;
|
|
692
|
+
*ctx->ptr = ctx->callback(*ctx->ptr);
|
|
688
693
|
|
|
689
694
|
return 0;
|
|
690
695
|
}
|
|
691
696
|
|
|
692
|
-
EXPORT int
|
|
697
|
+
EXPORT int CallThreaded(IntCallback *func, int x)
|
|
693
698
|
{
|
|
694
|
-
|
|
699
|
+
CallContext ctx;
|
|
700
|
+
|
|
701
|
+
ctx.callback = func ? func : callback;
|
|
702
|
+
ctx.ptr = &x;
|
|
703
|
+
|
|
704
|
+
HANDLE h = CreateThread(NULL, 0, CallThreadedFunc, &ctx, 0, NULL);
|
|
695
705
|
if (!h) {
|
|
696
706
|
perror("CreateThread");
|
|
697
707
|
exit(1);
|
|
@@ -705,19 +715,28 @@ EXPORT int CallIndirectThreaded(int x)
|
|
|
705
715
|
|
|
706
716
|
#else
|
|
707
717
|
|
|
708
|
-
|
|
718
|
+
typedef struct CallContext {
|
|
719
|
+
IntCallback *callback;
|
|
720
|
+
int *ptr;
|
|
721
|
+
} CallContext;
|
|
722
|
+
|
|
723
|
+
static void *CallThreadedFunc(void *udata)
|
|
709
724
|
{
|
|
710
|
-
|
|
711
|
-
*ptr = callback(*ptr);
|
|
725
|
+
CallContext *ctx = (CallContext *)udata;
|
|
726
|
+
*ctx->ptr = ctx->callback(*ctx->ptr);
|
|
712
727
|
|
|
713
728
|
return NULL;
|
|
714
729
|
}
|
|
715
730
|
|
|
716
|
-
EXPORT int
|
|
731
|
+
EXPORT int CallThreaded(IntCallback *func, int x)
|
|
717
732
|
{
|
|
718
|
-
|
|
733
|
+
CallContext ctx;
|
|
719
734
|
|
|
720
|
-
|
|
735
|
+
ctx.callback = func ? func : callback;
|
|
736
|
+
ctx.ptr = &x;
|
|
737
|
+
|
|
738
|
+
pthread_t thread;
|
|
739
|
+
if (pthread_create(&thread, NULL, CallThreadedFunc, &ctx)) {
|
|
721
740
|
perror("pthread_create");
|
|
722
741
|
exit(1);
|
|
723
742
|
}
|
|
@@ -729,12 +748,6 @@ EXPORT int CallIndirectThreaded(int x)
|
|
|
729
748
|
|
|
730
749
|
#endif
|
|
731
750
|
|
|
732
|
-
EXPORT int CallDirectThreaded(IntCallback *func, int x)
|
|
733
|
-
{
|
|
734
|
-
callback = func;
|
|
735
|
-
return CallIndirectThreaded(x);
|
|
736
|
-
}
|
|
737
|
-
|
|
738
751
|
EXPORT void ReverseBytes(void *p, int len)
|
|
739
752
|
{
|
|
740
753
|
uint8_t *bytes = (uint8_t *)p;
|
|
File without changes
|
|
@@ -342,7 +342,7 @@ async function prepare() {
|
|
|
342
342
|
log(machine, `${suite} > Status`, chalk.bold.red(`[manual]`));
|
|
343
343
|
needed = true;
|
|
344
344
|
} else {
|
|
345
|
-
log(machine, `${suite} > Status`, chalk.bold.red(`[
|
|
345
|
+
log(machine, `${suite} > Status`, chalk.bold.red(`[missing]`));
|
|
346
346
|
needed = true;
|
|
347
347
|
}
|
|
348
348
|
}
|
|
@@ -494,6 +494,7 @@ async function prepare() {
|
|
|
494
494
|
fs.renameSync(dist_dir + '/src/koffi/LICENSE.txt', dist_dir + '/LICENSE.txt');
|
|
495
495
|
fs.renameSync(dist_dir + '/src/koffi/ChangeLog.md', dist_dir + '/ChangeLog.md');
|
|
496
496
|
fs.renameSync(dist_dir + '/web/koffi.dev', dist_dir + '/doc');
|
|
497
|
+
fs.rmdirSync(dist_dir + '/web');
|
|
497
498
|
}
|
|
498
499
|
|
|
499
500
|
return dist_dir;
|
|
@@ -514,6 +515,8 @@ function snapshot() {
|
|
|
514
515
|
} else if (parts[0] == 'src') {
|
|
515
516
|
return parts[1] == null || parts[1] == 'cnoke' ||
|
|
516
517
|
parts[1] == 'koffi';
|
|
518
|
+
} else if (parts[0] == 'tools') {
|
|
519
|
+
return parts[1] == null || parts[1] != 'qemu';
|
|
517
520
|
} else if (parts[0] == 'vendor') {
|
|
518
521
|
return parts[1] == null || parts[1] == 'brotli' ||
|
|
519
522
|
parts[1] == 'dragonbox' ||
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
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
|
+
import argparse
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
def write_asm_trampolines(filename, comment_char, n,
|
|
20
|
+
fmt_export, fmt_export_x, fmt_proc, fmt_proc_x, end = None):
|
|
21
|
+
with open(filename) as f:
|
|
22
|
+
lines = f.readlines()
|
|
23
|
+
|
|
24
|
+
with open(filename, 'w') as f:
|
|
25
|
+
for line in lines:
|
|
26
|
+
if line.rstrip() == comment_char + ' Trampolines':
|
|
27
|
+
break
|
|
28
|
+
f.write(line)
|
|
29
|
+
|
|
30
|
+
print(comment_char + ' Trampolines', file = f)
|
|
31
|
+
print(comment_char + ' ----------------------------', file = f)
|
|
32
|
+
print('', file = f)
|
|
33
|
+
|
|
34
|
+
for i in range(0, n):
|
|
35
|
+
print(fmt_export.format(i), file = f)
|
|
36
|
+
print('', file = f)
|
|
37
|
+
for i in range(0, n):
|
|
38
|
+
print(fmt_export_x.format(i), file = f)
|
|
39
|
+
print('', file = f)
|
|
40
|
+
|
|
41
|
+
for i in range(0, n):
|
|
42
|
+
print(fmt_proc.format(i), file = f)
|
|
43
|
+
print('', file = f)
|
|
44
|
+
for i in range(0, n):
|
|
45
|
+
print(fmt_proc_x.format(i), file = f)
|
|
46
|
+
|
|
47
|
+
if end is not None:
|
|
48
|
+
print('', file = f)
|
|
49
|
+
print(end, file = f)
|
|
50
|
+
|
|
51
|
+
def write_cxx_trampolines(filename, n):
|
|
52
|
+
with open(filename) as f:
|
|
53
|
+
lines = f.readlines()
|
|
54
|
+
|
|
55
|
+
with open(filename, 'w') as f:
|
|
56
|
+
for line in lines:
|
|
57
|
+
if not line.startswith('//'):
|
|
58
|
+
break
|
|
59
|
+
f.write(line)
|
|
60
|
+
|
|
61
|
+
print('', file = f)
|
|
62
|
+
for i in range(0, n):
|
|
63
|
+
print('extern "C" int Trampoline{0}; extern "C" int TrampolineX{0};'.format(i), file = f)
|
|
64
|
+
|
|
65
|
+
print('', file = f)
|
|
66
|
+
print('static void *const Trampolines[][2] = {', file = f)
|
|
67
|
+
for i in range(0, n):
|
|
68
|
+
if i + 1 < n:
|
|
69
|
+
print(' {{ &Trampoline{0}, &TrampolineX{0} }},'.format(i), file = f)
|
|
70
|
+
else:
|
|
71
|
+
print(' {{ &Trampoline{0}, &TrampolineX{0} }}'.format(i), file = f)
|
|
72
|
+
print('};', file = f)
|
|
73
|
+
print('RG_STATIC_ASSERT(RG_LEN(Trampolines) == MaxTrampolines);', file = f)
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
parser = argparse.ArgumentParser(description = 'Generate static trampolines')
|
|
77
|
+
parser.add_argument('n', metavar = 'n', type = int, help = 'Number of trampolines')
|
|
78
|
+
args = parser.parse_args()
|
|
79
|
+
|
|
80
|
+
src_dir = os.path.dirname(__file__) + '/../src'
|
|
81
|
+
|
|
82
|
+
write_asm_trampolines(src_dir + '/abi_arm32_fwd.S', '#', args.n,
|
|
83
|
+
'.global Trampoline{0}',
|
|
84
|
+
'.global TrampolineX{0}',
|
|
85
|
+
'Trampoline{0}:\n trampoline {0}',
|
|
86
|
+
'TrampolineX{0}:\n trampoline_vec {0}'
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
write_asm_trampolines(src_dir + '/abi_arm64_fwd.asm', ';', args.n,
|
|
90
|
+
' EXPORT Trampoline{0}',
|
|
91
|
+
' EXPORT TrampolineX{0}',
|
|
92
|
+
'Trampoline{0} PROC\n trampoline {0}\n ENDP',
|
|
93
|
+
'TrampolineX{0} PROC\n trampoline_vec {0}\n ENDP',
|
|
94
|
+
' END'
|
|
95
|
+
)
|
|
96
|
+
write_asm_trampolines(src_dir + '/abi_arm64_fwd.S', '#', args.n,
|
|
97
|
+
'.global SYMBOL(Trampoline{0})',
|
|
98
|
+
'.global SYMBOL(TrampolineX{0})',
|
|
99
|
+
'SYMBOL(Trampoline{0}):\n trampoline {0}',
|
|
100
|
+
'SYMBOL(TrampolineX{0}):\n trampoline_vec {0}'
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
write_asm_trampolines(src_dir + '/abi_riscv64_fwd.S', '#', args.n,
|
|
104
|
+
'.global Trampoline{0}',
|
|
105
|
+
'.global TrampolineX{0}',
|
|
106
|
+
'Trampoline{0}:\n trampoline {0}',
|
|
107
|
+
'TrampolineX{0}:\n trampoline_vec {0}'
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
write_asm_trampolines(src_dir + '/abi_x64_sysv_fwd.S', '#', args.n,
|
|
111
|
+
'.global SYMBOL(Trampoline{0})',
|
|
112
|
+
'.global SYMBOL(TrampolineX{0})',
|
|
113
|
+
'SYMBOL(Trampoline{0}):\n trampoline {0}',
|
|
114
|
+
'SYMBOL(TrampolineX{0}):\n trampoline_xmm {0}'
|
|
115
|
+
)
|
|
116
|
+
write_asm_trampolines(src_dir + '/abi_x64_win_fwd.asm', ';', args.n,
|
|
117
|
+
'public Trampoline{0}',
|
|
118
|
+
'public TrampolineX{0}',
|
|
119
|
+
'Trampoline{0} proc frame\n trampoline {0}\nTrampoline{0} endp',
|
|
120
|
+
'TrampolineX{0} proc frame\n trampoline_xmm {0}\nTrampolineX{0} endp',
|
|
121
|
+
'end'
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
write_asm_trampolines(src_dir + '/abi_x86_fwd.asm', ';', args.n,
|
|
125
|
+
'public Trampoline{0}',
|
|
126
|
+
'public TrampolineX{0}',
|
|
127
|
+
'Trampoline{0} proc\n trampoline {0}\nTrampoline{0} endp',
|
|
128
|
+
'TrampolineX{0} proc\n trampoline_x87 {0}\nTrampolineX{0} endp',
|
|
129
|
+
'end'
|
|
130
|
+
)
|
|
131
|
+
write_asm_trampolines(src_dir + '/abi_x86_fwd.S', '#', args.n,
|
|
132
|
+
'.global Trampoline{0}',
|
|
133
|
+
'.global TrampolineX{0}',
|
|
134
|
+
'Trampoline{0}:\n trampoline {0}',
|
|
135
|
+
'TrampolineX{0}:\n trampoline_x87 {0}'
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
write_cxx_trampolines(src_dir + '/abi_trampolines.inc', args.n)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|