koffi 1.0.1 → 1.0.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.
- package/CMakeLists.txt +12 -11
- package/README.md +23 -20
- package/build/qemu/1.0.4/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_win32_x64.tar.gz +0 -0
- package/package.json +8 -4
- package/qemu/qemu.js +794 -0
- package/qemu/registry/machines.json +415 -0
- package/qemu/registry/sha256sum.txt +45 -0
- package/src/{call_arm32.cc → abi_arm32.cc} +153 -219
- package/src/{call_arm32_fwd.S → abi_arm32_fwd.S} +0 -0
- package/src/{call_arm64.cc → abi_arm64.cc} +130 -123
- package/src/{call_arm64_fwd.S → abi_arm64_fwd.S} +0 -0
- package/src/{call_x64_sysv.cc → abi_x64_sysv.cc} +138 -135
- package/src/{call_x64_sysv_fwd.S → abi_x64_sysv_fwd.S} +0 -0
- package/src/{call_x64_win.cc → abi_x64_win.cc} +107 -99
- package/src/{call_x64_win_fwd.asm → abi_x64_win_fwd.asm} +0 -0
- package/src/{call_x86.cc → abi_x86.cc} +110 -107
- package/src/{call_x86_fwd.S → abi_x86_fwd.S} +0 -0
- package/src/{call_x86_fwd.asm → abi_x86_fwd.asm} +0 -0
- package/src/call.cc +353 -0
- package/src/call.hh +132 -4
- package/src/ffi.cc +16 -2
- package/src/ffi.hh +8 -12
- package/src/util.cc +7 -280
- package/src/util.hh +0 -107
- package/test/CMakeLists.txt +1 -0
- package/test/misc.c +355 -0
- package/test/misc.def +3 -0
- package/test/misc.js +227 -0
- package/test/raylib.js +165 -0
- package/test/sqlite.js +104 -0
- package/vendor/libcc/libcc.hh +1 -1
- package/build/qemu/1.0.1/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_win32_x64.tar.gz +0 -0
package/src/util.cc
CHANGED
|
@@ -56,6 +56,13 @@ const TypeInfo *ResolveType(const InstanceData *instance, Napi::Value value, int
|
|
|
56
56
|
|
|
57
57
|
const TypeInfo *GetPointerType(InstanceData *instance, const TypeInfo *ref)
|
|
58
58
|
{
|
|
59
|
+
// Special cases
|
|
60
|
+
if (TestStr(ref->name, "char")) {
|
|
61
|
+
return instance->types_map.FindValue("string", nullptr);
|
|
62
|
+
} else if (TestStr(ref->name, "char16") || TestStr(ref->name, "char16_t")) {
|
|
63
|
+
return instance->types_map.FindValue("string16", nullptr);
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
char name_buf[256];
|
|
60
67
|
Fmt(name_buf, "%1%2*", ref->name, ref->primitive == PrimitiveKind::Pointer ? "" : " ");
|
|
61
68
|
|
|
@@ -119,284 +126,4 @@ bool CheckValueTag(const InstanceData *instance, Napi::Value value, const void *
|
|
|
119
126
|
return match;
|
|
120
127
|
}
|
|
121
128
|
|
|
122
|
-
CallData::CallData(Napi::Env env, InstanceData *instance, const FunctionInfo *func)
|
|
123
|
-
: env(env), instance(instance), func(func),
|
|
124
|
-
stack_mem(&instance->stack_mem), heap_mem(&instance->heap_mem),
|
|
125
|
-
old_stack_mem(instance->stack_mem), old_heap_mem(instance->heap_mem)
|
|
126
|
-
{
|
|
127
|
-
RG_ASSERT(AlignUp(stack_mem->ptr, 16) == stack_mem->ptr);
|
|
128
|
-
RG_ASSERT(AlignUp(stack_mem->end(), 16) == stack_mem->end());
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
CallData::~CallData()
|
|
132
|
-
{
|
|
133
|
-
instance->stack_mem = old_stack_mem;
|
|
134
|
-
instance->heap_mem = old_heap_mem;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const char *CallData::PushString(const Napi::Value &value)
|
|
138
|
-
{
|
|
139
|
-
RG_ASSERT(value.IsString());
|
|
140
|
-
|
|
141
|
-
Napi::Env env = value.Env();
|
|
142
|
-
|
|
143
|
-
Span<char> buf;
|
|
144
|
-
size_t len = 0;
|
|
145
|
-
napi_status status;
|
|
146
|
-
|
|
147
|
-
buf.ptr = (char *)heap_mem->ptr;
|
|
148
|
-
buf.len = std::max((Size)0, heap_mem->len - Kibibytes(32));
|
|
149
|
-
|
|
150
|
-
status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
151
|
-
RG_ASSERT(status == napi_ok);
|
|
152
|
-
|
|
153
|
-
len++;
|
|
154
|
-
|
|
155
|
-
if (RG_LIKELY(len < (size_t)buf.len)) {
|
|
156
|
-
heap_mem->ptr += (Size)len;
|
|
157
|
-
heap_mem->len -= (Size)len;
|
|
158
|
-
} else {
|
|
159
|
-
status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
|
|
160
|
-
RG_ASSERT(status == napi_ok);
|
|
161
|
-
|
|
162
|
-
len++;
|
|
163
|
-
|
|
164
|
-
buf.ptr = (char *)Allocator::Allocate(&big_alloc, (Size)len);
|
|
165
|
-
buf.len = (Size)len;
|
|
166
|
-
|
|
167
|
-
status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
168
|
-
RG_ASSERT(status == napi_ok);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return buf.ptr;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest)
|
|
175
|
-
{
|
|
176
|
-
Napi::Env env = obj.Env();
|
|
177
|
-
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
178
|
-
|
|
179
|
-
RG_ASSERT(IsObject(obj));
|
|
180
|
-
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
181
|
-
|
|
182
|
-
for (const RecordMember &member: type->members) {
|
|
183
|
-
Napi::Value value = obj.Get(member.name);
|
|
184
|
-
|
|
185
|
-
if (RG_UNLIKELY(value.IsUndefined())) {
|
|
186
|
-
ThrowError<Napi::TypeError>(env, "Missing expected object property '%1'", member.name);
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
dest = AlignUp(dest, member.align);
|
|
191
|
-
|
|
192
|
-
switch (member.type->primitive) {
|
|
193
|
-
case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
|
|
194
|
-
|
|
195
|
-
case PrimitiveKind::Bool: {
|
|
196
|
-
if (RG_UNLIKELY(!value.IsBoolean())) {
|
|
197
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected boolean", GetValueType(instance, value), member.name);
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
bool b = value.As<Napi::Boolean>();
|
|
202
|
-
*(bool *)dest = b;
|
|
203
|
-
} break;
|
|
204
|
-
|
|
205
|
-
case PrimitiveKind::Int8:
|
|
206
|
-
case PrimitiveKind::UInt8:
|
|
207
|
-
case PrimitiveKind::Int16:
|
|
208
|
-
case PrimitiveKind::UInt16:
|
|
209
|
-
case PrimitiveKind::Int32:
|
|
210
|
-
case PrimitiveKind::UInt32:
|
|
211
|
-
case PrimitiveKind::Int64:
|
|
212
|
-
case PrimitiveKind::UInt64: {
|
|
213
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
214
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
215
|
-
return false;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
int64_t v = CopyNumber<int64_t>(value);
|
|
219
|
-
memcpy(dest, &v, member.type->size); // Little Endian
|
|
220
|
-
} break;
|
|
221
|
-
case PrimitiveKind::Float32: {
|
|
222
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
223
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
float f = CopyNumber<float>(value);
|
|
228
|
-
memcpy(dest, &f, 4);
|
|
229
|
-
} break;
|
|
230
|
-
case PrimitiveKind::Float64: {
|
|
231
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
232
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
233
|
-
return false;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
double d = CopyNumber<double>(value);
|
|
237
|
-
memcpy(dest, &d, 8);
|
|
238
|
-
} break;
|
|
239
|
-
case PrimitiveKind::String: {
|
|
240
|
-
if (RG_UNLIKELY(!value.IsString())) {
|
|
241
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected string", GetValueType(instance, value), member.name);
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const char *str = PushString(value);
|
|
246
|
-
if (RG_UNLIKELY(!str))
|
|
247
|
-
return false;
|
|
248
|
-
*(const char **)dest = str;
|
|
249
|
-
} break;
|
|
250
|
-
case PrimitiveKind::Pointer: {
|
|
251
|
-
if (RG_UNLIKELY(!CheckValueTag(instance, value, member.type))) {
|
|
252
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected %3", GetValueType(instance, value), member.name, member.type->name);
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
Napi::External external = value.As<Napi::External<void>>();
|
|
257
|
-
void *ptr = external.Data();
|
|
258
|
-
*(void **)dest = ptr;
|
|
259
|
-
} break;
|
|
260
|
-
|
|
261
|
-
case PrimitiveKind::Record: {
|
|
262
|
-
if (RG_UNLIKELY(!IsObject(value))) {
|
|
263
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected object", GetValueType(instance, value), member.name);
|
|
264
|
-
return false;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
Napi::Object obj = value.As<Napi::Object>();
|
|
268
|
-
if (!PushObject(obj, member.type, dest))
|
|
269
|
-
return false;
|
|
270
|
-
} break;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
dest += member.type->size;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return true;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
void PopObject(Napi::Object obj, const uint8_t *ptr, const TypeInfo *type)
|
|
280
|
-
{
|
|
281
|
-
Napi::Env env = obj.Env();
|
|
282
|
-
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
283
|
-
|
|
284
|
-
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
285
|
-
|
|
286
|
-
for (const RecordMember &member: type->members) {
|
|
287
|
-
ptr = AlignUp(ptr, member.align);
|
|
288
|
-
|
|
289
|
-
switch (member.type->primitive) {
|
|
290
|
-
case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
|
|
291
|
-
|
|
292
|
-
case PrimitiveKind::Bool: {
|
|
293
|
-
bool b = *(bool *)ptr;
|
|
294
|
-
obj.Set(member.name, Napi::Boolean::New(env, b));
|
|
295
|
-
} break;
|
|
296
|
-
case PrimitiveKind::Int8: {
|
|
297
|
-
double d = (double)*(int8_t *)ptr;
|
|
298
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
299
|
-
} break;
|
|
300
|
-
case PrimitiveKind::UInt8: {
|
|
301
|
-
double d = (double)*(uint8_t *)ptr;
|
|
302
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
303
|
-
} break;
|
|
304
|
-
case PrimitiveKind::Int16: {
|
|
305
|
-
double d = (double)*(int16_t *)ptr;
|
|
306
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
307
|
-
} break;
|
|
308
|
-
case PrimitiveKind::UInt16: {
|
|
309
|
-
double d = (double)*(uint16_t *)ptr;
|
|
310
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
311
|
-
} break;
|
|
312
|
-
case PrimitiveKind::Int32: {
|
|
313
|
-
double d = (double)*(int32_t *)ptr;
|
|
314
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
315
|
-
} break;
|
|
316
|
-
case PrimitiveKind::UInt32: {
|
|
317
|
-
double d = (double)*(uint32_t *)ptr;
|
|
318
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
319
|
-
} break;
|
|
320
|
-
case PrimitiveKind::Int64: {
|
|
321
|
-
int64_t v = *(int64_t *)ptr;
|
|
322
|
-
obj.Set(member.name, Napi::BigInt::New(env, v));
|
|
323
|
-
} break;
|
|
324
|
-
case PrimitiveKind::UInt64: {
|
|
325
|
-
uint64_t v = *(uint64_t *)ptr;
|
|
326
|
-
obj.Set(member.name, Napi::BigInt::New(env, v));
|
|
327
|
-
} break;
|
|
328
|
-
case PrimitiveKind::Float32: {
|
|
329
|
-
float f;
|
|
330
|
-
memcpy(&f, ptr, 4);
|
|
331
|
-
obj.Set(member.name, Napi::Number::New(env, (double)f));
|
|
332
|
-
} break;
|
|
333
|
-
case PrimitiveKind::Float64: {
|
|
334
|
-
double d;
|
|
335
|
-
memcpy(&d, ptr, 8);
|
|
336
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
337
|
-
} break;
|
|
338
|
-
case PrimitiveKind::String: {
|
|
339
|
-
const char *str = *(const char **)ptr;
|
|
340
|
-
obj.Set(member.name, Napi::String::New(env, str));
|
|
341
|
-
} break;
|
|
342
|
-
case PrimitiveKind::Pointer: {
|
|
343
|
-
void *ptr2 = *(void **)ptr;
|
|
344
|
-
|
|
345
|
-
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
346
|
-
SetValueTag(instance, external, member.type);
|
|
347
|
-
|
|
348
|
-
obj.Set(member.name, external);
|
|
349
|
-
} break;
|
|
350
|
-
|
|
351
|
-
case PrimitiveKind::Record: {
|
|
352
|
-
Napi::Object obj2 = PopObject(env, ptr, member.type);
|
|
353
|
-
obj.Set(member.name, obj2);
|
|
354
|
-
} break;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
ptr += member.type->size;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
void PopOutArguments(Span<const OutObject> objects)
|
|
362
|
-
{
|
|
363
|
-
for (const OutObject &obj: objects) {
|
|
364
|
-
PopObject(obj.obj, obj.ptr, obj.type);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
static void DumpMemory(const char *type, Span<const uint8_t> bytes)
|
|
369
|
-
{
|
|
370
|
-
if (bytes.len) {
|
|
371
|
-
PrintLn(stderr, "%1 at 0x%2 (%3):", type, bytes.ptr, FmtMemSize(bytes.len));
|
|
372
|
-
|
|
373
|
-
for (const uint8_t *ptr = bytes.begin(); ptr < bytes.end();) {
|
|
374
|
-
Print(stderr, " [0x%1 %2 %3] ", FmtArg(ptr).Pad0(-16),
|
|
375
|
-
FmtArg((ptr - bytes.begin()) / sizeof(void *)).Pad(-4),
|
|
376
|
-
FmtArg(ptr - bytes.begin()).Pad(-4));
|
|
377
|
-
for (int i = 0; ptr < bytes.end() && i < (int)sizeof(void *); i++, ptr++) {
|
|
378
|
-
Print(stderr, " %1", FmtHex(*ptr).Pad0(-2));
|
|
379
|
-
}
|
|
380
|
-
PrintLn(stderr);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
void CallData::DumpDebug() const
|
|
386
|
-
{
|
|
387
|
-
PrintLn(stderr, "%!..+---- %1 (%2) ----%!0", func->name, CallConventionNames[(int)func->convention]);
|
|
388
|
-
|
|
389
|
-
if (func->parameters.len) {
|
|
390
|
-
PrintLn(stderr, "Parameters:");
|
|
391
|
-
for (Size i = 0; i < func->parameters.len; i++) {
|
|
392
|
-
const ParameterInfo ¶m = func->parameters[i];
|
|
393
|
-
PrintLn(stderr, " %1 = %2 (%3)", i, param.type->name, FmtMemSize(param.type->size));
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
PrintLn(stderr, "Return: %1 (%2)", func->ret.type->name, FmtMemSize(func->ret.type->size));
|
|
397
|
-
|
|
398
|
-
DumpMemory("Stack", GetStack());
|
|
399
|
-
DumpMemory("Heap", GetHeap());
|
|
400
|
-
}
|
|
401
|
-
|
|
402
129
|
}
|
package/src/util.hh
CHANGED
|
@@ -72,97 +72,6 @@ static inline bool IsObject(Napi::Value value)
|
|
|
72
72
|
return value.IsObject() && !IsNullOrUndefined(value) && !value.IsArray();
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
class CallData {
|
|
76
|
-
Napi::Env env;
|
|
77
|
-
InstanceData *instance;
|
|
78
|
-
const FunctionInfo *func;
|
|
79
|
-
|
|
80
|
-
Span<uint8_t> *stack_mem;
|
|
81
|
-
Span<uint8_t> *heap_mem;
|
|
82
|
-
BlockAllocator big_alloc;
|
|
83
|
-
|
|
84
|
-
Span<uint8_t> old_stack_mem;
|
|
85
|
-
Span<uint8_t> old_heap_mem;
|
|
86
|
-
|
|
87
|
-
public:
|
|
88
|
-
CallData(Napi::Env env, InstanceData *instance, const FunctionInfo *func);
|
|
89
|
-
~CallData();
|
|
90
|
-
|
|
91
|
-
Span<uint8_t> GetStack() const
|
|
92
|
-
{
|
|
93
|
-
uint8_t *sp = stack_mem->end();
|
|
94
|
-
Size len = old_stack_mem.end() - sp;
|
|
95
|
-
|
|
96
|
-
return MakeSpan(sp, len);
|
|
97
|
-
}
|
|
98
|
-
uint8_t *GetSP() const { return stack_mem->end(); };
|
|
99
|
-
|
|
100
|
-
Span<uint8_t> GetHeap() const
|
|
101
|
-
{
|
|
102
|
-
uint8_t *ptr = old_heap_mem.ptr;
|
|
103
|
-
Size len = heap_mem->ptr - ptr;
|
|
104
|
-
|
|
105
|
-
return MakeSpan(ptr, len);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
template <typename T = void>
|
|
109
|
-
bool AllocStack(Size size, Size align, T **out_ptr = nullptr);
|
|
110
|
-
template <typename T = void>
|
|
111
|
-
bool AllocHeap(Size size, Size align, T **out_ptr = nullptr);
|
|
112
|
-
|
|
113
|
-
const char *PushString(const Napi::Value &value);
|
|
114
|
-
bool PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest);
|
|
115
|
-
|
|
116
|
-
void DumpDebug() const;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
template <typename T>
|
|
120
|
-
bool CallData::AllocStack(Size size, Size align, T **out_ptr)
|
|
121
|
-
{
|
|
122
|
-
uint8_t *ptr = AlignDown(stack_mem->end() - size, align);
|
|
123
|
-
Size delta = stack_mem->end() - ptr;
|
|
124
|
-
|
|
125
|
-
if (RG_UNLIKELY(stack_mem->len < delta)) {
|
|
126
|
-
ThrowError<Napi::Error>(env, "FFI call is taking up too much memory");
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (instance->debug) {
|
|
131
|
-
memset(ptr, 0, delta);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
stack_mem->len -= delta;
|
|
135
|
-
|
|
136
|
-
if (out_ptr) {
|
|
137
|
-
*out_ptr = (T *)ptr;
|
|
138
|
-
}
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
template <typename T>
|
|
143
|
-
bool CallData::AllocHeap(Size size, Size align, T **out_ptr)
|
|
144
|
-
{
|
|
145
|
-
uint8_t *ptr = AlignUp(heap_mem->ptr, align);
|
|
146
|
-
Size delta = size + (ptr - heap_mem->ptr);
|
|
147
|
-
|
|
148
|
-
if (RG_UNLIKELY(delta > heap_mem->len)) {
|
|
149
|
-
ThrowError<Napi::Error>(env, "FFI call is taking up too much memory");
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (instance->debug) {
|
|
154
|
-
memset(heap_mem->ptr, 0, (size_t)delta);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
heap_mem->ptr += delta;
|
|
158
|
-
heap_mem->len -= delta;
|
|
159
|
-
|
|
160
|
-
if (out_ptr) {
|
|
161
|
-
*out_ptr = (T *)ptr;
|
|
162
|
-
}
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
75
|
template <typename T>
|
|
167
76
|
T CopyNumber(const Napi::Value &value)
|
|
168
77
|
{
|
|
@@ -180,20 +89,4 @@ T CopyNumber(const Napi::Value &value)
|
|
|
180
89
|
RG_UNREACHABLE();
|
|
181
90
|
}
|
|
182
91
|
|
|
183
|
-
void PopObject(Napi::Object obj, const uint8_t *ptr, const TypeInfo *type);
|
|
184
|
-
static inline Napi::Object PopObject(Napi::Env env, const uint8_t *ptr, const TypeInfo *type)
|
|
185
|
-
{
|
|
186
|
-
Napi::Object obj = Napi::Object::New(env);
|
|
187
|
-
PopObject(obj, ptr, type);
|
|
188
|
-
return obj;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
struct OutObject {
|
|
192
|
-
Napi::Object obj;
|
|
193
|
-
const uint8_t *ptr;
|
|
194
|
-
const TypeInfo *type;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
void PopOutArguments(Span<const OutObject> objects);
|
|
198
|
-
|
|
199
92
|
}
|